diff --git a/.cirrus.yml b/.cirrus.yml index 917859dad2b81..f2db9f81aa50d 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -14,7 +14,7 @@ task: - pkg install -y autoconf bison gmake re2c icu libiconv png freetype2 enchant2 bzip2 krb5 t1lib gmp tidyp libsodium libzip libxml2 libxslt openssl oniguruma pkgconf webp libavif script: - ./buildconf -f - - ./configure --prefix=/usr/local --enable-debug --enable-option-checking=fatal --enable-fpm --with-pdo-sqlite --without-pear --with-bz2 --with-avif --with-jpeg --with-webp --with-freetype --enable-gd --enable-exif --with-zip --with-zlib --enable-soap --enable-xmlreader --with-xsl --with-libxml --enable-shmop --enable-pcntl --enable-mbstring --with-curl --enable-sockets --with-openssl --with-iconv=/usr/local --enable-bcmath --enable-calendar --enable-ftp --with-kerberos --with-ffi --enable-zend-test --enable-intl --with-mhash --with-sodium --enable-werror --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d + - ./configure --prefix=/usr/local --enable-debug --enable-option-checking=fatal --enable-fpm --with-pdo-sqlite --without-pear --with-bz2 --with-avif --with-jpeg --with-webp --with-freetype --enable-gd --enable-exif --with-zip --with-zlib --enable-soap --enable-xmlreader --with-xsl --with-libxml --enable-shmop --enable-pcntl --enable-mbstring --with-curl --enable-sockets --with-openssl --with-iconv=/usr/local --enable-bcmath --enable-calendar --enable-ftp --with-kerberos --with-ffi --enable-zend-test --enable-dl-test=shared --enable-intl --with-mhash --with-sodium --enable-werror --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d - gmake -j2 - mkdir /etc/php.d - gmake install diff --git a/.gitattributes b/.gitattributes index 5bee19d08d632..514999ffccfeb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13,7 +13,8 @@ /UPGRADING merge=NEWS /UPGRADING.INTERNALS merge=NEWS -# Enable commit diffs for binary PHP test files. Some PHP test files include -# special characters, such as ASCII control characters. Git recognizes these as -# binary and wouldn't generate diffs. -*.phpt diff +# Configure proper diff drivers to improve the context lines in the output +# of git diff and to improve token splitting for --word-diff. +*.phpt diff=php +*.php diff=php +*.[ch] diff=cpp diff --git a/.github/actions/apt-x64/action.yml b/.github/actions/apt-x64/action.yml index c21a34534aea8..a5b0db49e8270 100644 --- a/.github/actions/apt-x64/action.yml +++ b/.github/actions/apt-x64/action.yml @@ -59,10 +59,10 @@ runs: libpng-dev \ libfreetype6-dev mkdir /opt/oracle - wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip - unzip instantclient-basiclite-linuxx64.zip - wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip - unzip instantclient-sdk-linuxx64.zip + wget -nv https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip + unzip instantclient-basiclite-linuxx64.zip && rm instantclient-basiclite-linuxx64.zip + wget -nv https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip + unzip instantclient-sdk-linuxx64.zip && rm instantclient-sdk-linuxx64.zip mv instantclient_*_* /opt/oracle/instantclient # Interferes with libldap2 headers. rm /opt/oracle/instantclient/sdk/include/ldap.h diff --git a/.github/actions/configure-macos/action.yml b/.github/actions/configure-macos/action.yml index 852d8f62b68e1..319a00595ffc4 100644 --- a/.github/actions/configure-macos/action.yml +++ b/.github/actions/configure-macos/action.yml @@ -61,6 +61,7 @@ runs: --enable-sysvmsg \ --with-ffi \ --enable-zend-test \ + --enable-dl-test=shared \ --enable-intl \ --with-mhash \ --with-sodium \ diff --git a/.github/actions/configure-x64/action.yml b/.github/actions/configure-x64/action.yml index f9b774218f4ef..5b5583918bcfe 100644 --- a/.github/actions/configure-x64/action.yml +++ b/.github/actions/configure-x64/action.yml @@ -56,6 +56,7 @@ runs: --enable-sysvmsg \ --with-ffi \ --enable-zend-test \ + --enable-dl-test=shared \ --with-ldap \ --with-ldap-sasl \ --with-password-argon2 \ diff --git a/.github/actions/install-linux/action.yml b/.github/actions/install-linux/action.yml index 6db48f0ec3e1d..e0f6726dbd1d3 100644 --- a/.github/actions/install-linux/action.yml +++ b/.github/actions/install-linux/action.yml @@ -10,5 +10,3 @@ runs: sudo chmod 777 /etc/php.d echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/pdo_mysql.ini - echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini - echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini diff --git a/.github/actions/verify-generated-files/action.yml b/.github/actions/verify-generated-files/action.yml new file mode 100644 index 0000000000000..21aa125a1cbbc --- /dev/null +++ b/.github/actions/verify-generated-files/action.yml @@ -0,0 +1,12 @@ +name: Verify generated files are up to date +runs: + using: composite + steps: + - shell: bash + run: | + set -x + [[ "$OSTYPE" == "darwin"* ]] && export PATH="/usr/local/opt/bison/bin:$PATH" + scripts/dev/genfiles + Zend/zend_vm_gen.php + build/gen_stub.php -f + git add . -Nu && git diff --exit-code diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1b847554afe9a..4d347323e89b3 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -6,6 +6,7 @@ on: jobs: GENERATE_MATRIX: name: Generate Matrix + if: github.repository_owner == 'php' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest outputs: branches: ${{ steps.set-matrix.outputs.branches }} @@ -74,6 +75,7 @@ jobs: runTestsParameters: >- ${{ matrix.run_tests_parameters }} -d zend_extension=opcache.so + -d opcache.enable_cli=1 -d opcache.jit_buffer_size=16M - name: Test OpCache uses: ./.github/actions/test-linux @@ -81,14 +83,18 @@ jobs: runTestsParameters: >- ${{ matrix.run_tests_parameters }} -d zend_extension=opcache.so + -d opcache.enable_cli=1 - name: Test Function JIT uses: ./.github/actions/test-linux with: runTestsParameters: >- ${{ matrix.run_tests_parameters }} -d zend_extension=opcache.so + -d opcache.enable_cli=1 -d opcache.jit_buffer_size=16M -d opcache.jit=1205 + - name: Verify generated files are up to date + uses: ./.github/actions/verify-generated-files MACOS: needs: GENERATE_MATRIX if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} @@ -126,6 +132,7 @@ jobs: with: runTestsParameters: >- -d zend_extension=opcache.so + -d opcache.enable_cli=1 -d opcache.protect_memory=1 -d opcache.jit_buffer_size=16M - name: Test OpCache @@ -133,12 +140,16 @@ jobs: with: runTestsParameters: >- -d zend_extension=opcache.so + -d opcache.enable_cli=1 -d opcache.protect_memory=1 - name: Test Function JIT uses: ./.github/actions/test-macos with: runTestsParameters: >- -d zend_extension=opcache.so + -d opcache.enable_cli=1 -d opcache.protect_memory=1 -d opcache.jit_buffer_size=16M -d opcache.jit=1205 + - name: Verify generated files are up to date + uses: ./.github/actions/verify-generated-files diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 7e348802b1e6e..4a1619ab5d106 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -53,7 +53,12 @@ jobs: - name: Test Tracing JIT uses: ./.github/actions/test-linux with: - runTestsParameters: -d zend_extension=opcache.so -d opcache.jit_buffer_size=16M + runTestsParameters: >- + -d zend_extension=opcache.so + -d opcache.enable_cli=1 + -d opcache.jit_buffer_size=16M + - name: Verify generated files are up to date + uses: ./.github/actions/verify-generated-files MACOS_DEBUG_NTS: runs-on: macos-10.15 steps: @@ -78,5 +83,8 @@ jobs: with: runTestsParameters: >- -d zend_extension=opcache.so + -d opcache.enable_cli=1 -d opcache.protect_memory=1 -d opcache.jit_buffer_size=16M + - name: Verify generated files are up to date + uses: ./.github/actions/verify-generated-files diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d18eb2c98cbe..860e6ae0f3b8e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,7 +36,8 @@ supported branch of PHP that the bug affects (only green branches on [the supported version page](https://www.php.net/supported-versions.php) are supported). For example, at the time of writing, the lowest supported version is PHP 8.0, which corresponds to the `PHP-8.0` branch in Git. Please also make sure -you add a link to the PR in the bug on [the bug tracker](https://bugs.php.net/). +you add a link to the PR in the bug on [the bug tracker](https://github.com/php/php-src/issues) +or [the old bug tracker](https://bugs.php.net/). Pull requests implementing RFCs should be submitted against `master`. @@ -49,7 +50,8 @@ them by using `git rebase` instead of `git merge`. Fork the official PHP repository and send a pull request. A notification will be sent to the pull request mailing list. Sending a note to PHP Internals list (internals@lists.php.net) may help getting more feedback and quicker turnaround. -You can also add pull requests to [bug reports](https://bugs.php.net/). +You can also add pull requests to [bug reports](https://github.com/php/php-src/issues) +and [old bug reports](https://bugs.php.net/). Read [Git access page](https://www.php.net/git.php) for help on using Git to get and build PHP source code. We recommend to look at our diff --git a/NEWS b/NEWS index 4178005c7b733..5c1712569ed92 100644 --- a/NEWS +++ b/NEWS @@ -9,11 +9,23 @@ PHP NEWS . Fixed bug #81380 (Observer may not be initialized properly). (krakjoe) . Fixed bug GH-7771 (Fix filename/lineno of constant expressions). (ilutov) . Fixed bug GH-7792 (Improve class type in error messages). (ilutov) + . Support huge pages on MacOS. (David CARLIER) + +- Curl: + . Added support for CURLOPT_XFERINFOFUNCTION. (David Carlier) + +- Date: + . Fixed GH-8458 (DateInterval::createFromDateString does not throw if + non-relative items are present). (Derick) + . idate() now accepts format specifiers "N" (ISO Day-of-Week) and "o" (ISO + Year). (Pavel Djundik) - FPM: . Emit error for invalid port setting. (David Carlier) . Added extra check for FPM proc dumpable on SELinux based systems. (David Carlier) + . Added support for listening queue on macOS. (David Carlier) + . Changed default for listen.backlog on Linux to -1. (Cristian Rodríguez) - Intl: . Update all grandfathered language tags with preferred values @@ -28,9 +40,20 @@ PHP NEWS . Fixed bug #80909 (crash with persistent connections in PDO_ODBC). (Calvin Buckley) +- Reflection: + . Added ReflectionFunction::isAnonymous(). (Nicolas Grekas) + . Added ReflectionMethod::hasPrototype(). (Ollie Read) + - Sodium: . Added sodium_crypto_stream_xchacha20_xor_ic(). (Scott) +- SQLite3: + . Changed sqlite3.defensive from PHP_INI_SYSTEM to PHP_INI_USER. (bohwaz) + +- Streams: + . Set IP_BIND_ADDRESS_NO_PORT if available when connecting to remote host. + (Cristian Rodríguez) + - Standard: . net_get_interfaces() also reports wireless network interfaces on Windows. (Yurun) diff --git a/TSRM/TSRM.c b/TSRM/TSRM.c index dc0ecff44ed1b..7cd924318ed4c 100644 --- a/TSRM/TSRM.c +++ b/TSRM/TSRM.c @@ -288,9 +288,9 @@ TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate tsrm_resource_type *_tmp; _tmp = (tsrm_resource_type *) realloc(resource_types_table, sizeof(tsrm_resource_type)*id_count); if (!_tmp) { - tsrm_mutex_unlock(tsmm_mutex); TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource")); *rsrc_id = 0; + tsrm_mutex_unlock(tsmm_mutex); return 0; } resource_types_table = _tmp; @@ -331,10 +331,10 @@ TSRM_API ts_rsrc_id ts_allocate_fast_id(ts_rsrc_id *rsrc_id, size_t *offset, siz size = TSRM_ALIGNED_SIZE(size); if (tsrm_reserved_size - tsrm_reserved_pos < size) { - tsrm_mutex_unlock(tsmm_mutex); TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate space for fast resource")); *rsrc_id = 0; *offset = 0; + tsrm_mutex_unlock(tsmm_mutex); return 0; } @@ -346,9 +346,9 @@ TSRM_API ts_rsrc_id ts_allocate_fast_id(ts_rsrc_id *rsrc_id, size_t *offset, siz tsrm_resource_type *_tmp; _tmp = (tsrm_resource_type *) realloc(resource_types_table, sizeof(tsrm_resource_type)*id_count); if (!_tmp) { - tsrm_mutex_unlock(tsmm_mutex); TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource")); *rsrc_id = 0; + tsrm_mutex_unlock(tsmm_mutex); return 0; } resource_types_table = _tmp; @@ -736,13 +736,15 @@ TSRM_API size_t tsrm_get_ls_cache_tcb_offset(void) #if defined(__APPLE__) && defined(__x86_64__) // TODO: Implement support for fast JIT ZTS code ??? return 0; -#elif defined(__x86_64__) && defined(__GNUC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__MUSL__) +#elif defined(__x86_64__) && defined(__GNUC__) && !defined(__FreeBSD__) && \ + !defined(__OpenBSD__) && !defined(__MUSL__) && !defined(__HAIKU__) size_t ret; asm ("movq _tsrm_ls_cache@gottpoff(%%rip),%0" : "=r" (ret)); return ret; -#elif defined(__i386__) && defined(__GNUC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__MUSL__) +#elif defined(__i386__) && defined(__GNUC__) && !defined(__FreeBSD__) && \ + !defined(__OpenBSD__) && !defined(__MUSL__) && !defined(__HAIKU__) size_t ret; asm ("leal _tsrm_ls_cache@ntpoff,%0" diff --git a/UPGRADING b/UPGRADING index 12cffeb9127e5..565759e86f9af 100644 --- a/UPGRADING +++ b/UPGRADING @@ -19,6 +19,12 @@ PHP 8.2 UPGRADE NOTES 1. Backward Incompatible Changes ======================================== +- Date: + . DateTime::createFromImmutable() now has a tentative return type of static, + previously it was DateTime + . DateTimeImmutable::createFromMutable() now has a tentative return type of static, + previously it was DateTimeImmutable + - Standard: . strtolower() and strtoupper() are no longer locale-sensitive. They now perform ASCII case conversion, as if the locale were "C". Use @@ -35,6 +41,10 @@ PHP 8.2 UPGRADE NOTES * SplFileObject::ftell() * SplFileObject::fgetc() * SplFileObject::fpassthru() + . SplFileObject::hasChildren() now has a tentative return type of false, + previously it was bool + . SplFileObject::getChildren() now has a tentative return type of null, + previously it was ?RecursiveIterator ======================================== 2. New Features @@ -44,6 +54,8 @@ PHP 8.2 UPGRADE NOTES . Added the #[\SensitiveParameter] attribute to redact sensitive data in backtraces. RFC: https://wiki.php.net/rfc/redact_parameters_in_back_traces + . It is now possible to use null and false as standalone types. + RFC: https://wiki.php.net/rfc/null-false-standalone-types - Curl: . Added CURLINFO_EFFECTIVE_METHOD option and returning the effective @@ -100,6 +112,10 @@ PHP 8.2 UPGRADE NOTES RFC: https://wiki.php.net/rfc/deprecate_partially_supported_callables + . The "${var}" and "${expr}" style string interpolations are deprecated and + will be removed in PHP 9. Use "$var"/"{$var}" or "{${expr}}", respectively. + RFC: https://wiki.php.net/rfc/deprecate_dollar_brace_string_interpolation + - Mbstring: . Use of QPrint, Base64, Uuencode, and HTML-ENTITIES 'text encodings' is deprecated for all Mbstring functions. Unlike all the other text @@ -128,6 +144,10 @@ PHP 8.2 UPGRADE NOTES 6. New Functions ======================================== +- Reflection: + . ReflectionFunction::isAnonymous() + . ReflectionMethod::hasPrototype() + - Sodium: . sodium_crypto_stream_xchacha20_xor_ic() @@ -158,6 +178,9 @@ PHP 8.2 UPGRADE NOTES - OCI8: . The minimum Oracle Client library version required is now 11.2. +- SQLite3: + . sqlite3.defensive is now PHP_INI_USER. + - Standard: . getimagesize() now reports the actual image dimensions, bits and channels of AVIF images. Previously, the dimensions have been reported as 0x0, and @@ -174,6 +197,9 @@ PHP 8.2 UPGRADE NOTES - COM_DOTNET: . LOCALE_NEUTRAL +- Curl: + . CURLOPT_XFERINFOFUNCTION + - Sockets: . SO_INCOMING_CPU diff --git a/Zend/Optimizer/optimize_func_calls.c b/Zend/Optimizer/optimize_func_calls.c index 846b34b46f457..200b5a6ff83f4 100644 --- a/Zend/Optimizer/optimize_func_calls.c +++ b/Zend/Optimizer/optimize_func_calls.c @@ -28,13 +28,6 @@ #include "zend_execute.h" #include "zend_vm.h" -#define ZEND_OP1_IS_CONST_STRING(opline) \ - (opline->op1_type == IS_CONST && \ - Z_TYPE(op_array->literals[(opline)->op1.constant]) == IS_STRING) -#define ZEND_OP2_IS_CONST_STRING(opline) \ - (opline->op2_type == IS_CONST && \ - Z_TYPE(op_array->literals[(opline)->op2.constant]) == IS_STRING) - typedef struct _optimizer_call_info { zend_function *func; zend_op *opline; @@ -139,6 +132,20 @@ static void zend_try_inline_call(zend_op_array *op_array, zend_op *fcall, zend_o } } +/* arg_num is 1-based here, to match SEND encoding. */ +static bool has_known_send_mode(const optimizer_call_info *info, uint32_t arg_num) +{ + if (!info->func) { + return false; + } + + /* For prototype functions we should not make assumptions about arguments that are not part of + * the signature: And inheriting method can add an optional by-ref argument. */ + return !info->is_prototype + || arg_num <= info->func->common.num_args + || (info->func->common.fn_flags & ZEND_ACC_VARIADIC); +} + void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_op *opline = op_array->opcodes; @@ -225,8 +232,8 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) case ZEND_FETCH_STATIC_PROP_FUNC_ARG: case ZEND_FETCH_OBJ_FUNC_ARG: case ZEND_FETCH_DIM_FUNC_ARG: - if (call_stack[call - 1].func - && call_stack[call - 1].func_arg_num != (uint32_t)-1) { + if (call_stack[call - 1].func_arg_num != (uint32_t)-1 + && has_known_send_mode(&call_stack[call - 1], call_stack[call - 1].func_arg_num)) { if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, call_stack[call - 1].func_arg_num)) { if (opline->opcode != ZEND_FETCH_STATIC_PROP_FUNC_ARG) { opline->opcode -= 9; @@ -251,40 +258,37 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) } break; case ZEND_SEND_VAL_EX: - if (call_stack[call - 1].func) { - if (opline->op2_type == IS_CONST) { - call_stack[call - 1].try_inline = 0; - break; - } + if (opline->op2_type == IS_CONST) { + call_stack[call - 1].try_inline = 0; + break; + } - if (ARG_MUST_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) { - /* We won't convert it into_DO_FCALL to emit error at run-time */ - call_stack[call - 1].opline = NULL; - } else { + if (has_known_send_mode(&call_stack[call - 1], opline->op2.num)) { + if (!ARG_MUST_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) { opline->opcode = ZEND_SEND_VAL; } } break; case ZEND_CHECK_FUNC_ARG: - if (call_stack[call - 1].func) { - if (opline->op2_type == IS_CONST) { - call_stack[call - 1].try_inline = 0; - call_stack[call - 1].func_arg_num = (uint32_t)-1; - break; - } + if (opline->op2_type == IS_CONST) { + call_stack[call - 1].try_inline = 0; + call_stack[call - 1].func_arg_num = (uint32_t)-1; + break; + } + if (has_known_send_mode(&call_stack[call - 1], opline->op2.num)) { call_stack[call - 1].func_arg_num = opline->op2.num; MAKE_NOP(opline); } break; case ZEND_SEND_VAR_EX: case ZEND_SEND_FUNC_ARG: - if (call_stack[call - 1].func) { - if (opline->op2_type == IS_CONST) { - call_stack[call - 1].try_inline = 0; - break; - } + if (opline->op2_type == IS_CONST) { + call_stack[call - 1].try_inline = 0; + break; + } + if (has_known_send_mode(&call_stack[call - 1], opline->op2.num)) { call_stack[call - 1].func_arg_num = (uint32_t)-1; if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) { opline->opcode = ZEND_SEND_REF; @@ -294,12 +298,12 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) } break; case ZEND_SEND_VAR_NO_REF_EX: - if (call_stack[call - 1].func) { - if (opline->op2_type == IS_CONST) { - call_stack[call - 1].try_inline = 0; - break; - } + if (opline->op2_type == IS_CONST) { + call_stack[call - 1].try_inline = 0; + break; + } + if (has_known_send_mode(&call_stack[call - 1], opline->op2.num)) { if (ARG_MUST_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) { opline->opcode = ZEND_SEND_VAR_NO_REF; } else if (ARG_MAY_BE_SENT_BY_REF(call_stack[call - 1].func, opline->op2.num)) { diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index 17af8bd62bd39..3ac97e0f89533 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -1721,6 +1721,10 @@ static zval *value_from_type_and_range(sccp_ctx *ctx, int var_num, zval *tmp) { } if (!(info->type & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_NULL))) { + if (ssa->vars[var_num].definition >= 0 + && ctx->scdf.op_array->opcodes[ssa->vars[var_num].definition].opcode == ZEND_VERIFY_RETURN_TYPE) { + return NULL; + } ZVAL_NULL(tmp); return tmp; } diff --git a/Zend/Optimizer/ssa_integrity.c b/Zend/Optimizer/ssa_integrity.c index d4ffbd1e7cd27..779edd2934843 100644 --- a/Zend/Optimizer/ssa_integrity.c +++ b/Zend/Optimizer/ssa_integrity.c @@ -176,6 +176,9 @@ void ssa_verify_integrity(zend_op_array *op_array, zend_ssa *ssa, const char *ex if ((type & MAY_BE_ARRAY_OF_ANY) && !(type & MAY_BE_ARRAY_KEY_ANY)) { FAIL("var " VARFMT " has array value type but not key type\n", VAR(i)); } + if ((type & MAY_BE_REF) && ssa->var_info[i].ce) { + FAIL("var " VARFMT " may be ref but has ce\n", VAR(i)); + } } /* Instructions */ diff --git a/Zend/Optimizer/zend_func_info.c b/Zend/Optimizer/zend_func_info.c index 7e9988fb31bdd..f125f4956b11e 100644 --- a/Zend/Optimizer/zend_func_info.c +++ b/Zend/Optimizer/zend_func_info.c @@ -186,6 +186,7 @@ ZEND_API uint32_t zend_get_func_info( /* It's allowed to override a method that return non-reference with a method that returns a reference */ if (call_info->is_prototype && (ret & ~MAY_BE_REF)) { ret |= MAY_BE_REF; + *ce = NULL; } } } diff --git a/Zend/Optimizer/zend_func_infos.h b/Zend/Optimizer/zend_func_infos.h index ff89312fb3f4b..a2b4fb392bcaf 100644 --- a/Zend/Optimizer/zend_func_infos.h +++ b/Zend/Optimizer/zend_func_infos.h @@ -134,7 +134,6 @@ static const func_info_t func_infos[] = { #if defined(HAVE_GD_BMP) F1("imagecreatefrombmp", MAY_BE_OBJECT|MAY_BE_FALSE), #endif - F0("imagecolorset", MAY_BE_FALSE|MAY_BE_NULL), F1("imagecolorsforindex", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG), F1("imagegetclip", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_LONG), #if defined(HAVE_GD_FREETYPE) @@ -514,7 +513,6 @@ static const func_info_t func_infos[] = { F1("get_current_user", MAY_BE_STRING), FN("get_cfg_var", MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_FALSE), F1("error_get_last", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_LONG|MAY_BE_ARRAY_OF_STRING|MAY_BE_NULL), - F0("register_shutdown_function", MAY_BE_FALSE|MAY_BE_NULL), F1("highlight_file", MAY_BE_STRING|MAY_BE_BOOL), F1("php_strip_whitespace", MAY_BE_STRING), F1("highlight_string", MAY_BE_STRING|MAY_BE_BOOL), @@ -619,7 +617,6 @@ static const func_info_t func_infos[] = { #endif F1("exec", MAY_BE_STRING|MAY_BE_FALSE), F1("system", MAY_BE_STRING|MAY_BE_FALSE), - F0("passthru", MAY_BE_FALSE|MAY_BE_NULL), F1("escapeshellcmd", MAY_BE_STRING), F1("escapeshellarg", MAY_BE_STRING), F1("shell_exec", MAY_BE_STRING|MAY_BE_FALSE|MAY_BE_NULL), diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 068b8f0fe8c65..2e1e2164c0adc 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -1787,7 +1787,7 @@ static uint32_t get_ssa_alias_types(zend_ssa_alias_kind alias) { #define COPY_SSA_OBJ_TYPE(from_var, to_var) do { \ if ((from_var) >= 0 && (ssa_var_info[(from_var)].type & MAY_BE_OBJECT) \ - && ssa_var_info[(from_var)].ce) { \ + && ssa_var_info[(from_var)].ce && !(ssa_var_info[(to_var)].type & MAY_BE_REF)) { \ UPDATE_SSA_OBJ_TYPE(ssa_var_info[(from_var)].ce, \ ssa_var_info[(from_var)].is_instanceof, (to_var)); \ } else { \ @@ -2708,6 +2708,9 @@ static zend_always_inline zend_result _zend_update_type_info( tmp |= MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING; } } + if (!tmp) { + tmp = MAY_BE_NULL; + } tmp |= MAY_BE_RC1 | MAY_BE_RCN; UPDATE_SSA_TYPE(tmp, ssa_op->result_def); } @@ -3001,6 +3004,7 @@ static zend_always_inline zend_result _zend_update_type_info( tmp = zend_fetch_arg_info_type(script, arg_info, &ce); if (ZEND_ARG_SEND_MODE(arg_info)) { tmp |= MAY_BE_REF; + ce = NULL; } if (opline->opcode == ZEND_RECV_VARIADIC) { @@ -3249,7 +3253,12 @@ static zend_always_inline zend_result _zend_update_type_info( tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN); } if (opline->op2_type == IS_UNUSED) { - key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; + if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL)) { + key_type |= MAY_BE_ARRAY_PACKED; + } + if (t1 & MAY_BE_ARRAY) { + key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; + } } else { if (t2 & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) { key_type |= MAY_BE_HASH_ONLY(t1) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; @@ -3273,10 +3282,11 @@ static zend_always_inline zend_result _zend_update_type_info( tmp |= t1 & (MAY_BE_RC1|MAY_BE_RCN); } } - if (opline->opcode == ZEND_FETCH_DIM_RW + if ((key_type & (MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING)) + && (opline->opcode == ZEND_FETCH_DIM_RW || opline->opcode == ZEND_FETCH_DIM_W || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG - || opline->opcode == ZEND_FETCH_LIST_W) { + || opline->opcode == ZEND_FETCH_LIST_W)) { j = ssa_vars[ssa_op->result_def].use_chain; if (j < 0) { /* no uses */ @@ -3354,11 +3364,12 @@ static zend_always_inline zend_result _zend_update_type_info( ZEND_ASSERT(j < 0 && "There should only be one use"); } } - if ((tmp & MAY_BE_ARRAY) && (tmp & MAY_BE_ARRAY_KEY_ANY)) { + if (((tmp & MAY_BE_ARRAY) && (tmp & MAY_BE_ARRAY_KEY_ANY)) || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG) { UPDATE_SSA_TYPE(tmp, ssa_op->op1_def); } else { /* invalid key type */ - tmp = (tmp & (MAY_BE_RC1|MAY_BE_RCN)) | (t1 & ~(MAY_BE_RC1|MAY_BE_RCN)); + tmp = (tmp & (MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ARRAY)) | + (t1 & ~(MAY_BE_RC1|MAY_BE_RCN|MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)); UPDATE_SSA_TYPE(tmp, ssa_op->op1_def); } COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def); @@ -3367,7 +3378,8 @@ static zend_always_inline zend_result _zend_update_type_info( tmp = zend_array_element_type( opline->opcode != ZEND_FETCH_LIST_R ? t1 : ((t1 & ~MAY_BE_STRING) | MAY_BE_NULL), opline->op1_type, - opline->result_type == IS_VAR, + opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS + && opline->opcode != ZEND_FETCH_LIST_R, opline->op2_type == IS_UNUSED); if (opline->opcode == ZEND_FETCH_DIM_IS && (t1 & MAY_BE_STRING)) { tmp |= MAY_BE_NULL; @@ -3408,8 +3420,9 @@ static zend_always_inline zend_result _zend_update_type_info( if (opline->op1_type == IS_UNUSED || (t1 & MAY_BE_OBJECT)) { zend_property_info *prop_info = zend_fetch_prop_info(op_array, ssa, opline, ssa_op); tmp |= zend_fetch_prop_type(script, prop_info, &ce); - if (opline->result_type == IS_VAR) { + if (opline->opcode != ZEND_FETCH_OBJ_R && opline->opcode != ZEND_FETCH_OBJ_IS) { tmp |= MAY_BE_REF | MAY_BE_INDIRECT; + ce = NULL; } else if (!(opline->op1_type & (IS_VAR|IS_TMP_VAR)) || !(t1 & MAY_BE_RC1)) { zend_class_entry *ce = NULL; @@ -3449,8 +3462,10 @@ static zend_always_inline zend_result _zend_update_type_info( case ZEND_FETCH_STATIC_PROP_FUNC_ARG: tmp = zend_fetch_prop_type(script, zend_fetch_static_prop_info(script, op_array, ssa, opline), &ce); - if (opline->result_type == IS_VAR) { + if (opline->opcode != ZEND_FETCH_STATIC_PROP_R + && opline->opcode != ZEND_FETCH_STATIC_PROP_IS) { tmp |= MAY_BE_REF | MAY_BE_INDIRECT; + ce = NULL; } else { if (!result_may_be_separated(ssa, ssa_op)) { tmp &= ~MAY_BE_RC1; @@ -3740,7 +3755,11 @@ static zend_result zend_infer_types_ex(const zend_op_array *op_array, const zend } UPDATE_SSA_TYPE(tmp, j); - UPDATE_SSA_OBJ_TYPE(ce, is_instanceof, j); + if (tmp & MAY_BE_REF) { + UPDATE_SSA_OBJ_TYPE(NULL, 0, j); + } else { + UPDATE_SSA_OBJ_TYPE(ce, is_instanceof, j); + } } else { int first = 1; int is_instanceof = 0; @@ -4044,6 +4063,8 @@ uint32_t zend_get_return_info_from_signature_only( if ((func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) && !(func->common.fn_flags & ZEND_ACC_GENERATOR)) { type |= MAY_BE_REF; + *ce = NULL; + *ce_is_instanceof = 0; } return type; } @@ -4127,7 +4148,7 @@ static void zend_func_return_info(const zend_op_array *op_array, tmp |= t1; if (ssa_op && info->ssa.var_info && - ssa_op->op1_use >= 0 && + ssa_op->op1_use >= 0 && !(t1 & MAY_BE_REF) && info->ssa.var_info[ssa_op->op1_use].ce) { arg_ce = info->ssa.var_info[ssa_op->op1_use].ce; arg_is_instanceof = info->ssa.var_info[ssa_op->op1_use].is_instanceof; diff --git a/Zend/Optimizer/zend_optimizer.c b/Zend/Optimizer/zend_optimizer.c index e7d429ddeff47..bb2936fd40a38 100644 --- a/Zend/Optimizer/zend_optimizer.c +++ b/Zend/Optimizer/zend_optimizer.c @@ -184,6 +184,9 @@ zend_result zend_optimizer_eval_special_func_call( if (zend_string_equals_literal(name, "ini_get")) { zend_ini_entry *ini_entry = zend_hash_find_ptr(EG(ini_directives), arg); if (!ini_entry) { + if (PG(enable_dl)) { + return FAILURE; + } ZVAL_FALSE(result); } else if (ini_entry->modifiable != ZEND_INI_SYSTEM) { return FAILURE; @@ -413,6 +416,8 @@ bool zend_optimizer_update_op1_const(zend_op_array *op_array, case ZEND_FETCH_IS: case ZEND_FETCH_UNSET: case ZEND_FETCH_FUNC_ARG: + case ZEND_ISSET_ISEMPTY_VAR: + case ZEND_UNSET_VAR: TO_STRING_NOWARN(val); if (opline->opcode == ZEND_CONCAT && opline->op2_type == IS_CONST) { opline->opcode = ZEND_FAST_CONCAT; @@ -1014,7 +1019,8 @@ static void zend_optimize(zend_op_array *op_array, /* pass 9: * - Optimize temp variables usage */ - if (ZEND_OPTIMIZER_PASS_9 & ctx->optimization_level) { + if ((ZEND_OPTIMIZER_PASS_9 & ctx->optimization_level) && + !(ZEND_OPTIMIZER_PASS_7 & ctx->optimization_level)) { zend_optimize_temporary_variables(op_array, ctx); if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_9) { zend_dump_op_array(op_array, 0, "after pass 9", NULL); @@ -1517,6 +1523,15 @@ ZEND_API void zend_optimize_script(zend_script *script, zend_long optimization_l } } + if (ZEND_OPTIMIZER_PASS_9 & optimization_level) { + for (i = 0; i < call_graph.op_arrays_count; i++) { + zend_optimize_temporary_variables(call_graph.op_arrays[i], &ctx); + if (debug_level & ZEND_DUMP_AFTER_PASS_9) { + zend_dump_op_array(call_graph.op_arrays[i], 0, "after pass 9", NULL); + } + } + } + if (ZEND_OPTIMIZER_PASS_11 & optimization_level) { for (i = 0; i < call_graph.op_arrays_count; i++) { zend_optimizer_compact_literals(call_graph.op_arrays[i], &ctx); diff --git a/Zend/tests/add_optional_by_ref_arg.phpt b/Zend/tests/add_optional_by_ref_arg.phpt new file mode 100644 index 0000000000000..7ce4fd5a46f46 --- /dev/null +++ b/Zend/tests/add_optional_by_ref_arg.phpt @@ -0,0 +1,22 @@ +--TEST-- +Adding an optional by-ref arg in a child method +--FILE-- +method2($x); + var_dump($x); + } + public function method2() {} +} +class Test2 extends Test1 { + public function method2(&$x = null) { + ++$x; + } +} +(new Test2)->method1(); + +?> +--EXPECT-- +int(1) diff --git a/Zend/tests/assign_obj_to_ref_inference.phpt b/Zend/tests/assign_obj_to_ref_inference.phpt new file mode 100644 index 0000000000000..5a91210371aec --- /dev/null +++ b/Zend/tests/assign_obj_to_ref_inference.phpt @@ -0,0 +1,42 @@ +--TEST-- +Assigning an object of known type to a reference variable +--FILE-- +x = 3.141; + var_dump(is_float($o->x)); +} + +function test2($o) { + $r =& $o; + if ($o instanceof Test) { + $r = new stdClass; + $r->x = 3.141; + var_dump(is_float($o->x)); + } +} + +function test3(Test &$o) { + $GLOBALS['r'] = new stdClass; + $GLOBALS['r']->x = 3.141; + var_dump(is_float($o->x)); +} + +test1(); +test2(new Test); +$r = new Test; +test3($r); + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) diff --git a/Zend/tests/attributes/gh8421.phpt b/Zend/tests/attributes/gh8421.phpt new file mode 100644 index 0000000000000..605772c704c59 --- /dev/null +++ b/Zend/tests/attributes/gh8421.phpt @@ -0,0 +1,59 @@ +--TEST-- +Bug GH-8421: Attributes that target functions are not valid for anonymous functions defined within a method +--FILE-- + true; +$globalStaticClosure = #[FunctionAttribute] +static fn() => true; + +class ClosureHolder +{ + public function getClosureDefinedInScope(): Closure + { + return #[FunctionAttribute] + fn() => true; + } + + public function getStaticClosureDefinedInScope(): Closure + { + return #[FunctionAttribute] + static fn() => true; + } + + public static function getClosureDefinedInScopeStatically(): Closure + { + return #[FunctionAttribute] + fn() => true; + } + + public static function getStaticClosureDefinedInScopeStatically(): Closure + { + return #[FunctionAttribute] + static fn() => true; + } +} + +var_dump((new ReflectionFunction($globalClosure))->getAttributes(FunctionAttribute::class)[0]->newInstance()->number); +var_dump((new ReflectionFunction($globalStaticClosure))->getAttributes(FunctionAttribute::class)[0]->newInstance()->number); +var_dump((new ReflectionFunction(ClosureHolder::getClosureDefinedInScopeStatically()))->getAttributes(FunctionAttribute::class)[0]->newInstance()->number); +var_dump((new ReflectionFunction(ClosureHolder::getStaticClosureDefinedInScopeStatically()))->getAttributes(FunctionAttribute::class)[0]->newInstance()->number); + +$holder = new ClosureHolder; + +var_dump((new ReflectionFunction($holder->getClosureDefinedInScope()))->getAttributes(FunctionAttribute::class)[0]->newInstance()->number); +var_dump((new ReflectionFunction($holder->getStaticClosureDefinedInScope()))->getAttributes(FunctionAttribute::class)[0]->newInstance()->number); +?> +--EXPECT-- +int(1) +int(1) +int(1) +int(1) +int(1) +int(1) diff --git a/Zend/tests/bug61681.phpt b/Zend/tests/bug61681.phpt index 00a23e97d7a18..6329c6083e1ac 100644 --- a/Zend/tests/bug61681.phpt +++ b/Zend/tests/bug61681.phpt @@ -7,5 +7,6 @@ $la = "ooxx"; echo "${substr('laruence', 0, 2)}"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d ooxx diff --git a/Zend/tests/bug73350.phpt b/Zend/tests/bug73350.phpt index 7505884efbcdd..80584204b254e 100644 --- a/Zend/tests/bug73350.phpt +++ b/Zend/tests/bug73350.phpt @@ -12,7 +12,7 @@ $e = new Exception(); var_export($e); ?> --EXPECTF-- -Exception::__set_state(array( +\Exception::__set_state(array( 'message' => '', 'string' => 'Exception in %sbug73350.php:%d Stack trace: diff --git a/Zend/tests/class_constants_006.phpt b/Zend/tests/class_constants_006.phpt new file mode 100644 index 0000000000000..aed8d831b7016 --- /dev/null +++ b/Zend/tests/class_constants_006.phpt @@ -0,0 +1,13 @@ +--TEST-- +Ownership of constant expression inhereted from interface should be transfered to class +--FILE-- + +--EXPECT-- +string(2) "XY" diff --git a/Zend/tests/deprecate_dollar_brace_string_interpolation_1.phpt b/Zend/tests/deprecate_dollar_brace_string_interpolation_1.phpt new file mode 100644 index 0000000000000..84652675e62b5 --- /dev/null +++ b/Zend/tests/deprecate_dollar_brace_string_interpolation_1.phpt @@ -0,0 +1,12 @@ +--TEST-- +"${}" emits a deprecation +--FILE-- + +--EXPECTF-- +Deprecated: Using ${var} in strings is deprecated, use {$var} instead in %s on line %d +string(3) "bar" diff --git a/Zend/tests/enum/enum-in-var-export.phpt b/Zend/tests/enum/enum-in-var-export.phpt new file mode 100644 index 0000000000000..a45567c544933 --- /dev/null +++ b/Zend/tests/enum/enum-in-var-export.phpt @@ -0,0 +1,28 @@ +--TEST-- +Enum in var_export() +--FILE-- + +--EXPECT-- +\Foo::BAR +\A\Foo::BAR +\A\B\Foo::BAR diff --git a/Zend/tests/enum/var_export.phpt b/Zend/tests/enum/var_export.phpt index 7a5a01fc28a23..d45b6d321d8ec 100644 --- a/Zend/tests/enum/var_export.phpt +++ b/Zend/tests/enum/var_export.phpt @@ -14,8 +14,8 @@ echo str_replace(" \n", "\n", var_export([Foo::Bar], true)); ?> --EXPECT-- -Foo::Bar +\Foo::Bar array ( 0 => - Foo::Bar, + \Foo::Bar, ) diff --git a/Zend/tests/exception_in_nested_rope.phpt b/Zend/tests/exception_in_nested_rope.phpt index df0d6fbf8d2a1..7afd1412354a9 100644 --- a/Zend/tests/exception_in_nested_rope.phpt +++ b/Zend/tests/exception_in_nested_rope.phpt @@ -13,5 +13,6 @@ try { } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d Exception diff --git a/Zend/tests/flexible-heredoc-complex-test1.phpt b/Zend/tests/flexible-heredoc-complex-test1.phpt index 3e148d065243b..5f3d085ea4162 100644 --- a/Zend/tests/flexible-heredoc-complex-test1.phpt +++ b/Zend/tests/flexible-heredoc-complex-test1.phpt @@ -21,7 +21,10 @@ var_dump(<< ---EXPECT-- +--EXPECTF-- +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d + +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d string(5) "a b c" diff --git a/Zend/tests/flexible-heredoc-complex-test2.phpt b/Zend/tests/flexible-heredoc-complex-test2.phpt index d585e4b476b48..818c670c4ae5b 100644 --- a/Zend/tests/flexible-heredoc-complex-test2.phpt +++ b/Zend/tests/flexible-heredoc-complex-test2.phpt @@ -21,7 +21,10 @@ var_dump(<< ---EXPECT-- +--EXPECTF-- +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d + +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d string(5) "a b c" diff --git a/Zend/tests/flexible-heredoc-complex-test3.phpt b/Zend/tests/flexible-heredoc-complex-test3.phpt index cf68f123163b2..ed48a0e6c12ec 100644 --- a/Zend/tests/flexible-heredoc-complex-test3.phpt +++ b/Zend/tests/flexible-heredoc-complex-test3.phpt @@ -21,7 +21,10 @@ var_dump(<< ---EXPECT-- +--EXPECTF-- +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d + +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d string(8) " a b c" diff --git a/Zend/tests/flexible-heredoc-complex-test4.phpt b/Zend/tests/flexible-heredoc-complex-test4.phpt index 5be0f442f62fe..3ffff0b60fb73 100644 --- a/Zend/tests/flexible-heredoc-complex-test4.phpt +++ b/Zend/tests/flexible-heredoc-complex-test4.phpt @@ -28,7 +28,10 @@ the same delimiter name as the heredoc } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d + +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d string(8) "Test FOO" string(16) " Test diff --git a/Zend/tests/function_arguments/sensitive_parameter_value.phpt b/Zend/tests/function_arguments/sensitive_parameter_value.phpt index 2949b0b18de61..accf19338a521 100644 --- a/Zend/tests/function_arguments/sensitive_parameter_value.phpt +++ b/Zend/tests/function_arguments/sensitive_parameter_value.phpt @@ -5,9 +5,10 @@ A SensitiveParameterValue keeps the inner value secret. $v = new SensitiveParameterValue('secret'); -echo "# var_dump() / debug_zval_dump()", PHP_EOL; +echo "# var_dump() / debug_zval_dump() / print_r()", PHP_EOL; var_dump($v); debug_zval_dump($v); +print_r($v); echo PHP_EOL; echo "# var_export()", PHP_EOL; @@ -24,14 +25,15 @@ var_dump($v->getValue()); ?> --EXPECTF-- -# var_dump() / debug_zval_dump() +# var_dump() / debug_zval_dump() / print_r() object(SensitiveParameterValue)#%d (0) { } object(SensitiveParameterValue)#%d (%d) refcount(%d){ } +SensitiveParameterValue Object # var_export() -SensitiveParameterValue::__set_state(array( +\SensitiveParameterValue::__set_state(array( )) # (array) / json_encode() diff --git a/Zend/tests/temporary_cleaning_016.phpt b/Zend/tests/temporary_cleaning_016.phpt index cdc9bff0cb8c2..8dc4c8ea31488 100644 --- a/Zend/tests/temporary_cleaning_016.phpt +++ b/Zend/tests/temporary_cleaning_016.phpt @@ -11,5 +11,6 @@ try { } ?> DONE ---EXPECT-- +--EXPECTF-- +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d DONE diff --git a/Zend/tests/warning_during_heredoc_scan_ahead.phpt b/Zend/tests/warning_during_heredoc_scan_ahead.phpt index 7def8a4554e6a..a0becbb782a6d 100644 --- a/Zend/tests/warning_during_heredoc_scan_ahead.phpt +++ b/Zend/tests/warning_during_heredoc_scan_ahead.phpt @@ -14,4 +14,6 @@ Warning: Octal escape sequence overflow \400 is greater than \377 in %s on line Warning: Octal escape sequence overflow \400 is greater than \377 in %s on line %d +Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in %s on line %d + Warning: Undefined variable $ in %s on line %d diff --git a/Zend/zend.c b/Zend/zend.c index ca56e74615c8a..bebf00a424d3a 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1016,9 +1016,7 @@ void zend_startup(zend_utility_functions *utility_functions) /* {{{ */ void zend_register_standard_ini_entries(void) /* {{{ */ { - int module_number = 0; - - REGISTER_INI_ENTRIES(); + zend_register_ini_entries_ex(ini_entries, 0, MODULE_PERSISTENT); } /* }}} */ diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 6ce9f593e17dd..bfcbe2e5f3e17 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2970,7 +2970,7 @@ void module_destructor(zend_module_entry *module) /* {{{ */ if (module->module_started && !module->module_shutdown_func && module->type == MODULE_TEMPORARY) { - zend_unregister_ini_entries(module->module_number); + zend_unregister_ini_entries_ex(module->module_number, module->type); } /* Deinitialize module globals */ diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index e2d06c1762dd9..3511c48a76f5e 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -464,9 +464,16 @@ static void *zend_mm_mmap(size_t size) #else void *ptr; -#ifdef MAP_HUGETLB +#if defined(MAP_HUGETLB) || defined(VM_FLAGS_SUPERPAGE_SIZE_2MB) if (zend_mm_use_huge_pages && size == ZEND_MM_CHUNK_SIZE) { - ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_HUGETLB, -1, 0); + int fd = -1; + int mflags = MAP_PRIVATE | MAP_ANON; +#if defined(MAP_HUGETLB) + mflags |= MAP_HUGETLB; +#else + fd = VM_FLAGS_SUPERPAGE_SIZE_2MB; +#endif + ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, mflags, fd, 0); if (ptr != MAP_FAILED) { return ptr; } @@ -671,7 +678,7 @@ static zend_always_inline void zend_mm_hugepage(void* ptr, size_t size) #elif defined(HAVE_MEMCNTL) struct memcntl_mha m = {.mha_cmd = MHA_MAPSIZE_VA, .mha_pagesize = ZEND_MM_CHUNK_SIZE, .mha_flags = 0}; (void)memcntl(ptr, size, MC_HAT_ADVISE, (char *)&m, 0, 0); -#else +#elif !defined(VM_FLAGS_SUPERPAGE_SIZE_2MB) && !defined(MAP_ALIGNED_SUPER) zend_error_noreturn(E_WARNING, "huge_pages: thp unsupported on this platform"); #endif } diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index f1ea28112bdde..8f248b464c9b3 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -763,6 +763,12 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast break; case ZEND_AST_CONST_ENUM_INIT: { + // Preloading will attempt to resolve constants but objects can't be stored in shm + // Aborting here to store the const AST instead + if (CG(in_compilation)) { + return FAILURE; + } + zend_ast *class_name_ast = ast->child[0]; zend_string *class_name = zend_ast_get_str(class_name_ast); @@ -775,13 +781,6 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast : NULL; zend_class_entry *ce = zend_lookup_class(class_name); - if (!ce) { - /* Class may not be available when resolving constants on a dynamically - * declared enum during preloading. */ - ZEND_ASSERT(CG(compiler_options) & ZEND_COMPILE_PRELOAD); - return FAILURE; - } - zend_enum_new(result, ce, case_name, case_value_zv); break; } diff --git a/Zend/zend_attributes.c b/Zend/zend_attributes.c index 9f7b8f01448b5..433586f55f08c 100644 --- a/Zend/zend_attributes.c +++ b/Zend/zend_attributes.c @@ -109,7 +109,7 @@ ZEND_METHOD(SensitiveParameterValue, __construct) Z_PARAM_ZVAL(value) ZEND_PARSE_PARAMETERS_END(); - ZVAL_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), value); + zend_update_property(zend_ce_sensitive_parameter_value, Z_OBJ_P(ZEND_THIS), "value", strlen("value"), value); } ZEND_METHOD(SensitiveParameterValue, getValue) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 444dee5b0d7d4..76470e811cea9 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3487,6 +3487,9 @@ static uint32_t zend_compile_args( if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) { opcode = ZEND_SEND_VAR_NO_REF; } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) { + /* For IS_VAR operands, SEND_VAL will pass through the operand without + * dereferencing, so it will use a by-ref pass if the call returned by-ref + * and a by-value pass if it returned by-value. */ opcode = ZEND_SEND_VAL; } else { opcode = ZEND_SEND_VAR; @@ -3589,16 +3592,17 @@ static uint32_t zend_compile_args( ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc) /* {{{ */ { if (fbc) { + ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)); if (fbc->type == ZEND_INTERNAL_FUNCTION && !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) { if (init_op->opcode == ZEND_INIT_FCALL && !zend_execute_internal) { - if (!(fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED))) { + if (!(fbc->common.fn_flags & ZEND_ACC_DEPRECATED)) { return ZEND_DO_ICALL; } else { return ZEND_DO_FCALL_BY_NAME; } } } else if (!(CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS)){ - if (zend_execute_ex == execute_ex && !(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) { + if (zend_execute_ex == execute_ex) { return ZEND_DO_UCALL; } } @@ -9500,7 +9504,16 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */ j = 0; last_const_node.op_type = IS_UNUSED; for (i = 0; i < list->children; i++) { - zend_compile_expr(&elem_node, list->child[i]); + zend_ast *encaps_var = list->child[i]; + if (encaps_var->attr & (ZEND_ENCAPS_VAR_DOLLAR_CURLY|ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR)) { + if (encaps_var->attr & ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR) { + zend_error(E_DEPRECATED, "Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead"); + } else { + zend_error(E_DEPRECATED, "Using ${var} in strings is deprecated, use {$var} instead"); + } + } + + zend_compile_expr(&elem_node, encaps_var); if (elem_node.op_type == IS_CONST) { convert_to_string(&elem_node.u.constant); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index b3e2d62737d51..038eb6543f19e 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -1077,6 +1077,10 @@ static zend_always_inline bool zend_check_arg_send_type(const zend_function *zf, /* Attribute for ternary inside parentheses */ #define ZEND_PARENTHESIZED_CONDITIONAL 1 +/* Attributes for ${} encaps var in strings */ +#define ZEND_ENCAPS_VAR_DOLLAR_CURLY (1<<0) +#define ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR (1<<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.h b/Zend/zend_constants.h index 77e8fa14509df..736dbb0091085 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -26,6 +26,7 @@ #define CONST_PERSISTENT (1<<0) /* Persistent */ #define CONST_NO_FILE_CACHE (1<<1) /* Can't be saved in file cache */ #define CONST_DEPRECATED (1<<2) /* Deprecated */ +#define CONST_OWNED (1<<3) /* constant should be destroyed together with class */ #define PHP_USER_CONSTANT 0x7fffff /* a constant defined in user space */ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index e9ecc5d6697d6..2a26e71847db2 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -558,7 +558,7 @@ ZEND_API zend_string *get_active_function_or_method_name(void) /* {{{ */ ZEND_API zend_string *get_function_or_method_name(const zend_function *func) /* {{{ */ { - if (func->common.scope) { + if (func->common.scope && func->common.function_name) { return zend_create_member_string(func->common.scope->name, func->common.function_name); } diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index eca8812325db8..fe4af53ecbdcc 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -655,21 +655,18 @@ ZEND_API void ZEND_FASTCALL zend_hash_iterators_advance(HashTable *ht, HashPosit } } -static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zend_string *key, bool known_hash) +/* Hash must be known and precomputed before */ +static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, const zend_string *key) { - zend_ulong h; + zend_ulong key_hash = ZSTR_H(key); uint32_t nIndex; uint32_t idx; Bucket *p, *arData; - if (known_hash) { - h = ZSTR_H(key); - ZEND_ASSERT(h != 0 && "Hash must be known"); - } else { - h = zend_string_hash_val(key); - } + ZEND_ASSERT(key_hash != 0 && "Hash must be known"); + arData = ht->arData; - nIndex = h | ht->nTableMask; + nIndex = key_hash | ht->nTableMask; idx = HT_HASH_EX(arData, nIndex); if (UNEXPECTED(idx == HT_INVALID_IDX)) { @@ -681,7 +678,7 @@ static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zen } while (1) { - if (p->h == ZSTR_H(key) && + if (p->h == key_hash && EXPECTED(p->key) && zend_string_equal_content(p->key, key)) { return p; @@ -758,7 +755,7 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s zend_hash_packed_to_hash(ht); } } else if ((flag & HASH_ADD_NEW) == 0 || ZEND_DEBUG) { - p = zend_hash_find_bucket(ht, key, 1); + p = zend_hash_find_bucket(ht, key); if (p) { zval *data; @@ -1166,7 +1163,8 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_set_bucket_key(HashTable *ht, Bucket *b, HT_ASSERT_RC1(ht); ZEND_ASSERT(!HT_IS_PACKED(ht)); - p = zend_hash_find_bucket(ht, key, 0); + (void)zend_string_hash_val(key); + p = zend_hash_find_bucket(ht, key); if (UNEXPECTED(p)) { return (p == b) ? &p->val : NULL; } @@ -2526,17 +2524,18 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *ke IS_CONSISTENT(ht); - p = zend_hash_find_bucket(ht, key, 0); + (void)zend_string_hash_val(key); + p = zend_hash_find_bucket(ht, key); return p ? &p->val : NULL; } -ZEND_API zval* ZEND_FASTCALL zend_hash_find_known_hash(const HashTable *ht, zend_string *key) +ZEND_API zval* ZEND_FASTCALL zend_hash_find_known_hash(const HashTable *ht, const zend_string *key) { Bucket *p; IS_CONSISTENT(ht); - p = zend_hash_find_bucket(ht, key, 1); + p = zend_hash_find_bucket(ht, key); return p ? &p->val : NULL; } diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index e004439029f6e..02244380da10f 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -179,7 +179,7 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulon ZEND_API zval* ZEND_FASTCALL _zend_hash_index_find(const HashTable *ht, zend_ulong h); /* The same as zend_hash_find(), but hash value of the key must be already calculated. */ -ZEND_API zval* ZEND_FASTCALL zend_hash_find_known_hash(const HashTable *ht, zend_string *key); +ZEND_API zval* ZEND_FASTCALL zend_hash_find_known_hash(const HashTable *ht, const zend_string *key); static zend_always_inline zval *zend_hash_find_ex(const HashTable *ht, zend_string *key, bool known_hash) { diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 2709fb5639186..c5660d258d88b 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -28,6 +28,7 @@ #include "zend_exceptions.h" #include "zend_enum.h" #include "zend_attributes.h" +#include "zend_constants.h" ZEND_API zend_class_entry* (*zend_inheritance_cache_get)(zend_class_entry *ce, zend_class_entry *parent, zend_class_entry **traits_and_interfaces) = NULL; ZEND_API zend_class_entry* (*zend_inheritance_cache_add)(zend_class_entry *ce, zend_class_entry *proto, zend_class_entry *parent, zend_class_entry **traits_and_interfaces, HashTable *dependencies) = NULL; @@ -1632,6 +1633,7 @@ static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, ct = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant)); memcpy(ct, c, sizeof(zend_class_constant)); c = ct; + Z_CONSTANT_FLAGS(c->value) |= CONST_OWNED; } } if (ce->type & ZEND_INTERNAL_CLASS) { @@ -2764,101 +2766,113 @@ 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) { - if (is_cacheable) { - if (zend_inheritance_cache_get && zend_inheritance_cache_add) { - zend_class_entry *ret = zend_inheritance_cache_get(ce, parent, traits_and_interfaces); - if (ret) { - if (traits_and_interfaces) { - free_alloca(traits_and_interfaces, use_heap); - } - zv = zend_hash_find_known_hash(CG(class_table), key); - Z_CE_P(zv) = ret; - return ret; - } - /* Make sure warnings (such as deprecations) thrown during inheritance - * will be recoreded in the inheritance cache. */ - zend_begin_record_errors(); - } else { - is_cacheable = 0; + 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); + if (ret) { + if (traits_and_interfaces) { + free_alloca(traits_and_interfaces, use_heap); + } + zv = zend_hash_find_known_hash(CG(class_table), key); + Z_CE_P(zv) = ret; + return ret; } - proto = ce; + + /* Make sure warnings (such as deprecations) thrown during inheritance + * will be recorded in the inheritance cache. */ + zend_begin_record_errors(); + } else { + is_cacheable = 0; } - /* Lazy class loading */ - ce = zend_lazy_class_load(ce); - zv = zend_hash_find_known_hash(CG(class_table), key); - Z_CE_P(zv) = ce; - } else if (ce->ce_flags & ZEND_ACC_FILE_CACHED) { - /* Lazy class loading */ - ce = zend_lazy_class_load(ce); - ce->ce_flags &= ~ZEND_ACC_FILE_CACHED; - zv = zend_hash_find_known_hash(CG(class_table), key); - Z_CE_P(zv) = ce; + proto = ce; } - if (CG(unlinked_uses)) { - zend_hash_index_del(CG(unlinked_uses), (zend_long)(zend_uintptr_t) ce); - } + zend_try { + if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { + /* Lazy class loading */ + ce = zend_lazy_class_load(ce); + zv = zend_hash_find_known_hash(CG(class_table), key); + Z_CE_P(zv) = ce; + } else if (ce->ce_flags & ZEND_ACC_FILE_CACHED) { + /* Lazy class loading */ + ce = zend_lazy_class_load(ce); + ce->ce_flags &= ~ZEND_ACC_FILE_CACHED; + zv = zend_hash_find_known_hash(CG(class_table), key); + Z_CE_P(zv) = ce; + } - orig_linking_class = CG(current_linking_class); - CG(current_linking_class) = is_cacheable ? ce : NULL; + if (CG(unlinked_uses)) { + zend_hash_index_del(CG(unlinked_uses), (zend_long)(zend_uintptr_t) ce); + } - if (ce->ce_flags & ZEND_ACC_ENUM) { - /* Only register builtin enum methods during inheritance to avoid persisting them in - * opcache. */ - zend_enum_register_funcs(ce); - } + orig_linking_class = CG(current_linking_class); + CG(current_linking_class) = is_cacheable ? ce : NULL; - if (parent) { - if (!(parent->ce_flags & ZEND_ACC_LINKED)) { - add_dependency_obligation(ce, parent); + if (ce->ce_flags & ZEND_ACC_ENUM) { + /* Only register builtin enum methods during inheritance to avoid persisting them in + * opcache. */ + zend_enum_register_funcs(ce); } - zend_do_inheritance(ce, parent); - } - if (ce->num_traits) { - zend_do_bind_traits(ce, traits_and_interfaces); - } - if (ce->num_interfaces) { - /* Also copy the parent interfaces here, so we don't need to reallocate later. */ - uint32_t num_parent_interfaces = parent ? parent->num_interfaces : 0; - zend_class_entry **interfaces = emalloc( - sizeof(zend_class_entry *) * (ce->num_interfaces + num_parent_interfaces)); - if (num_parent_interfaces) { - memcpy(interfaces, parent->interfaces, - sizeof(zend_class_entry *) * num_parent_interfaces); + if (parent) { + if (!(parent->ce_flags & ZEND_ACC_LINKED)) { + add_dependency_obligation(ce, parent); + } + zend_do_inheritance(ce, parent); + } + if (ce->num_traits) { + zend_do_bind_traits(ce, traits_and_interfaces); } - memcpy(interfaces + num_parent_interfaces, traits_and_interfaces + ce->num_traits, - sizeof(zend_class_entry *) * ce->num_interfaces); + if (ce->num_interfaces) { + /* Also copy the parent interfaces here, so we don't need to reallocate later. */ + uint32_t num_parent_interfaces = parent ? parent->num_interfaces : 0; + zend_class_entry **interfaces = emalloc( + sizeof(zend_class_entry *) * (ce->num_interfaces + num_parent_interfaces)); - zend_do_implement_interfaces(ce, interfaces); - } else if (parent && parent->num_interfaces) { - zend_do_inherit_interfaces(ce, parent); - } - if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT)) - && (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) - ) { - zend_verify_abstract_class(ce); - } - if (ce->ce_flags & ZEND_ACC_ENUM) { - zend_verify_enum(ce); - } + if (num_parent_interfaces) { + memcpy(interfaces, parent->interfaces, + sizeof(zend_class_entry *) * num_parent_interfaces); + } + memcpy(interfaces + num_parent_interfaces, traits_and_interfaces + ce->num_traits, + sizeof(zend_class_entry *) * ce->num_interfaces); - /* Normally Stringable is added during compilation. However, if it is imported from a trait, - * we need to explicilty add the interface here. */ - if (ce->__tostring && !(ce->ce_flags & ZEND_ACC_TRAIT) + zend_do_implement_interfaces(ce, interfaces); + } else if (parent && parent->num_interfaces) { + zend_do_inherit_interfaces(ce, parent); + } + if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT)) + && (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) + ) { + zend_verify_abstract_class(ce); + } + if (ce->ce_flags & ZEND_ACC_ENUM) { + zend_verify_enum(ce); + } + + /* Normally Stringable is added during compilation. However, if it is imported from a trait, + * we need to explicilty add the interface here. */ + if (ce->__tostring && !(ce->ce_flags & ZEND_ACC_TRAIT) && !zend_class_implements_interface(ce, zend_ce_stringable)) { - ZEND_ASSERT(ce->__tostring->common.fn_flags & ZEND_ACC_TRAIT_CLONE); - ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES; - ce->num_interfaces++; - ce->interfaces = perealloc(ce->interfaces, - sizeof(zend_class_entry *) * ce->num_interfaces, ce->type == ZEND_INTERNAL_CLASS); - ce->interfaces[ce->num_interfaces - 1] = zend_ce_stringable; - do_interface_implementation(ce, zend_ce_stringable); - } + ZEND_ASSERT(ce->__tostring->common.fn_flags & ZEND_ACC_TRAIT_CLONE); + ce->ce_flags |= ZEND_ACC_RESOLVED_INTERFACES; + ce->num_interfaces++; + ce->interfaces = perealloc(ce->interfaces, + sizeof(zend_class_entry *) * ce->num_interfaces, ce->type == ZEND_INTERNAL_CLASS); + ce->interfaces[ce->num_interfaces - 1] = zend_ce_stringable; + do_interface_implementation(ce, zend_ce_stringable); + } + + zend_build_properties_info_table(ce); + } zend_catch { + /* Do not leak recorded errors to the next linked class. */ + if (!orig_record_errors) { + EG(record_errors) = false; + zend_free_recorded_errors(); + } + zend_bailout(); + } zend_end_try(); - zend_build_properties_info_table(ce); EG(record_errors) = orig_record_errors; if (!(ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE)) { @@ -3027,22 +3041,29 @@ 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; - if (is_cacheable) { - zend_begin_record_errors(); - } + zend_try{ + if (is_cacheable) { + zend_begin_record_errors(); + } - zend_do_inheritance_ex(ce, parent_ce, status == INHERITANCE_SUCCESS); - if (parent_ce && parent_ce->num_interfaces) { - zend_do_inherit_interfaces(ce, parent_ce); - } - zend_build_properties_info_table(ce); - if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { - zend_verify_abstract_class(ce); - } - ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE)); - ce->ce_flags |= ZEND_ACC_LINKED; + zend_do_inheritance_ex(ce, parent_ce, status == INHERITANCE_SUCCESS); + if (parent_ce && parent_ce->num_interfaces) { + zend_do_inherit_interfaces(ce, parent_ce); + } + zend_build_properties_info_table(ce); + if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { + zend_verify_abstract_class(ce); + } + ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE)); + ce->ce_flags |= ZEND_ACC_LINKED; + + CG(current_linking_class) = orig_linking_class; + } zend_catch { + EG(record_errors) = false; + zend_free_recorded_errors(); + zend_bailout(); + } zend_end_try(); - CG(current_linking_class) = orig_linking_class; EG(record_errors) = false; if (is_cacheable) { diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index 3ce92cc509523..f4f17c7ba18ef 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -23,6 +23,7 @@ #include "zend_alloc.h" #include "zend_operators.h" #include "zend_strtod.h" +#include "zend_modules.h" static HashTable *registered_zend_ini_directives; @@ -194,7 +195,7 @@ ZEND_API void zend_ini_sort_entries(void) /* {{{ */ /* * Registration / unregistration */ -ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number) /* {{{ */ +ZEND_API zend_result zend_register_ini_entries_ex(const zend_ini_entry_def *ini_entry, int module_number, int module_type) /* {{{ */ { zend_ini_entry *p; zval *default_value; @@ -210,7 +211,10 @@ ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_ent * lead to death. */ if (directives != EG(ini_directives)) { + ZEND_ASSERT(module_type == MODULE_TEMPORARY); directives = EG(ini_directives); + } else { + ZEND_ASSERT(module_type == MODULE_PERSISTENT); } #endif @@ -234,7 +238,7 @@ ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_ent if (p->name) { zend_string_release_ex(p->name, 1); } - zend_unregister_ini_entries(module_number); + zend_unregister_ini_entries_ex(module_number, module_type); return FAILURE; } if (((default_value = zend_get_configuration_directive(p->name)) != NULL) && @@ -255,9 +259,46 @@ ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_ent } /* }}} */ +ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number) /* {{{ */ +{ + zend_module_entry *module; + + /* Module is likely to be the last one in the list */ + ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) { + if (module->module_number == module_number) { + return zend_register_ini_entries_ex(ini_entry, module_number, module->type); + } + } ZEND_HASH_FOREACH_END(); + + return FAILURE; +} +/* }}} */ + +ZEND_API void zend_unregister_ini_entries_ex(int module_number, int module_type) /* {{{ */ +{ + static HashTable *ini_directives; + + if (module_type == MODULE_TEMPORARY) { + ini_directives = EG(ini_directives); + } else { + ini_directives = registered_zend_ini_directives; + } + + zend_hash_apply_with_argument(ini_directives, zend_remove_ini_entries, (void *) &module_number); +} +/* }}} */ + ZEND_API void zend_unregister_ini_entries(int module_number) /* {{{ */ { - zend_hash_apply_with_argument(registered_zend_ini_directives, zend_remove_ini_entries, (void *) &module_number); + zend_module_entry *module; + + /* Module is likely to be the last one in the list */ + ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) { + if (module->module_number == module_number) { + zend_unregister_ini_entries_ex(module_number, module->type); + return; + } + } ZEND_HASH_FOREACH_END(); } /* }}} */ diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h index 590ff09cef0c5..23258ec0ca8b5 100644 --- a/Zend/zend_ini.h +++ b/Zend/zend_ini.h @@ -72,7 +72,9 @@ ZEND_API void zend_copy_ini_directives(void); ZEND_API void zend_ini_sort_entries(void); ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number); +ZEND_API zend_result zend_register_ini_entries_ex(const zend_ini_entry_def *ini_entry, int module_number, int module_type); ZEND_API void zend_unregister_ini_entries(int module_number); +ZEND_API void zend_unregister_ini_entries_ex(int module_number, int module_type); 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); ZEND_API zend_result zend_alter_ini_entry_ex(zend_string *name, zend_string *new_value, int modify_type, int stage, bool force_change); @@ -148,8 +150,8 @@ END_EXTERN_C() #define INI_ORIG_STR(name) zend_ini_string((name), strlen(name), 1) #define INI_ORIG_BOOL(name) ((bool) INI_ORIG_INT(name)) -#define REGISTER_INI_ENTRIES() zend_register_ini_entries(ini_entries, module_number) -#define UNREGISTER_INI_ENTRIES() zend_unregister_ini_entries(module_number) +#define REGISTER_INI_ENTRIES() zend_register_ini_entries_ex(ini_entries, module_number, type) +#define UNREGISTER_INI_ENTRIES() zend_unregister_ini_entries_ex(module_number, type) #define DISPLAY_INI_ENTRIES() display_ini_entries(zend_module) #define REGISTER_INI_DISPLAYER(name, displayer) zend_ini_register_displayer((name), strlen(name), displayer) diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index f6ba5465abebb..01adacf065ef4 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -1490,11 +1490,11 @@ encaps_var: { $$ = zend_ast_create(ZEND_AST_NULLSAFE_PROP, zend_ast_create(ZEND_AST_VAR, $1), $3); } | T_DOLLAR_OPEN_CURLY_BRACES expr '}' - { $$ = zend_ast_create(ZEND_AST_VAR, $2); } + { $$ = zend_ast_create_ex(ZEND_AST_VAR, ZEND_ENCAPS_VAR_DOLLAR_CURLY_VAR_VAR, $2); } | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' - { $$ = zend_ast_create(ZEND_AST_VAR, $2); } + { $$ = zend_ast_create_ex(ZEND_AST_VAR, ZEND_ENCAPS_VAR_DOLLAR_CURLY, $2); } | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' - { $$ = zend_ast_create(ZEND_AST_DIM, + { $$ = zend_ast_create_ex(ZEND_AST_DIM, ZEND_ENCAPS_VAR_DOLLAR_CURLY, zend_ast_create(ZEND_AST_VAR, $2), $4); } | T_CURLY_OPEN variable '}' { $$ = $2; } ; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 9e27c2fea142b..35f84a6d9356a 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -26,6 +26,7 @@ #include "zend_extensions.h" #include "zend_API.h" #include "zend_sort.h" +#include "zend_constants.h" #include "zend_vm.h" @@ -255,7 +256,7 @@ ZEND_API void zend_cleanup_mutable_class_data(zend_class_entry *ce) zend_class_constant *c; ZEND_HASH_MAP_FOREACH_PTR(constants_table, c) { - if (c->ce == ce) { + if (c->ce == ce || (Z_CONSTANT_FLAGS(c->value) & CONST_OWNED)) { zval_ptr_dtor_nogc(&c->value); } } ZEND_HASH_FOREACH_END(); @@ -387,7 +388,7 @@ ZEND_API void destroy_zend_class(zval *zv) zend_class_constant *c; ZEND_HASH_MAP_FOREACH_PTR(&ce->constants_table, c) { - if (c->ce == ce) { + if (c->ce == ce || (Z_CONSTANT_FLAGS(c->value) & CONST_OWNED)) { zval_ptr_dtor_nogc(&c->value); if (c->doc_comment) { zend_string_release_ex(c->doc_comment, 0); @@ -751,31 +752,29 @@ static void emit_live_range( while (def_opline + 1 < use_opline) { def_opline++; start++; - if (def_opline->opcode == ZEND_DO_FCALL) { - if (level == 0) { + switch (def_opline->opcode) { + case ZEND_INIT_FCALL: + case ZEND_INIT_FCALL_BY_NAME: + case ZEND_INIT_NS_FCALL_BY_NAME: + case ZEND_INIT_DYNAMIC_CALL: + case ZEND_INIT_USER_CALL: + case ZEND_INIT_METHOD_CALL: + case ZEND_INIT_STATIC_METHOD_CALL: + case ZEND_NEW: + level++; + break; + case ZEND_DO_FCALL: + case ZEND_DO_FCALL_BY_NAME: + case ZEND_DO_ICALL: + case ZEND_DO_UCALL: + if (level == 0) { + goto done; + } + level--; break; - } - level--; - } else { - switch (def_opline->opcode) { - case ZEND_INIT_FCALL: - case ZEND_INIT_FCALL_BY_NAME: - case ZEND_INIT_NS_FCALL_BY_NAME: - case ZEND_INIT_DYNAMIC_CALL: - case ZEND_INIT_USER_CALL: - case ZEND_INIT_METHOD_CALL: - case ZEND_INIT_STATIC_METHOD_CALL: - case ZEND_NEW: - level++; - break; - case ZEND_DO_ICALL: - case ZEND_DO_UCALL: - case ZEND_DO_FCALL_BY_NAME: - level--; - break; - } } } +done: emit_live_range_raw(op_array, var_num, ZEND_LIVE_NEW, orig_start + 1, start + 1); if (start + 1 == end) { /* Trivial live-range, no need to store it. */ diff --git a/Zend/zend_stream.c b/Zend/zend_stream.c index ae2c734b09b4e..8e11841ad2658 100644 --- a/Zend/zend_stream.c +++ b/Zend/zend_stream.c @@ -39,7 +39,7 @@ static void zend_stream_stdio_closer(void *handle) /* {{{ */ static size_t zend_stream_stdio_fsizer(void *handle) /* {{{ */ { - zend_stat_t buf; + zend_stat_t buf = {0}; if (handle && zend_fstat(fileno((FILE*)handle), &buf) == 0) { #ifdef S_ISREG if (!S_ISREG(buf.st_mode)) { diff --git a/Zend/zend_string.c b/Zend/zend_string.c index 1284e908a55b1..b4214bc38cd6f 100644 --- a/Zend/zend_string.c +++ b/Zend/zend_string.c @@ -366,20 +366,20 @@ ZEND_API void zend_interned_strings_switch_storage(bool request) /* Even if we don't build with valgrind support, include the symbol so that valgrind available * only at runtime will not result in false positives. */ -#ifndef HAVE_VALGRIND +#ifndef I_REPLACE_SONAME_FNNAME_ZU # define I_REPLACE_SONAME_FNNAME_ZU(soname, fnname) _vgr00000ZU_ ## soname ## _ ## fnname #endif -ZEND_API bool ZEND_FASTCALL I_REPLACE_SONAME_FNNAME_ZU(NONE,zend_string_equal_val)(zend_string *s1, zend_string *s2) +ZEND_API bool ZEND_FASTCALL I_REPLACE_SONAME_FNNAME_ZU(NONE,zend_string_equal_val)(const zend_string *s1, const zend_string *s2) { return !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1)); } #if defined(__GNUC__) && defined(__i386__) -ZEND_API bool ZEND_FASTCALL zend_string_equal_val(zend_string *s1, zend_string *s2) +ZEND_API bool ZEND_FASTCALL zend_string_equal_val(const zend_string *s1, const zend_string *s2) { - char *ptr = ZSTR_VAL(s1); - size_t delta = (char*)s2 - (char*)s1; + const char *ptr = ZSTR_VAL(s1); + size_t delta = (const char*)s2 - (const char*)s1; size_t len = ZSTR_LEN(s1); zend_ulong ret; @@ -414,10 +414,10 @@ ZEND_API bool ZEND_FASTCALL zend_string_equal_val(zend_string *s1, zend_string * } #elif defined(__GNUC__) && defined(__x86_64__) && !defined(__ILP32__) -ZEND_API bool ZEND_FASTCALL zend_string_equal_val(zend_string *s1, zend_string *s2) +ZEND_API bool ZEND_FASTCALL zend_string_equal_val(const zend_string *s1, const zend_string *s2) { - char *ptr = ZSTR_VAL(s1); - size_t delta = (char*)s2 - (char*)s1; + const char *ptr = ZSTR_VAL(s1); + size_t delta = (const char*)s2 - (const char*)s1; size_t len = ZSTR_LEN(s1); zend_ulong ret; diff --git a/Zend/zend_string.h b/Zend/zend_string.h index 06a4edc01ae51..1a1c0cd7a67bf 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -346,21 +346,21 @@ static zend_always_inline bool zend_string_equals_cstr(const zend_string *s1, co #if defined(__GNUC__) && (defined(__i386__) || (defined(__x86_64__) && !defined(__ILP32__))) BEGIN_EXTERN_C() -ZEND_API bool ZEND_FASTCALL zend_string_equal_val(zend_string *s1, zend_string *s2); +ZEND_API bool ZEND_FASTCALL zend_string_equal_val(const zend_string *s1, const zend_string *s2); END_EXTERN_C() #else -static zend_always_inline bool zend_string_equal_val(zend_string *s1, zend_string *s2) +static zend_always_inline bool zend_string_equal_val(const zend_string *s1, const zend_string *s2) { return !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1)); } #endif -static zend_always_inline bool zend_string_equal_content(zend_string *s1, zend_string *s2) +static zend_always_inline bool zend_string_equal_content(const zend_string *s1, const zend_string *s2) { return ZSTR_LEN(s1) == ZSTR_LEN(s2) && zend_string_equal_val(s1, s2); } -static zend_always_inline bool zend_string_equals(zend_string *s1, zend_string *s2) +static zend_always_inline bool zend_string_equals(const zend_string *s1, const zend_string *s2) { return s1 == s2 || zend_string_equal_content(s1, s2); } diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index d8a9046d04d8b..404a5cfea4c33 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -502,7 +502,7 @@ static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, tim do { free(pathw); } while(0); #else - zend_stat_t st; + zend_stat_t st = {0}; #endif realpath_cache_bucket *bucket; char *tmp; diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index ed3b9fecf1d8a..f878425ab65be 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -2865,7 +2865,7 @@ function gen_vm($def, $skel) { out($f, "\t\t\t\t\tbreak;\n"); out($f, "\t\t\t\t}\n"); } - out($f, "\t\t\t\tspec = ${spec_dsc['spec_code']};\n"); + out($f, "\t\t\t\tspec = {$spec_dsc['spec_code']};\n"); if (isset($spec_dsc["spec"]["COMMUTATIVE"]) && !isset($dsc["spec"]["COMMUTATIVE"])) { out($f, "\t\t\t\tif (op->op1_type < op->op2_type) {\n"); out($f, "\t\t\t\t\tzend_swap_operands(op);\n"); diff --git a/appveyor/setup_hmailserver.php b/appveyor/setup_hmailserver.php new file mode 100644 index 0000000000000..fe661756ad6ca --- /dev/null +++ b/appveyor/setup_hmailserver.php @@ -0,0 +1,21 @@ +authenticate("Administrator", ""); + +$domain = $hmail->Domains->Add(); +$domain->Name = IMAP_MAIL_DOMAIN; +$domain->Active = true; +$domain->Save(); + +$accounts = $domain->accounts(); + +foreach (IMAP_USERS as $user) { + $account = $accounts->Add(); + $account->Address = "$user@" . IMAP_MAIL_DOMAIN; + $account->Password = IMAP_MAILBOX_PASSWORD; + $account->Active = true; + $account->Save(); +} diff --git a/appveyor/test_task.bat b/appveyor/test_task.bat index fb58e9bc438e6..e19a6f6acaab9 100644 --- a/appveyor/test_task.bat +++ b/appveyor/test_task.bat @@ -89,9 +89,19 @@ if not exist "%PHP_BUILD_CACHE_ENCHANT_DICT_DIR%\en_US.aff" ( mkdir %LOCALAPPDATA%\enchant\hunspell copy %PHP_BUILD_CACHE_ENCHANT_DICT_DIR%\* %LOCALAPPDATA%\enchant\hunspell +rem prepare for snmp +set MIBDIRS=%DEPS_DIR%\share\mibs +start %DEPS_DIR%\bin\snmpd.exe -C -c %APPVEYOR_BUILD_FOLDER%\ext\snmp\tests\snmpd.conf -Ln + set PHP_BUILD_DIR=%PHP_BUILD_OBJ_DIR%\Release if "%THREAD_SAFE%" equ "1" set PHP_BUILD_DIR=%PHP_BUILD_DIR%_TS +rem prepare for mail +curl -sLo hMailServer.exe https://www.hmailserver.com/download_file/?downloadid=271 +hMailServer.exe /verysilent +cd %APPVEYOR_BUILD_FOLDER% +%PHP_BUILD_DIR%\php.exe -dextension_dir=%PHP_BUILD_DIR% -dextension=com_dotnet appveyor\setup_hmailserver.php + mkdir %PHP_BUILD_DIR%\test_file_cache rem generate php.ini echo extension_dir=%PHP_BUILD_DIR% > %PHP_BUILD_DIR%\php.ini @@ -101,7 +111,7 @@ rem work-around for some spawned PHP processes requiring OpenSSL echo extension=php_openssl.dll >> %PHP_BUILD_DIR%\php.ini rem remove ext dlls for which tests are not supported -for %%i in (imap ldap oci8_12c pdo_firebird pdo_oci snmp) do ( +for %%i in (ldap oci8_12c pdo_firebird pdo_oci) do ( del %PHP_BUILD_DIR%\php_%%i.dll ) @@ -116,6 +126,8 @@ nmake test TESTS="%OPCACHE_OPTS% -q --offline --show-diff --show-slow 1000 --set set EXIT_CODE=%errorlevel% +taskkill /f /im snmpd.exe + appveyor PushArtifact %TEST_PHP_JUNIT% if %EXIT_CODE% GEQ 1 ( diff --git a/azure/configure.yml b/azure/configure.yml index a7a65845e1a56..667610b3a3356 100644 --- a/azure/configure.yml +++ b/azure/configure.yml @@ -50,6 +50,7 @@ steps: --enable-sysvmsg \ --with-ffi \ --enable-zend-test \ + --enable-dl-test=shared \ --with-ldap \ --with-ldap-sasl \ --with-password-argon2 \ diff --git a/azure/i386/job.yml b/azure/i386/job.yml index 6fdfc539fc0c2..6f945aef36c94 100644 --- a/azure/i386/job.yml +++ b/azure/i386/job.yml @@ -62,6 +62,7 @@ jobs: --enable-sysvmsg \ --with-ffi \ --enable-zend-test \ + --enable-dl-test=shared \ --with-mhash \ --with-sodium \ --enable-dba \ diff --git a/azure/libmysqlclient_job.yml b/azure/libmysqlclient_job.yml index be71b20a3954a..4eb998014c316 100644 --- a/azure/libmysqlclient_job.yml +++ b/azure/libmysqlclient_job.yml @@ -28,8 +28,8 @@ jobs: # libmysql: mysql-5.6.49-linux-glibc2.12-x86_64.tar.gz - template: libmysqlclient_test.yml parameters: - configurationName: ${{ parameters.configurationName }} - MySQL 5.7.35 - libmysql: mysql-5.7.35-linux-glibc2.12-x86_64.tar.gz + configurationName: ${{ parameters.configurationName }} - MySQL 5.7.38 + libmysql: mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz - template: libmysqlclient_test.yml parameters: configurationName: ${{ parameters.configurationName }} - MySQL 8.0.27 diff --git a/azure/msan_job.yml b/azure/msan_job.yml index 919547b11858c..28f9dbe2015a0 100644 --- a/azure/msan_job.yml +++ b/azure/msan_job.yml @@ -49,6 +49,7 @@ jobs: --enable-calendar \ --enable-ftp \ --enable-zend-test \ + --enable-dl-test=shared \ --enable-werror \ --enable-memory-sanitizer \ --with-config-file-path=/etc \ diff --git a/build/Makefile.global b/build/Makefile.global index 3c44a52693ae2..dee5fa5ecde73 100644 --- a/build/Makefile.global +++ b/build/Makefile.global @@ -75,7 +75,10 @@ PHP_TEST_SETTINGS = -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit= PHP_TEST_SHARED_EXTENSIONS = ` \ if test "x$(PHP_MODULES)" != "x"; then \ for i in $(PHP_MODULES)""; do \ - . $$i; $(top_srcdir)/build/shtool echo -n -- " -d extension=$$dlname"; \ + . $$i; \ + if test "x$$dlname" != "xdl_test.so"; then \ + $(top_srcdir)/build/shtool echo -n -- " -d extension=$$dlname"; \ + fi; \ done; \ fi; \ if test "x$(PHP_ZEND_EX)" != "x"; then \ @@ -134,6 +137,7 @@ distclean: clean prof-gen: CCACHE_DISABLE=1 $(MAKE) PROF_FLAGS=-fprofile-generate all + find . -name \*.gcda | xargs rm -f prof-clean: find . -name \*.lo -o -name \*.o | xargs rm -f diff --git a/build/gen_stub.php b/build/gen_stub.php index 6856b5610e92c..bd8166d3afe0d 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -286,6 +286,10 @@ public function toTypeCode(): string { return "IS_STATIC"; case "never": return "IS_NEVER"; + case "null": + return "IS_NULL"; + case "false": + return "IS_FALSE"; default: throw new Exception("Not implemented: $this->name"); } @@ -400,7 +404,6 @@ public function toEscapedName(): string { } public function toVarEscapedName(): string { - $name = str_replace('_', '__', $this->name); return str_replace('\\', '_', $this->name); } @@ -506,6 +509,10 @@ function(SimpleType $type) { public function tryToSimpleType(): ?SimpleType { $withoutNull = $this->getWithoutNull(); + /* type has only null */ + if (count($withoutNull->types) === 0) { + return $this->types[0]; + } if (count($withoutNull->types) === 1) { return $withoutNull->types[0]; } @@ -1477,7 +1484,7 @@ public function getDeclaration(): string { } else { $escapedClassName = $arginfoType->classTypes[0]->toEscapedName(); $varEscapedClassName = $arginfoType->classTypes[0]->toVarEscapedName(); - $code .= "\tzend_string *property_{$propertyName}_class_{$varEscapedClassName} = zend_string_init(\"{$escapedClassName}\", sizeof(\"${escapedClassName}\")-1, 1);\n"; + $code .= "\tzend_string *property_{$propertyName}_class_{$varEscapedClassName} = zend_string_init(\"{$escapedClassName}\", sizeof(\"{$escapedClassName}\")-1, 1);\n"; $typeCode = "(zend_type) ZEND_TYPE_INIT_CLASS(property_{$propertyName}_class_{$varEscapedClassName}, 0, " . $arginfoType->toTypeMask() . ")"; } diff --git a/configure.ac b/configure.ac index c2886439afa6b..29dd3b0437a4f 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.2.0-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.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 @@ -364,6 +364,7 @@ PHP_CHECK_FUNC(socketpair, socket, network) PHP_CHECK_FUNC(htonl, socket, network) PHP_CHECK_FUNC(gethostname, nsl, network) PHP_CHECK_FUNC(gethostbyaddr, nsl, network) +PHP_CHECK_FUNC(copy_file_range) PHP_CHECK_FUNC(dlopen, dl, root) PHP_CHECK_FUNC(dlsym, dl, root) if test "$ac_cv_func_dlopen" = "yes"; then @@ -1610,6 +1611,7 @@ PHP_ADD_SOURCES(TSRM, TSRM.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c \ fopen_wrappers.c alloca.c php_scandir.c \ + php_ini_builder.c \ php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ strlcat.c explicit_bzero.c reentrancy.c php_variables.c php_ticks.c \ network.c php_open_temporary_file.c \ diff --git a/docs/release-process.md b/docs/release-process.md index f9bb1d1fe71aa..b73274d028f7c 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -4,7 +4,7 @@ A release managers role includes making packaged source code from the canonical available according to their release schedule. The release schedule for their branch is available on a Wiki page, for example - [PHP 8.0 release schedule](https://wiki.php.net/todo/php80) +[PHP 8.0 release schedule](https://wiki.php.net/todo/php80) There are two types of release: @@ -15,8 +15,8 @@ The process of making packaged source available and announcing availability is e in detail below. The process differs slightly for non-stable and stable releases. Before a release manager can begin their work, there are several things that must happen, -explained at the end of this document in - [New Release Manager Checklist](#new-release-manager-checklist). +explained at the end of this document in +[New Release Manager Checklist](#new-release-manager-checklist). ## General notes and tips @@ -422,8 +422,9 @@ branch: next minor or major release, issue a call for volunteers on internals@lists.php.net (cf. http://news.php.net/php.internals/98652). - 2. Make sure that there are two or more volunteers, and hold a vote if - necessary (see + 2. Make sure that there are two or more volunteers. Typically, one should be a + veteran release manager (having previously served as a php-src release manager), + while the other one (or two) should be rookies. Hold a vote if necessary (see https://wiki.php.net/rfc/releaseprocess#release_managers_selection). 3. Help the new release managers with their first steps. diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index 3af382dee4243..8e55bf92bed76 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -393,9 +393,7 @@ PHP_FUNCTION(bzopen) RETURN_FALSE; } break; - default: - /* not reachable */ - break; + EMPTY_SWITCH_DEFAULT_CASE(); } if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_FD, (void *) &fd, REPORT_ERRORS)) { diff --git a/ext/curl/curl_private.h b/ext/curl/curl_private.h index 842ee5fb79c2a..edf19c86f8354 100644 --- a/ext/curl/curl_private.h +++ b/ext/curl/curl_private.h @@ -73,9 +73,10 @@ typedef struct { php_curl_read *read; zval std_err; php_curl_callback *progress; -#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ - php_curl_callback *fnmatch; +#if LIBCURL_VERSION_NUM >= 0x072000 + php_curl_callback *xferinfo; #endif + php_curl_callback *fnmatch; } php_curl_handlers; struct _php_curl_error { diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 0062586c64ec9..7fee37770f7d3 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -456,6 +456,9 @@ PHP_MINIT_FUNCTION(curl) REGISTER_CURL_CONSTANT(CURLOPT_VERBOSE); REGISTER_CURL_CONSTANT(CURLOPT_WRITEFUNCTION); REGISTER_CURL_CONSTANT(CURLOPT_WRITEHEADER); +#if LIBCURL_VERSION_NUM >= 0x072000 + REGISTER_CURL_CONSTANT(CURLOPT_XFERINFOFUNCTION); +#endif /* */ REGISTER_CURL_CONSTANT(CURLE_ABORTED_BY_CALLBACK); @@ -1287,11 +1290,15 @@ static HashTable *curl_get_gc(zend_object *object, zval **table, int *n) zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.progress->func_name); } -#if LIBCURL_VERSION_NUM >= 0x071500 +#if LIBCURL_VERSION_NUM >= 0x072000 + if (curl->handlers.xferinfo) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.xferinfo->func_name); + } +#endif + if (curl->handlers.fnmatch) { zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.fnmatch->func_name); } -#endif zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers.std_err); zend_get_gc_buffer_add_zval(gc_buffer, &curl->private_data); @@ -1496,6 +1503,56 @@ static size_t curl_progress(void *clientp, double dltotal, double dlnow, double } /* }}} */ +#if LIBCURL_VERSION_NUM >= 0x072000 +/* {{{ 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) +{ + php_curl *ch = (php_curl *)clientp; + php_curl_callback *t = ch->handlers.xferinfo; + size_t rval = 0; + +#if PHP_CURL_DEBUG + fprintf(stderr, "curl_xferinfo() called\n"); + fprintf(stderr, "clientp = %x, dltotal = %ld, dlnow = %ld, ultotal = %ld, ulnow = %ld\n", clientp, dltotal, dlnow, ultotal, ulnow); +#endif + + zval argv[5]; + zval retval; + zend_result error; + zend_fcall_info fci; + + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); + ZVAL_LONG(&argv[1], dltotal); + ZVAL_LONG(&argv[2], dlnow); + ZVAL_LONG(&argv[3], ultotal); + ZVAL_LONG(&argv[4], ulnow); + + fci.size = sizeof(fci); + ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); + fci.object = NULL; + fci.retval = &retval; + fci.param_count = 5; + fci.params = argv; + fci.named_params = NULL; + + ch->in_callback = 1; + error = zend_call_function(&fci, &t->fci_cache); + ch->in_callback = 0; + if (error == FAILURE) { + php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_XFERINFOFUNCTION"); + } else if (!Z_ISUNDEF(retval)) { + _php_curl_verify_handlers(ch, /* reporterror */ true); + if (0 != zval_get_long(&retval)) { + rval = 1; + } + } + zval_ptr_dtor(&argv[0]); + return rval; +} +/* }}} */ +#endif + /* {{{ curl_read */ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) { @@ -1753,6 +1810,9 @@ void init_curl_handle(php_curl *ch) ch->handlers.write_header = ecalloc(1, sizeof(php_curl_write)); ch->handlers.read = ecalloc(1, sizeof(php_curl_read)); ch->handlers.progress = NULL; +#if LIBCURL_VERSION_NUM >= 0x072000 + ch->handlers.xferinfo = NULL; +#endif ch->handlers.fnmatch = NULL; ch->clone = emalloc(sizeof(uint32_t)); *ch->clone = 1; @@ -1925,6 +1985,16 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, (void *) ch); } +#if LIBCURL_VERSION_NUM >= 0x072000 + if (source->handlers.xferinfo) { + ch->handlers.xferinfo = ecalloc(1, sizeof(php_curl_callback)); + if (!Z_ISUNDEF(source->handlers.xferinfo->func_name)) { + ZVAL_COPY(&ch->handlers.xferinfo->func_name, &source->handlers.xferinfo->func_name); + } + curl_easy_setopt(ch->cp, CURLOPT_XFERINFODATA, (void *) ch); + } +#endif + if (source->handlers.fnmatch) { ch->handlers.fnmatch = ecalloc(1, sizeof(php_curl_callback)); if (!Z_ISUNDEF(source->handlers.fnmatch->func_name)) { @@ -1991,15 +2061,17 @@ static void free_cb(void *arg) /* {{{ */ /* }}} */ #endif +#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ static inline CURLcode add_simple_field(curl_mime *mime, zend_string *string_key, zval *current) +#else +static inline CURLcode add_simple_field(struct HttpPost **first, struct HttpPost **last, zend_string *string_key, zval *current) +#endif { CURLcode error = CURLE_OK; #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ curl_mimepart *part; CURLcode form_error; #else - struct HttpPost *first = NULL; - struct HttpPost *last = NULL; CURLFORMcode form_error; #endif zend_string *postval, *tmp_postval; @@ -2021,7 +2093,7 @@ static inline CURLcode add_simple_field(curl_mime *mime, zend_string *string_key /* The arguments after _NAMELENGTH and _CONTENTSLENGTH * must be explicitly cast to long in curl_formadd * use since curl needs a long not an int. */ - form_error = curl_formadd(&first, &last, + form_error = curl_formadd(first, last, CURLFORM_COPYNAME, ZSTR_VAL(string_key), CURLFORM_NAMELENGTH, ZSTR_LEN(string_key), CURLFORM_COPYCONTENTS, ZSTR_VAL(postval), @@ -2233,14 +2305,22 @@ static inline zend_result build_mime_structure_from_hash(php_curl *ch, zval *zpo zval *current_element; ZEND_HASH_FOREACH_VAL(HASH_OF(current), current_element) { +#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ add_simple_field(mime, string_key, current_element); +#else + add_simple_field(&first, &last, string_key, current_element); +#endif } ZEND_HASH_FOREACH_END(); zend_string_release_ex(string_key, 0); continue; } +#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ add_simple_field(mime, string_key, current); +#else + add_simple_field(&first, &last, string_key, current); +#endif zend_string_release_ex(string_key, 0); } ZEND_HASH_FOREACH_END(); @@ -2884,6 +2964,20 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue ch->handlers.write->method = PHP_CURL_USER; break; +#if LIBCURL_VERSION_NUM >= 0x072000 + case CURLOPT_XFERINFOFUNCTION: + curl_easy_setopt(ch->cp, CURLOPT_XFERINFOFUNCTION, curl_xferinfo); + curl_easy_setopt(ch->cp, CURLOPT_XFERINFODATA, ch); + if (ch->handlers.xferinfo == NULL) { + ch->handlers.xferinfo = ecalloc(1, sizeof(php_curl_callback)); + } else if (!Z_ISUNDEF(ch->handlers.xferinfo->func_name)) { + zval_ptr_dtor(&ch->handlers.xferinfo->func_name); + ch->handlers.xferinfo->fci_cache = empty_fcall_info_cache; + } + ZVAL_COPY(&ch->handlers.xferinfo->func_name, zvalue); + break; +#endif + /* Curl off_t options */ case CURLOPT_MAX_RECV_SPEED_LARGE: case CURLOPT_MAX_SEND_SPEED_LARGE: @@ -3521,6 +3615,13 @@ static void curl_free_obj(zend_object *object) efree(ch->handlers.progress); } +#if LIBCURL_VERSION_NUM >= 0x072000 + if (ch->handlers.xferinfo) { + zval_ptr_dtor(&ch->handlers.xferinfo->func_name); + efree(ch->handlers.xferinfo); + } +#endif + if (ch->handlers.fnmatch) { zval_ptr_dtor(&ch->handlers.fnmatch->func_name); efree(ch->handlers.fnmatch); @@ -3593,12 +3694,19 @@ static void _php_curl_reset_handlers(php_curl *ch) ch->handlers.progress = NULL; } +#if LIBCURL_VERSION_NUM >= 0x072000 + if (ch->handlers.xferinfo) { + zval_ptr_dtor(&ch->handlers.xferinfo->func_name); + efree(ch->handlers.xferinfo); + ch->handlers.xferinfo = NULL; + } +#endif + if (ch->handlers.fnmatch) { zval_ptr_dtor(&ch->handlers.fnmatch->func_name); efree(ch->handlers.fnmatch); ch->handlers.fnmatch = NULL; } - } /* }}} */ diff --git a/ext/curl/sync-constants.php b/ext/curl/sync-constants.php index 035dbcf6a237d..2ed2efb18a24d 100755 --- a/ext/curl/sync-constants.php +++ b/ext/curl/sync-constants.php @@ -15,7 +15,8 @@ const MIN_SUPPORTED_CURL_VERSION = '7.29.0'; const IGNORED_CONSTANTS = [ - 'CURLOPT_PROGRESSDATA' + 'CURLOPT_PROGRESSDATA', + 'CURLOPT_XFERINFODATA' ]; const CONSTANTS_REGEX_PATTERN = '~^CURL(?:OPT|_VERSION)_[A-Z0-9_]+$~'; diff --git a/ext/curl/tests/curl_basic_007.phpt b/ext/curl/tests/curl_basic_007.phpt index 3b53658d6a7e0..3834e4674f827 100644 --- a/ext/curl/tests/curl_basic_007.phpt +++ b/ext/curl/tests/curl_basic_007.phpt @@ -20,5 +20,5 @@ curl_close($ch); ?> --EXPECTF-- -string(%d) "No URL set!%w" +string(%d) "No URL set%A" int(3) diff --git a/ext/curl/tests/curl_copy_handle_xferinfo.phpt b/ext/curl/tests/curl_copy_handle_xferinfo.phpt new file mode 100644 index 0000000000000..55050551b797e --- /dev/null +++ b/ext/curl/tests/curl_copy_handle_xferinfo.phpt @@ -0,0 +1,27 @@ +--TEST-- +Test curl_copy_handle() with CURLOPT_XFERINFOFUNCTION +--EXTENSIONS-- +curl +--FILE-- + +--EXPECT-- +Download progress! +Hello World! +Hello World! +Hello World! +Hello World! diff --git a/ext/curl/tests/curl_postfields_array.phpt b/ext/curl/tests/curl_postfields_array.phpt index 05aa91a3f06df..4fe41eb1e0b5d 100644 --- a/ext/curl/tests/curl_postfields_array.phpt +++ b/ext/curl/tests/curl_postfields_array.phpt @@ -31,6 +31,7 @@ $options = [ CURLOPT_FORBID_REUSE => 1, CURLOPT_TIMEOUT => 1, CURLOPT_POSTFIELDS => $fields, + CURLOPT_HTTPHEADER => [ 'Expect:' ], ]; $ch = curl_init(); diff --git a/ext/date/php_date.c b/ext/date/php_date.c index e51dcbe760504..96cd22129c10a 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -882,6 +882,7 @@ PHPAPI int php_idate(char format, time_t ts, bool localtime) /* day */ case 'd': case 'j': retval = (int) t->d; break; + case 'N': retval = (int) timelib_iso_day_of_week(t->y, t->m, t->d); break; case 'w': retval = (int) timelib_day_of_week(t->y, t->m, t->d); break; case 'z': retval = (int) timelib_day_of_year(t->y, t->m, t->d); break; @@ -896,6 +897,7 @@ PHPAPI int php_idate(char format, time_t ts, bool localtime) case 'L': retval = (int) timelib_is_leap((int) t->y); break; case 'y': retval = (int) (t->y % 100); break; case 'Y': retval = (int) t->y; break; + case 'o': retval = (int) isoyear; break; /* iso year */ /* Swatch Beat a.k.a. Internet Time */ case 'B': @@ -1035,6 +1037,9 @@ PHP_FUNCTION(strtotime) } tzi = get_timezone_info(); + if (!tzi) { + return; + } now = timelib_time_ctor(); now->tz_info = tzi; @@ -1094,6 +1099,9 @@ PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, bool gmt) timelib_unixtime2gmt(now, (timelib_sll) php_time()); } else { tzi = get_timezone_info(); + if (!tzi) { + return; + } now->tz_info = tzi; now->zone_type = TIMELIB_ZONETYPE_ID; timelib_unixtime2local(now, (timelib_sll) php_time()); @@ -1215,6 +1223,9 @@ PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, bool gmt) timelib_unixtime2gmt(ts, (timelib_sll) timestamp); } else { tzi = get_timezone_info(); + if (!tzi) { + return; + } ts->tz_info = tzi; ts->zone_type = TIMELIB_ZONETYPE_ID; timelib_unixtime2local(ts, (timelib_sll) timestamp); @@ -1323,6 +1334,9 @@ PHP_FUNCTION(localtime) } tzi = get_timezone_info(); + if (!tzi) { + RETURN_THROWS(); + } ts = timelib_time_ctor(); ts->tz_info = tzi; ts->zone_type = TIMELIB_ZONETYPE_ID; @@ -1374,6 +1388,9 @@ PHP_FUNCTION(getdate) } tzi = get_timezone_info(); + if (!tzi) { + RETURN_THROWS(); + } ts = timelib_time_ctor(); ts->tz_info = tzi; ts->zone_type = TIMELIB_ZONETYPE_ID; @@ -1451,16 +1468,6 @@ static int date_period_it_has_more(zend_object_iterator *iter) { date_period_it *iterator = (date_period_it *)iter; php_period_obj *object = Z_PHPPERIOD_P(&iterator->intern.data); - timelib_time *it_time = object->current; - - /* apply modification if it's not the first iteration */ - if (!object->include_start_date || iterator->current_index > 0) { - it_time->have_relative = 1; - it_time->relative = *object->interval; - it_time->sse_uptodate = 0; - timelib_update_ts(it_time, NULL); - timelib_update_from_sse(it_time); - } if (object->end) { return object->current->sse < object->end->sse ? SUCCESS : FAILURE; @@ -1502,10 +1509,23 @@ static void date_period_it_current_key(zend_object_iterator *iter, zval *key) } /* }}} */ +static void date_period_advance(timelib_time *it_time, timelib_rel_time *interval) +{ + it_time->have_relative = 1; + it_time->relative = *interval; + it_time->sse_uptodate = 0; + timelib_update_ts(it_time, NULL); + timelib_update_from_sse(it_time); +} + /* {{{ date_period_it_move_forward */ static void date_period_it_move_forward(zend_object_iterator *iter) { - date_period_it *iterator = (date_period_it *)iter; + date_period_it *iterator = (date_period_it *)iter; + php_period_obj *object = Z_PHPPERIOD_P(&iterator->intern.data); + timelib_time *it_time = object->current; + + date_period_advance(it_time, object->interval); iterator->current_index++; date_period_it_invalidate_current(iter); @@ -1525,7 +1545,13 @@ static void date_period_it_rewind(zend_object_iterator *iter) zend_throw_error(NULL, "DatePeriod has not been initialized correctly"); return; } + iterator->object->current = timelib_time_clone(iterator->object->start); + + if (!iterator->object->include_start_date) { + date_period_advance(iterator->object->current, iterator->object->interval); + } + date_period_it_invalidate_current(iter); } /* }}} */ @@ -1787,28 +1813,9 @@ static HashTable *date_object_get_gc_timezone(zend_object *object, zval **table, return zend_std_get_properties(object); } /* }}} */ -static HashTable *date_object_get_properties_for(zend_object *object, zend_prop_purpose purpose) /* {{{ */ +static void date_object_to_hash(php_date_obj *dateobj, HashTable *props) { - HashTable *props; zval zv; - php_date_obj *dateobj; - - switch (purpose) { - case ZEND_PROP_PURPOSE_DEBUG: - case ZEND_PROP_PURPOSE_SERIALIZE: - case ZEND_PROP_PURPOSE_VAR_EXPORT: - case ZEND_PROP_PURPOSE_JSON: - case ZEND_PROP_PURPOSE_ARRAY_CAST: - break; - default: - return zend_std_get_properties_for(object, purpose); - } - - dateobj = php_date_obj_from_obj(object); - props = zend_array_dup(zend_std_get_properties(object)); - if (!dateobj->time) { - return props; - } /* first we add the date and time in ISO format */ ZVAL_STR(&zv, date_format("Y-m-d H:i:s.u", sizeof("Y-m-d H:i:s.u")-1, dateobj->time, 1)); @@ -1841,6 +1848,31 @@ static HashTable *date_object_get_properties_for(zend_object *object, zend_prop_ } zend_hash_str_update(props, "timezone", sizeof("timezone")-1, &zv); } +} + +static HashTable *date_object_get_properties_for(zend_object *object, zend_prop_purpose purpose) /* {{{ */ +{ + HashTable *props; + php_date_obj *dateobj; + + switch (purpose) { + case ZEND_PROP_PURPOSE_DEBUG: + case ZEND_PROP_PURPOSE_SERIALIZE: + case ZEND_PROP_PURPOSE_VAR_EXPORT: + case ZEND_PROP_PURPOSE_JSON: + case ZEND_PROP_PURPOSE_ARRAY_CAST: + break; + default: + return zend_std_get_properties_for(object, purpose); + } + + dateobj = php_date_obj_from_obj(object); + props = zend_array_dup(zend_std_get_properties(object)); + if (!dateobj->time) { + return props; + } + + date_object_to_hash(dateobj, props); return props; } /* }}} */ @@ -1939,10 +1971,20 @@ static void php_timezone_to_string(php_timezone_obj *tzobj, zval *zv) } } +void date_timezone_object_to_hash(php_timezone_obj *tzobj, HashTable *props) +{ + zval zv; + + ZVAL_LONG(&zv, tzobj->type); + zend_hash_str_update(props, "timezone_type", strlen("timezone_type"), &zv); + + php_timezone_to_string(tzobj, &zv); + zend_hash_str_update(props, "timezone", strlen("timezone"), &zv); +} + static HashTable *date_object_get_properties_for_timezone(zend_object *object, zend_prop_purpose purpose) /* {{{ */ { HashTable *props; - zval zv; php_timezone_obj *tzobj; switch (purpose) { @@ -1962,11 +2004,7 @@ static HashTable *date_object_get_properties_for_timezone(zend_object *object, z return props; } - ZVAL_LONG(&zv, tzobj->type); - zend_hash_str_update(props, "timezone_type", sizeof("timezone_type")-1, &zv); - - php_timezone_to_string(tzobj, &zv); - zend_hash_str_update(props, "timezone", sizeof("timezone")-1, &zv); + date_timezone_object_to_hash(tzobj, props); return props; } /* }}} */ @@ -2009,6 +2047,11 @@ static zend_object *date_object_clone_interval(zend_object *this_ptr) /* {{{ */ php_interval_obj *new_obj = php_interval_obj_from_obj(date_object_new_interval(old_obj->std.ce)); zend_objects_clone_members(&new_obj->std, &old_obj->std); + new_obj->civil_or_wall = old_obj->civil_or_wall; + new_obj->from_string = old_obj->from_string; + if (old_obj->date_string) { + new_obj->date_string = zend_string_copy(old_obj->date_string); + } new_obj->initialized = old_obj->initialized; if (old_obj->diff) { new_obj->diff = timelib_rel_time_clone(old_obj->diff); @@ -2025,16 +2068,17 @@ static HashTable *date_object_get_gc_interval(zend_object *object, zval **table, return zend_std_get_properties(object); } /* }}} */ -static HashTable *date_object_get_properties_interval(zend_object *object) /* {{{ */ +static void date_interval_object_to_hash(php_interval_obj *intervalobj, HashTable *props) { - HashTable *props; zval zv; - php_interval_obj *intervalobj; - intervalobj = php_interval_obj_from_obj(object); - props = zend_std_get_properties(object); - if (!intervalobj->initialized) { - return props; + /* Records whether this is a special relative interval that needs to be recreated from a string */ + if (intervalobj->from_string) { + ZVAL_BOOL(&zv, (zend_bool)intervalobj->from_string); + zend_hash_str_update(props, "from_string", strlen("from_string"), &zv); + ZVAL_STR_COPY(&zv, intervalobj->date_string); + zend_hash_str_update(props, "date_string", strlen("date_string"), &zv); + return; } #define PHP_DATE_INTERVAL_ADD_PROPERTY(n,f) \ @@ -2049,9 +2093,6 @@ static HashTable *date_object_get_properties_interval(zend_object *object) /* {{ PHP_DATE_INTERVAL_ADD_PROPERTY("s", s); ZVAL_DOUBLE(&zv, (double)intervalobj->diff->us / 1000000.0); zend_hash_str_update(props, "f", sizeof("f") - 1, &zv); - PHP_DATE_INTERVAL_ADD_PROPERTY("weekday", weekday); - PHP_DATE_INTERVAL_ADD_PROPERTY("weekday_behavior", weekday_behavior); - PHP_DATE_INTERVAL_ADD_PROPERTY("first_last_day_of", first_last_day_of); PHP_DATE_INTERVAL_ADD_PROPERTY("invert", invert); if (intervalobj->diff->days != -99999) { PHP_DATE_INTERVAL_ADD_PROPERTY("days", days); @@ -2059,10 +2100,24 @@ static HashTable *date_object_get_properties_interval(zend_object *object) /* {{ ZVAL_FALSE(&zv); zend_hash_str_update(props, "days", sizeof("days")-1, &zv); } - PHP_DATE_INTERVAL_ADD_PROPERTY("special_type", special.type); - PHP_DATE_INTERVAL_ADD_PROPERTY("special_amount", special.amount); - PHP_DATE_INTERVAL_ADD_PROPERTY("have_weekday_relative", have_weekday_relative); - PHP_DATE_INTERVAL_ADD_PROPERTY("have_special_relative", have_special_relative); + ZVAL_BOOL(&zv, (zend_bool)intervalobj->from_string); + zend_hash_str_update(props, "from_string", strlen("from_string"), &zv); + +#undef PHP_DATE_INTERVAL_ADD_PROPERTY +} + +static HashTable *date_object_get_properties_interval(zend_object *object) /* {{{ */ +{ + HashTable *props; + php_interval_obj *intervalobj; + + intervalobj = php_interval_obj_from_obj(object); + props = zend_std_get_properties(object); + if (!intervalobj->initialized) { + return props; + } + + date_interval_object_to_hash(intervalobj, props); return props; } /* }}} */ @@ -2130,6 +2185,10 @@ static void date_object_free_storage_interval(zend_object *object) /* {{{ */ { php_interval_obj *intern = php_interval_obj_from_obj(object); + if (intern->date_string) { + zend_string_release(intern->date_string); + intern->date_string = NULL; + } timelib_rel_time_dtor(intern->diff); zend_object_std_dtor(&intern->std); } /* }}} */ @@ -2256,6 +2315,9 @@ PHPAPI bool php_date_initialize(php_date_obj *dateobj, const char *time_str, siz tzi = dateobj->time->tz_info; } else { tzi = get_timezone_info(); + if (!tzi) { + return 0; + } } now = timelib_time_ctor(); @@ -2432,8 +2494,10 @@ PHP_METHOD(DateTime, createFromImmutable) Z_PARAM_OBJECT_OF_CLASS(datetimeimmutable_object, date_ce_immutable) ZEND_PARSE_PARAMETERS_END(); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value); old_obj = Z_PHPDATE_P(datetimeimmutable_object); + DATE_CHECK_INITIALIZED(old_obj->time, DateTimeImmutable); + + php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value); new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2451,8 +2515,10 @@ PHP_METHOD(DateTime, createFromInterface) Z_PARAM_OBJECT_OF_CLASS(datetimeinterface_object, date_ce_interface) ZEND_PARSE_PARAMETERS_END(); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value); old_obj = Z_PHPDATE_P(datetimeinterface_object); + DATE_CHECK_INITIALIZED(old_obj->time, DateTimeInterface); + + php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_date, return_value); new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2470,8 +2536,10 @@ PHP_METHOD(DateTimeImmutable, createFromMutable) Z_PARAM_OBJECT_OF_CLASS(datetime_object, date_ce_date) ZEND_PARSE_PARAMETERS_END(); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value); old_obj = Z_PHPDATE_P(datetime_object); + DATE_CHECK_INITIALIZED(old_obj->time, DateTime); + + php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value); new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2489,8 +2557,10 @@ PHP_METHOD(DateTimeImmutable, createFromInterface) Z_PARAM_OBJECT_OF_CLASS(datetimeinterface_object, date_ce_interface) ZEND_PARSE_PARAMETERS_END(); - php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value); old_obj = Z_PHPDATE_P(datetimeinterface_object); + DATE_CHECK_INITIALIZED(old_obj->time, DateTimeInterface); + + php_date_instantiate(execute_data->This.value.ce ? execute_data->This.value.ce : date_ce_immutable, return_value); new_obj = Z_PHPDATE_P(return_value); new_obj->time = timelib_time_clone(old_obj->time); @@ -2596,6 +2666,84 @@ PHP_METHOD(DateTimeImmutable, __set_state) } /* }}} */ +/* {{{ */ +PHP_METHOD(DateTime, __serialize) +{ + zval *object = ZEND_THIS; + php_date_obj *dateobj; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_NONE(); + + dateobj = Z_PHPDATE_P(object); + DATE_CHECK_INITIALIZED(dateobj->time, DateTime); + + array_init(return_value); + myht = Z_ARRVAL_P(return_value); + date_object_to_hash(dateobj, myht); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(DateTimeImmutable, __serialize) +{ + zval *object = ZEND_THIS; + php_date_obj *dateobj; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_NONE(); + + dateobj = Z_PHPDATE_P(object); + DATE_CHECK_INITIALIZED(dateobj->time, DateTimeImmutable); + + array_init(return_value); + myht = Z_ARRVAL_P(return_value); + date_object_to_hash(dateobj, myht); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(DateTime, __unserialize) +{ + zval *object = ZEND_THIS; + php_date_obj *dateobj; + zval *array; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY(array) + ZEND_PARSE_PARAMETERS_END(); + + dateobj = Z_PHPDATE_P(object); + myht = Z_ARRVAL_P(array); + + if (!php_date_initialize_from_hash(&dateobj, myht)) { + zend_throw_error(NULL, "Invalid serialization data for DateTime object"); + } +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(DateTimeImmutable, __unserialize) +{ + zval *object = ZEND_THIS; + php_date_obj *dateobj; + zval *array; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY(array) + ZEND_PARSE_PARAMETERS_END(); + + dateobj = Z_PHPDATE_P(object); + myht = Z_ARRVAL_P(array); + + if (!php_date_initialize_from_hash(&dateobj, myht)) { + zend_throw_error(NULL, "Invalid serialization data for DateTimeImmutable object"); + } +} +/* }}} */ + /* {{{ */ PHP_METHOD(DateTime, __wakeup) { @@ -2965,7 +3113,7 @@ static void php_date_sub(zval *object, zval *interval, zval *return_value) /* {{ intobj = Z_PHPINTERVAL_P(interval); DATE_CHECK_INITIALIZED(intobj->initialized, DateInterval); - if (intobj->diff->have_special_relative) { + if (intobj->diff->have_weekday_relative || intobj->diff->have_special_relative) { php_error_docref(NULL, E_WARNING, "Only non-special relative time specifications are supported for subtraction"); return; } @@ -3013,6 +3161,12 @@ PHP_METHOD(DateTimeImmutable, sub) static void set_timezone_from_timelib_time(php_timezone_obj *tzobj, timelib_time *t) { + /* Free abbreviation if already set */ + if (tzobj->initialized && tzobj->type == TIMELIB_ZONETYPE_ABBR) { + timelib_free(tzobj->tzi.z.abbr); + } + + /* Set new values */ tzobj->initialized = 1; tzobj->type = t->zone_type; @@ -3389,7 +3543,7 @@ PHP_FUNCTION(date_diff) } /* }}} */ -static zend_result timezone_initialize(php_timezone_obj *tzobj, const char *tz, size_t tz_len) /* {{{ */ +static bool timezone_initialize(php_timezone_obj *tzobj, const char *tz, size_t tz_len) /* {{{ */ { timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time)); int dst, not_found; @@ -3398,19 +3552,19 @@ static zend_result timezone_initialize(php_timezone_obj *tzobj, const char *tz, if (strlen(tz) != tz_len) { php_error_docref(NULL, E_WARNING, "Timezone must not contain null bytes"); efree(dummy_t); - return FAILURE; + return false; } dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, ¬_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); if (not_found) { php_error_docref(NULL, E_WARNING, "Unknown or bad timezone (%s)", orig_tz); efree(dummy_t); - return FAILURE; + return false; } else { set_timezone_from_timelib_time(tzobj, dummy_t); timelib_free(dummy_t->tz_abbr); efree(dummy_t); - return SUCCESS; + return true; } } /* }}} */ @@ -3425,7 +3579,7 @@ PHP_FUNCTION(timezone_open) ZEND_PARSE_PARAMETERS_END(); tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value)); - if (FAILURE == timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz))) { + if (!timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz))) { zval_ptr_dtor(return_value); RETURN_FALSE; } @@ -3450,25 +3604,25 @@ PHP_METHOD(DateTimeZone, __construct) } /* }}} */ -static zend_result php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht) /* {{{ */ +static bool php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht) /* {{{ */ { zval *z_timezone_type; if ((z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type") - 1)) == NULL) { - return FAILURE; + return false; } zval *z_timezone; if ((z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone") - 1)) == NULL) { - return FAILURE; + return false; } if (Z_TYPE_P(z_timezone_type) != IS_LONG) { - return FAILURE; + return false; } if (Z_TYPE_P(z_timezone) != IS_STRING) { - return FAILURE; + return false; } return timezone_initialize(*tzobj, Z_STRVAL_P(z_timezone), Z_STRLEN_P(z_timezone)); } /* }}} */ @@ -3488,7 +3642,7 @@ PHP_METHOD(DateTimeZone, __set_state) php_date_instantiate(date_ce_timezone, return_value); tzobj = Z_PHPTIMEZONE_P(return_value); - if (php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht) == FAILURE) { + if (!php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht)) { zend_throw_error(NULL, "Timezone initialization failed"); zval_ptr_dtor(return_value); } @@ -3508,12 +3662,51 @@ PHP_METHOD(DateTimeZone, __wakeup) myht = Z_OBJPROP_P(object); - if (php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht) == FAILURE) { + if (!php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht)) { zend_throw_error(NULL, "Timezone initialization failed"); } } /* }}} */ +/* {{{ */ +PHP_METHOD(DateTimeZone, __serialize) +{ + zval *object = ZEND_THIS; + php_timezone_obj *tzobj; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_NONE(); + + tzobj = Z_PHPTIMEZONE_P(object); + DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone); + + array_init(return_value); + myht = Z_ARRVAL_P(return_value); + date_timezone_object_to_hash(tzobj, myht); +} +/* }}} */ + +/* {{{ */ +PHP_METHOD(DateTimeZone, __unserialize) +{ + zval *object = ZEND_THIS; + php_timezone_obj *tzobj; + zval *array; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY(array) + ZEND_PARSE_PARAMETERS_END(); + + tzobj = Z_PHPTIMEZONE_P(object); + myht = Z_ARRVAL_P(array); + + if (!php_date_timezone_initialize_from_hash(&object, &tzobj, myht)) { + zend_throw_error(NULL, "Invalid serialization data for DateTimeZone object"); + } +} +/* }}} */ + /* {{{ Returns the name of the timezone. */ PHP_FUNCTION(timezone_name_get) { @@ -3930,6 +4123,41 @@ PHP_METHOD(DateInterval, __construct) static void php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht) /* {{{ */ { + /* If ->diff is already set, then we need to free it first */ + if ((*intobj)->diff) { + timelib_rel_time_dtor((*intobj)->diff); + } + + /* If we have a date_string, use that instead */ + zval *date_str = zend_hash_str_find(myht, "date_string", strlen("date_string")); + if (date_str && Z_TYPE_P(date_str) == IS_STRING) { + timelib_time *time; + timelib_error_container *err = NULL; + + time = timelib_strtotime(Z_STRVAL_P(date_str), Z_STRLEN_P(date_str), &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); + + if (err->error_count > 0) { + php_error_docref(NULL, + E_WARNING, + "Unknown or bad format (%s) at position %d (%c) while unserializing: %s", + Z_STRVAL_P(date_str), + err->error_messages[0].position, + err->error_messages[0].character ? err->error_messages[0].character : ' ', err->error_messages[0].message); + } + + (*intobj)->diff = timelib_rel_time_clone(&time->relative); + (*intobj)->initialized = 1; + (*intobj)->civil_or_wall = PHP_DATE_CIVIL; + (*intobj)->from_string = true; + (*intobj)->date_string = zend_string_copy(Z_STR_P(date_str)); + + timelib_time_dtor(time); + timelib_error_container_dtor(err); + + return; + } + + /* Set new value */ (*intobj)->diff = timelib_rel_time_ctor(); #define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def) \ @@ -4008,6 +4236,7 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte (*intobj)->civil_or_wall = val; } } + (*intobj)->initialized = 1; } /* }}} */ @@ -4030,6 +4259,44 @@ PHP_METHOD(DateInterval, __set_state) } /* }}} */ +/* {{{ */ +PHP_METHOD(DateInterval, __serialize) +{ + zval *object = ZEND_THIS; + php_interval_obj *intervalobj; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_NONE(); + + intervalobj = Z_PHPINTERVAL_P(object); + DATE_CHECK_INITIALIZED(intervalobj->initialized, DateInterval); + + array_init(return_value); + myht = Z_ARRVAL_P(return_value); + date_interval_object_to_hash(intervalobj, myht); +} +/* }}} */ + + +/* {{{ */ +PHP_METHOD(DateInterval, __unserialize) +{ + zval *object = ZEND_THIS; + php_interval_obj *intervalobj; + zval *array; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY(array) + ZEND_PARSE_PARAMETERS_END(); + + intervalobj = Z_PHPINTERVAL_P(object); + myht = Z_ARRVAL_P(array); + + php_date_interval_initialize_from_hash(&object, &intervalobj, myht); +} +/* }}} */ + /* {{{ */ PHP_METHOD(DateInterval, __wakeup) { @@ -4068,11 +4335,19 @@ PHP_FUNCTION(date_interval_create_from_date_string) goto cleanup; } + if (time->have_date || time->have_time || time->have_zone) { + php_error_docref(NULL, E_WARNING, "String '%s' contains non-relative elements", ZSTR_VAL(time_str)); + RETVAL_FALSE; + goto cleanup; + } + 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->civil_or_wall = PHP_DATE_CIVIL; + diobj->from_string = true; + diobj->date_string = zend_string_copy(time_str); cleanup: timelib_time_dtor(time); @@ -4526,6 +4801,9 @@ PHP_FUNCTION(date_default_timezone_get) ZEND_PARSE_PARAMETERS_NONE(); default_tz = get_timezone_info(); + if (!default_tz) { + RETURN_THROWS(); + } RETVAL_STRING(default_tz->name); } /* }}} */ @@ -4581,8 +4859,11 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, bool calc_s altitude = 90 - zenith; /* Initialize time struct */ - t = timelib_time_ctor(); tzi = get_timezone_info(); + if (!tzi) { + RETURN_THROWS(); + } + t = timelib_time_ctor(); t->tz_info = tzi; t->zone_type = TIMELIB_ZONETYPE_ID; @@ -4652,8 +4933,11 @@ PHP_FUNCTION(date_sun_info) ZEND_PARSE_PARAMETERS_END(); /* Initialize time struct */ - t = timelib_time_ctor(); tzi = get_timezone_info(); + if (!tzi) { + RETURN_THROWS(); + } + t = timelib_time_ctor(); t->tz_info = tzi; t->zone_type = TIMELIB_ZONETYPE_ID; timelib_unixtime2local(t, time); @@ -4747,17 +5031,9 @@ static HashTable *date_object_get_gc_period(zend_object *object, zval **table, i return zend_std_get_properties(object); } /* }}} */ -static HashTable *date_object_get_properties_period(zend_object *object) /* {{{ */ +static void date_period_object_to_hash(php_period_obj *period_obj, HashTable *props) { - HashTable *props; - zval zv; - php_period_obj *period_obj; - - period_obj = php_period_obj_from_obj(object); - props = zend_std_get_properties(object); - if (!period_obj->start) { - return props; - } + zval zv; if (period_obj->start) { php_date_obj *date_obj; @@ -4806,6 +5082,20 @@ static HashTable *date_object_get_properties_period(zend_object *object) /* {{{ ZVAL_BOOL(&zv, period_obj->include_start_date); zend_hash_str_update(props, "include_start_date", sizeof("include_start_date")-1, &zv); +} + +static HashTable *date_object_get_properties_period(zend_object *object) /* {{{ */ +{ + HashTable *props; + php_period_obj *period_obj; + + period_obj = php_period_obj_from_obj(object); + props = zend_std_get_properties(object); + if (!period_obj->start) { + return props; + } + + date_period_object_to_hash(period_obj, props); return props; } /* }}} */ @@ -4911,6 +5201,46 @@ PHP_METHOD(DatePeriod, __set_state) } /* }}} */ +/* {{{ */ +PHP_METHOD(DatePeriod, __serialize) +{ + zval *object = ZEND_THIS; + php_period_obj *period_obj; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_NONE(); + + period_obj = Z_PHPPERIOD_P(object); + DATE_CHECK_INITIALIZED(period_obj->start, DatePeriod); + + array_init(return_value); + myht = Z_ARRVAL_P(return_value); + date_period_object_to_hash(period_obj, myht); +} +/* }}} */ + + +/* {{{ */ +PHP_METHOD(DatePeriod, __unserialize) +{ + zval *object = ZEND_THIS; + php_period_obj *period_obj; + zval *array; + HashTable *myht; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY(array) + ZEND_PARSE_PARAMETERS_END(); + + period_obj = Z_PHPPERIOD_P(object); + myht = Z_ARRVAL_P(array); + + if (!php_date_period_initialize_from_hash(period_obj, myht)) { + zend_throw_error(NULL, "Invalid serialization data for DatePeriod object"); + } +} +/* }}} */ + /* {{{ */ PHP_METHOD(DatePeriod, __wakeup) { diff --git a/ext/date/php_date.h b/ext/date/php_date.h index c30d34d3aa76a..d18529f10d30f 100644 --- a/ext/date/php_date.h +++ b/ext/date/php_date.h @@ -72,6 +72,8 @@ static inline php_timezone_obj *php_timezone_obj_from_obj(zend_object *obj) { struct _php_interval_obj { timelib_rel_time *diff; int civil_or_wall; + bool from_string; + zend_string *date_string; bool initialized; zend_object std; }; diff --git a/ext/date/php_date.stub.php b/ext/date/php_date.stub.php index 5720ac3f573c1..347dd6c99e622 100644 --- a/ext/date/php_date.stub.php +++ b/ext/date/php_date.stub.php @@ -205,12 +205,20 @@ public function diff(DateTimeInterface $targetObject, bool $absolute = false): D /** @tentative-return-type */ public function __wakeup(): void; + + public function __serialize(): array; + + public function __unserialize(array $data): void; } class DateTime implements DateTimeInterface { public function __construct(string $datetime = "now", ?DateTimeZone $timezone = null) {} + public function __serialize(): array {} + + public function __unserialize(array $data): void {} + /** @tentative-return-type */ public function __wakeup(): void {} @@ -218,9 +226,10 @@ public function __wakeup(): void {} public static function __set_state(array $array): DateTime {} /** @tentative-return-type */ - public static function createFromImmutable(DateTimeImmutable $object): DateTime {} + public static function createFromImmutable(DateTimeImmutable $object): static {} - public static function createFromInterface(DateTimeInterface $object): DateTime {} + /** @return static */ + public static function createFromInterface(DateTimeInterface $object): DateTime {} // TODO return type should be static /** * @tentative-return-type @@ -318,6 +327,10 @@ class DateTimeImmutable implements DateTimeInterface { public function __construct(string $datetime = "now", ?DateTimeZone $timezone = null) {} + public function __serialize(): array {} + + public function __unserialize(array $data): void {} + /** @tentative-return-type */ public function __wakeup(): void {} @@ -392,9 +405,10 @@ public function setISODate(int $year, int $week, int $dayOfWeek = 1): DateTimeIm public function setTimestamp(int $timestamp): DateTimeImmutable {} /** @tentative-return-type */ - public static function createFromMutable(DateTime $object): DateTimeImmutable {} + public static function createFromMutable(DateTime $object): static {} - public static function createFromInterface(DateTimeInterface $object): DateTimeImmutable {} + /** @return static */ + public static function createFromInterface(DateTimeInterface $object): DateTimeImmutable {} // TODO return type should be static } class DateTimeZone @@ -441,6 +455,10 @@ public static function listAbbreviations(): array {} */ public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array {} + public function __serialize(): array {} + + public function __unserialize(array $data): void {} + /** @tentative-return-type */ public function __wakeup(): void {} @@ -464,6 +482,10 @@ public static function createFromDateString(string $datetime): DateInterval|fals */ public function format(string $format): string {} + public function __serialize(): array; + + public function __unserialize(array $data): void; + /** @tentative-return-type */ public function __wakeup(): void {} @@ -493,6 +515,10 @@ public function getDateInterval(): DateInterval {} /** @tentative-return-type */ public function getRecurrences(): ?int {} + public function __serialize(): array; + + public function __unserialize(array $data): void; + /** @tentative-return-type */ public function __wakeup(): void {} diff --git a/ext/date/php_date_arginfo.h b/ext/date/php_date_arginfo.h index 3b8f1578f949a..3621fc331545d 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: ea354510fbf64c42ee1cdd6fd786ab937516226c */ + * Stub hash: ca149a2efec878f0730eb744f4e11f6462d70d83 */ 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) @@ -245,18 +245,28 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeInterface___wakeup, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() +#define arginfo_class_DateTimeInterface___serialize arginfo_timezone_abbreviations_list + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeInterface___unserialize, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DateTime___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, datetime, IS_STRING, 0, "\"now\"") ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, timezone, DateTimeZone, 1, "null") ZEND_END_ARG_INFO() +#define arginfo_class_DateTime___serialize arginfo_timezone_abbreviations_list + +#define arginfo_class_DateTime___unserialize arginfo_class_DateTimeInterface___unserialize + #define arginfo_class_DateTime___wakeup arginfo_class_DateTimeInterface___wakeup ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime___set_state, 0, 1, DateTime, 0) ZEND_ARG_TYPE_INFO(0, array, IS_ARRAY, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTime_createFromImmutable, 0, 1, DateTime, 0) +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTime_createFromImmutable, 0, 1, IS_STATIC, 0) ZEND_ARG_OBJ_INFO(0, object, DateTimeImmutable, 0) ZEND_END_ARG_INFO() @@ -322,6 +332,10 @@ ZEND_END_ARG_INFO() #define arginfo_class_DateTimeImmutable___construct arginfo_class_DateTime___construct +#define arginfo_class_DateTimeImmutable___serialize arginfo_timezone_abbreviations_list + +#define arginfo_class_DateTimeImmutable___unserialize arginfo_class_DateTimeInterface___unserialize + #define arginfo_class_DateTimeImmutable___wakeup arginfo_class_DateTimeInterface___wakeup ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable___set_state, 0, 1, DateTimeImmutable, 0) @@ -383,7 +397,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeImmutable_createFromMutable, 0, 1, DateTimeImmutable, 0) +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeImmutable_createFromMutable, 0, 1, IS_STATIC, 0) ZEND_ARG_OBJ_INFO(0, object, DateTime, 0) ZEND_END_ARG_INFO() @@ -417,6 +431,10 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeZone_lis ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, countryCode, IS_STRING, 1, "null") ZEND_END_ARG_INFO() +#define arginfo_class_DateTimeZone___serialize arginfo_timezone_abbreviations_list + +#define arginfo_class_DateTimeZone___unserialize arginfo_class_DateTimeInterface___unserialize + #define arginfo_class_DateTimeZone___wakeup arginfo_class_DateTimeInterface___wakeup ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeZone___set_state, 0, 1, DateTimeZone, 0) @@ -433,6 +451,10 @@ ZEND_END_ARG_INFO() #define arginfo_class_DateInterval_format arginfo_class_DateTimeInterface_format +#define arginfo_class_DateInterval___serialize arginfo_timezone_abbreviations_list + +#define arginfo_class_DateInterval___unserialize arginfo_class_DateTimeInterface___unserialize + #define arginfo_class_DateInterval___wakeup arginfo_class_DateTimeInterface___wakeup ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateInterval___set_state, 0, 1, DateInterval, 0) @@ -458,6 +480,10 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DatePeriod_getRecurrences, 0, 0, IS_LONG, 1) ZEND_END_ARG_INFO() +#define arginfo_class_DatePeriod___serialize arginfo_timezone_abbreviations_list + +#define arginfo_class_DatePeriod___unserialize arginfo_class_DateTimeInterface___unserialize + #define arginfo_class_DatePeriod___wakeup arginfo_class_DateTimeInterface___wakeup ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DatePeriod___set_state, 0, 1, DatePeriod, 0) @@ -517,11 +543,15 @@ ZEND_FUNCTION(date_sunrise); ZEND_FUNCTION(date_sunset); ZEND_FUNCTION(date_sun_info); ZEND_METHOD(DateTime, __construct); +ZEND_METHOD(DateTime, __serialize); +ZEND_METHOD(DateTime, __unserialize); ZEND_METHOD(DateTime, __wakeup); ZEND_METHOD(DateTime, __set_state); ZEND_METHOD(DateTime, createFromImmutable); ZEND_METHOD(DateTime, createFromInterface); ZEND_METHOD(DateTimeImmutable, __construct); +ZEND_METHOD(DateTimeImmutable, __serialize); +ZEND_METHOD(DateTimeImmutable, __unserialize); ZEND_METHOD(DateTimeImmutable, __wakeup); ZEND_METHOD(DateTimeImmutable, __set_state); ZEND_METHOD(DateTimeImmutable, modify); @@ -535,9 +565,13 @@ ZEND_METHOD(DateTimeImmutable, setTimestamp); ZEND_METHOD(DateTimeImmutable, createFromMutable); ZEND_METHOD(DateTimeImmutable, createFromInterface); ZEND_METHOD(DateTimeZone, __construct); +ZEND_METHOD(DateTimeZone, __serialize); +ZEND_METHOD(DateTimeZone, __unserialize); ZEND_METHOD(DateTimeZone, __wakeup); ZEND_METHOD(DateTimeZone, __set_state); ZEND_METHOD(DateInterval, __construct); +ZEND_METHOD(DateInterval, __serialize); +ZEND_METHOD(DateInterval, __unserialize); ZEND_METHOD(DateInterval, __wakeup); ZEND_METHOD(DateInterval, __set_state); ZEND_METHOD(DatePeriod, __construct); @@ -545,6 +579,8 @@ ZEND_METHOD(DatePeriod, getStartDate); ZEND_METHOD(DatePeriod, getEndDate); ZEND_METHOD(DatePeriod, getDateInterval); ZEND_METHOD(DatePeriod, getRecurrences); +ZEND_METHOD(DatePeriod, __serialize); +ZEND_METHOD(DatePeriod, __unserialize); ZEND_METHOD(DatePeriod, __wakeup); ZEND_METHOD(DatePeriod, __set_state); ZEND_METHOD(DatePeriod, getIterator); @@ -610,12 +646,16 @@ static const zend_function_entry class_DateTimeInterface_methods[] = { ZEND_ABSTRACT_ME_WITH_FLAGS(DateTimeInterface, getTimestamp, arginfo_class_DateTimeInterface_getTimestamp, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT) ZEND_ABSTRACT_ME_WITH_FLAGS(DateTimeInterface, diff, arginfo_class_DateTimeInterface_diff, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT) ZEND_ABSTRACT_ME_WITH_FLAGS(DateTimeInterface, __wakeup, arginfo_class_DateTimeInterface___wakeup, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT) + ZEND_ABSTRACT_ME_WITH_FLAGS(DateTimeInterface, __serialize, arginfo_class_DateTimeInterface___serialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT) + ZEND_ABSTRACT_ME_WITH_FLAGS(DateTimeInterface, __unserialize, arginfo_class_DateTimeInterface___unserialize, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT) ZEND_FE_END }; 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, __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) @@ -641,6 +681,8 @@ static const zend_function_entry class_DateTime_methods[] = { 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, __set_state, arginfo_class_DateTimeImmutable___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME_MAPPING(createFromFormat, date_create_immutable_from_format, arginfo_class_DateTimeImmutable_createFromFormat, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) @@ -672,6 +714,8 @@ static const zend_function_entry class_DateTimeZone_methods[] = { ZEND_ME_MAPPING(getLocation, timezone_location_get, arginfo_class_DateTimeZone_getLocation, ZEND_ACC_PUBLIC) ZEND_ME_MAPPING(listAbbreviations, timezone_abbreviations_list, arginfo_class_DateTimeZone_listAbbreviations, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME_MAPPING(listIdentifiers, timezone_identifiers_list, arginfo_class_DateTimeZone_listIdentifiers, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + 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, __set_state, arginfo_class_DateTimeZone___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_FE_END @@ -682,6 +726,8 @@ static const zend_function_entry class_DateInterval_methods[] = { ZEND_ME(DateInterval, __construct, arginfo_class_DateInterval___construct, ZEND_ACC_PUBLIC) ZEND_ME_MAPPING(createFromDateString, date_interval_create_from_date_string, arginfo_class_DateInterval_createFromDateString, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME_MAPPING(format, date_interval_format, arginfo_class_DateInterval_format, ZEND_ACC_PUBLIC) + 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, __set_state, arginfo_class_DateInterval___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_FE_END @@ -694,6 +740,8 @@ static const zend_function_entry class_DatePeriod_methods[] = { ZEND_ME(DatePeriod, getEndDate, arginfo_class_DatePeriod_getEndDate, ZEND_ACC_PUBLIC) ZEND_ME(DatePeriod, getDateInterval, arginfo_class_DatePeriod_getDateInterval, ZEND_ACC_PUBLIC) 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, __set_state, arginfo_class_DatePeriod___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ZEND_ME(DatePeriod, getIterator, arginfo_class_DatePeriod_getIterator, ZEND_ACC_PUBLIC) diff --git a/ext/date/tests/DateInterval_serialize-001.phpt b/ext/date/tests/DateInterval_serialize-001.phpt new file mode 100644 index 0000000000000..cad33185cf9bb --- /dev/null +++ b/ext/date/tests/DateInterval_serialize-001.phpt @@ -0,0 +1,123 @@ +--TEST-- +Test DateInterval::__serialize and DateInterval::__unserialize +--FILE-- +__serialize()); + +echo "\n\nUsed serialised interval:\n"; +$now = new DateTimeImmutable("2022-04-22 16:25:11 BST"); +var_dump($now->add($e)); +var_dump($now->sub($e)); +?> +--EXPECTF-- +Original object: +object(DateInterval)#1 (10) { + ["y"]=> + int(2) + ["m"]=> + int(0) + ["d"]=> + int(4) + ["h"]=> + int(6) + ["i"]=> + int(8) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) +} + + +Serialised object: +string(164) "O:12:"DateInterval":10:{s:1:"y";i:2;s:1:"m";i:0;s:1:"d";i:4;s:1:"h";i:6;s:1:"i";i:8;s:1:"s";i:0;s:1:"f";d:0;s:6:"invert";i:0;s:4:"days";b:0;s:11:"from_string";b:0;}" + + +Unserialised object: +object(DateInterval)#2 (10) { + ["y"]=> + int(2) + ["m"]=> + int(0) + ["d"]=> + int(4) + ["h"]=> + int(6) + ["i"]=> + int(8) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) +} + + +Calling __serialize manually: +array(%d) { + ["y"]=> + int(2) + ["m"]=> + int(0) + ["d"]=> + int(4) + ["h"]=> + int(6) + ["i"]=> + int(8) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) +} + + +Used serialised interval: +object(DateTimeImmutable)#4 (3) { + ["date"]=> + string(26) "2024-04-26 22:33:11.000000" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(3) "BST" +} +object(DateTimeImmutable)#4 (3) { + ["date"]=> + string(26) "2020-04-18 10:17:11.000000" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(3) "BST" +} diff --git a/ext/date/tests/DateInterval_serialize-002.phpt b/ext/date/tests/DateInterval_serialize-002.phpt new file mode 100644 index 0000000000000..d21e02245e695 --- /dev/null +++ b/ext/date/tests/DateInterval_serialize-002.phpt @@ -0,0 +1,167 @@ +--TEST-- +Test DateInterval::__serialize and DateInterval::__unserialize +--FILE-- +diff($d2); +echo "Original object:\n"; +var_dump($d); + +echo "\n\nSerialised object:\n"; +$s = serialize($d); +var_dump($s); + +echo "\n\nUnserialised object:\n"; +$e = unserialize($s); +var_dump($e); + +echo "\n\nCalling __serialize manually:\n"; +var_dump($d->__serialize()); + +echo "\n\nCalling __unserialize manually:\n"; +$d = new DateInterval('P2Y4DT6H8M'); +$d->__unserialize( + [ + 'y' => 43, + 'm' => 3, + 'd' => 24, + 'h' => 1, + 'i' => 12, + 's' => 27, + 'f' => 0.654321, + 'days' => 15820, + ] +); +var_dump($d); + +echo "\n\nUsed serialised interval:\n"; +$now = new DateTimeImmutable("2022-04-15 10:27:27 BST"); +var_dump($now->add($e)); +var_dump($now->sub($e)); +?> +--EXPECTF-- +Original object: +object(DateInterval)#3 (10) { + ["y"]=> + int(43) + ["m"]=> + int(3) + ["d"]=> + int(24) + ["h"]=> + int(1) + ["i"]=> + int(12) + ["s"]=> + int(27) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + int(15820) + ["from_string"]=> + bool(false) +} + + +Serialised object: +string(172) "O:12:"DateInterval":10:{s:1:"y";i:43;s:1:"m";i:3;s:1:"d";i:24;s:1:"h";i:1;s:1:"i";i:12;s:1:"s";i:27;s:1:"f";d:0;s:6:"invert";i:0;s:4:"days";i:15820;s:11:"from_string";b:0;}" + + +Unserialised object: +object(DateInterval)#4 (10) { + ["y"]=> + int(43) + ["m"]=> + int(3) + ["d"]=> + int(24) + ["h"]=> + int(1) + ["i"]=> + int(12) + ["s"]=> + int(27) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + int(15820) + ["from_string"]=> + bool(false) +} + + +Calling __serialize manually: +array(%d) { + ["y"]=> + int(43) + ["m"]=> + int(3) + ["d"]=> + int(24) + ["h"]=> + int(1) + ["i"]=> + int(12) + ["s"]=> + int(27) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + int(15820) + ["from_string"]=> + bool(false) +} + + +Calling __unserialize manually: +object(DateInterval)#5 (10) { + ["y"]=> + int(43) + ["m"]=> + int(3) + ["d"]=> + int(24) + ["h"]=> + int(1) + ["i"]=> + int(12) + ["s"]=> + int(27) + ["f"]=> + float(0.654321) + ["invert"]=> + int(0) + ["days"]=> + int(15820) + ["from_string"]=> + bool(false) +} + + +Used serialised interval: +object(DateTimeImmutable)#6 (3) { + ["date"]=> + string(26) "2065-08-08 11:39:54.000000" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(3) "BST" +} +object(DateTimeImmutable)#6 (3) { + ["date"]=> + string(26) "1978-12-22 09:15:00.000000" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(3) "BST" +} diff --git a/ext/date/tests/DateInterval_serialize-003.phpt b/ext/date/tests/DateInterval_serialize-003.phpt new file mode 100644 index 0000000000000..b338a9ae93adb --- /dev/null +++ b/ext/date/tests/DateInterval_serialize-003.phpt @@ -0,0 +1,96 @@ +--TEST-- +Test DateInterval::__serialize and DateInterval::__unserialize +--FILE-- +__serialize()); + +echo "\n\nCalling __unserialize manually:\n"; +$d = new DateInterval('P2Y4DT6H8M'); +$d->__unserialize( + [ + 'from_string' => true, + 'date_string' => 'next weekday', + ] +); +var_dump($d); + +echo "\n\nUsed serialised interval:\n"; +$now = new DateTimeImmutable("2022-04-22 16:25:11 BST"); +var_dump($now->add($e)); +var_dump($now->sub($e)); +?> +--EXPECTF-- +Original object: +object(DateInterval)#1 (%d) { + ["from_string"]=> + bool(true) + ["date_string"]=> + string(%d) "next weekday" +} + + +Serialised object: +string(%d) "O:12:"DateInterval":2:{s:11:"from_string";b:1;s:11:"date_string";s:%d:"next weekday";}" + + +Unserialised object: +object(DateInterval)#2 (2) { + ["from_string"]=> + bool(true) + ["date_string"]=> + string(%d) "next weekday" +} + + +Calling __serialize manually: +array(2) { + ["from_string"]=> + bool(true) + ["date_string"]=> + string(%d) "next weekday" +} + + +Calling __unserialize manually: +object(DateInterval)#3 (2) { + ["from_string"]=> + bool(true) + ["date_string"]=> + string(%d) "next weekday" +} + + +Used serialised interval: +object(DateTimeImmutable)#4 (3) { + ["date"]=> + string(26) "2022-04-25 16:25:11.000000" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(3) "BST" +} + +Warning: DateTimeImmutable::sub(): Only non-special relative time specifications are supported for subtraction in %s on line %d +object(DateTimeImmutable)#4 (3) { + ["date"]=> + string(26) "2022-04-22 16:25:11.000000" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(3) "BST" +} diff --git a/ext/date/tests/DatePeriod_no_advance_on_valid.phpt b/ext/date/tests/DatePeriod_no_advance_on_valid.phpt new file mode 100644 index 0000000000000..6a8a9d0f5d04a --- /dev/null +++ b/ext/date/tests/DatePeriod_no_advance_on_valid.phpt @@ -0,0 +1,52 @@ +--TEST-- +Date Period iterators do not advance on valid() +--FILE-- +getIterator(); + +foreach ($iterator as $item) { + echo $item->format('Y-m-d') . "\n"; +} + +echo "---------STEP 2\n"; + +foreach ($iterator as $item) { + $iterator->valid(); + echo $item->format('Y-m-d') . "\n"; +} + +$period = new DatePeriod($start, $interval, $end, DatePeriod::EXCLUDE_START_DATE); +$iterator = $period->getIterator(); + +echo "---------STEP 3\n"; + +foreach ($iterator as $item) { + echo $item->format('Y-m-d') . "\n"; +} + +echo "---------STEP 4\n"; + +foreach ($iterator as $item) { + $iterator->valid(); + echo $item->format('Y-m-d') . "\n"; +} +?> +--EXPECT-- +2022-01-01 +2022-01-02 +2022-01-03 +---------STEP 2 +2022-01-01 +2022-01-02 +2022-01-03 +---------STEP 3 +2022-01-02 +2022-01-03 +---------STEP 4 +2022-01-02 +2022-01-03 diff --git a/ext/date/tests/DatePeriod_serialize-001.phpt b/ext/date/tests/DatePeriod_serialize-001.phpt new file mode 100644 index 0000000000000..0f555ab425145 --- /dev/null +++ b/ext/date/tests/DatePeriod_serialize-001.phpt @@ -0,0 +1,160 @@ +--TEST-- +Test DatePeriod::__serialize and DatePeriod::__unserialize (ISO String) +--FILE-- +__serialize()); + +?> +--EXPECTF-- +Original object: +object(DatePeriod)#1 (6) { + ["start"]=> + object(DateTime)#2 (3) { + ["date"]=> + string(26) "2012-07-01 00:00:00.000000" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+00:00" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#3 (10) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(7) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(5) + ["include_start_date"]=> + bool(true) +} + + +Serialised object: +string(411) "O:10:"DatePeriod":6:{s:5:"start";O:8:"DateTime":3:{s:4:"date";s:26:"2012-07-01 00:00:00.000000";s:13:"timezone_type";i:1;s:8:"timezone";s:6:"+00:00";}s:7:"current";N;s:3:"end";N;s:8:"interval";O:12:"DateInterval":10:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:7;s:1:"h";i:0;s:1:"i";i:0;s:1:"s";i:0;s:1:"f";d:0;s:6:"invert";i:0;s:4:"days";b:0;s:11:"from_string";b:0;}s:11:"recurrences";i:5;s:18:"include_start_date";b:1;}" + + +Unserialised object: +object(DatePeriod)#5 (6) { + ["start"]=> + object(DateTime)#6 (3) { + ["date"]=> + string(26) "2012-07-01 00:00:00.000000" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+00:00" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#4 (10) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(7) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(5) + ["include_start_date"]=> + bool(true) +} + + +Calling __serialize manually: +array(6) { + ["start"]=> + object(DateTime)#7 (3) { + ["date"]=> + string(26) "2012-07-01 00:00:00.000000" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+00:00" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#8 (10) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(7) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(5) + ["include_start_date"]=> + bool(true) +} diff --git a/ext/date/tests/DatePeriod_serialize-002.phpt b/ext/date/tests/DatePeriod_serialize-002.phpt new file mode 100644 index 0000000000000..7e9d3e62dae54 --- /dev/null +++ b/ext/date/tests/DatePeriod_serialize-002.phpt @@ -0,0 +1,210 @@ +--TEST-- +Test DatePeriod::__serialize and DatePeriod::__unserialize (start/end) +--FILE-- +__serialize()); + +echo "\n\nIterate of unserialised object:\n"; +foreach ( $e as $d ) +{ + echo $d->format(DateTime::ISO8601), "\n"; +} +?> +--EXPECTF-- +Original object: +object(DatePeriod)#4 (6) { + ["start"]=> + object(DateTimeImmutable)#5 (3) { + ["date"]=> + string(26) "1978-12-22 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["current"]=> + NULL + ["end"]=> + object(DateTimeImmutable)#6 (3) { + ["date"]=> + string(26) "2022-04-29 15:51:56.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" + } + ["interval"]=> + object(DateInterval)#7 (10) { + ["y"]=> + int(2) + ["m"]=> + int(6) + ["d"]=> + int(0) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(1) + ["include_start_date"]=> + bool(true) +} + + +Serialised object: +string(565) "O:10:"DatePeriod":6:{s:5:"start";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"1978-12-22 09:15:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:16:"Europe/Amsterdam";}s:7:"current";N;s:3:"end";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"2022-04-29 15:51:56.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:13:"Europe/London";}s:8:"interval";O:12:"DateInterval":10:{s:1:"y";i:2;s:1:"m";i:6;s:1:"d";i:0;s:1:"h";i:0;s:1:"i";i:0;s:1:"s";i:0;s:1:"f";d:0;s:6:"invert";i:0;s:4:"days";b:0;s:11:"from_string";b:0;}s:11:"recurrences";i:1;s:18:"include_start_date";b:1;}" + + +Unserialised object: +object(DatePeriod)#1 (6) { + ["start"]=> + object(DateTimeImmutable)#2 (3) { + ["date"]=> + string(26) "1978-12-22 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["current"]=> + NULL + ["end"]=> + object(DateTimeImmutable)#8 (3) { + ["date"]=> + string(26) "2022-04-29 15:51:56.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" + } + ["interval"]=> + object(DateInterval)#9 (10) { + ["y"]=> + int(2) + ["m"]=> + int(6) + ["d"]=> + int(0) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(1) + ["include_start_date"]=> + bool(true) +} + + +Calling __serialize manually: +array(6) { + ["start"]=> + object(DateTimeImmutable)#10 (3) { + ["date"]=> + string(26) "1978-12-22 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["current"]=> + NULL + ["end"]=> + object(DateTimeImmutable)#11 (3) { + ["date"]=> + string(26) "2022-04-29 15:51:56.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" + } + ["interval"]=> + object(DateInterval)#12 (10) { + ["y"]=> + int(2) + ["m"]=> + int(6) + ["d"]=> + int(0) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(1) + ["include_start_date"]=> + bool(true) +} + + +Iterate of unserialised object: +1978-12-22T09:15:00+0100 +1981-06-22T09:15:00+0200 +1983-12-22T09:15:00+0100 +1986-06-22T09:15:00+0200 +1988-12-22T09:15:00+0100 +1991-06-22T09:15:00+0200 +1993-12-22T09:15:00+0100 +1996-06-22T09:15:00+0200 +1998-12-22T09:15:00+0100 +2001-06-22T09:15:00+0200 +2003-12-22T09:15:00+0100 +2006-06-22T09:15:00+0200 +2008-12-22T09:15:00+0100 +2011-06-22T09:15:00+0200 +2013-12-22T09:15:00+0100 +2016-06-22T09:15:00+0200 +2018-12-22T09:15:00+0100 +2021-06-22T09:15:00+0200 diff --git a/ext/date/tests/DatePeriod_serialize-003.phpt b/ext/date/tests/DatePeriod_serialize-003.phpt new file mode 100644 index 0000000000000..ada8c7478f586 --- /dev/null +++ b/ext/date/tests/DatePeriod_serialize-003.phpt @@ -0,0 +1,209 @@ +--TEST-- +Test DatePeriod::__serialize and DatePeriod::__unserialize (start/end) +--FILE-- +__serialize()); + +echo "\n\nIterate of unserialised object:\n"; +foreach ( $e as $d ) +{ + echo $d->format(DateTime::ISO8601), "\n"; +} +?> +--EXPECTF-- +Original object: +object(DatePeriod)#4 (6) { + ["start"]=> + object(DateTimeImmutable)#5 (3) { + ["date"]=> + string(26) "1978-12-22 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["current"]=> + NULL + ["end"]=> + object(DateTimeImmutable)#6 (3) { + ["date"]=> + string(26) "2022-04-29 15:51:56.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" + } + ["interval"]=> + object(DateInterval)#7 (10) { + ["y"]=> + int(2) + ["m"]=> + int(6) + ["d"]=> + int(0) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(0) + ["include_start_date"]=> + bool(false) +} + + +Serialised object: +string(565) "O:10:"DatePeriod":6:{s:5:"start";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"1978-12-22 09:15:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:16:"Europe/Amsterdam";}s:7:"current";N;s:3:"end";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"2022-04-29 15:51:56.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:13:"Europe/London";}s:8:"interval";O:12:"DateInterval":10:{s:1:"y";i:2;s:1:"m";i:6;s:1:"d";i:0;s:1:"h";i:0;s:1:"i";i:0;s:1:"s";i:0;s:1:"f";d:0;s:6:"invert";i:0;s:4:"days";b:0;s:11:"from_string";b:0;}s:11:"recurrences";i:0;s:18:"include_start_date";b:0;}" + + +Unserialised object: +object(DatePeriod)#1 (6) { + ["start"]=> + object(DateTimeImmutable)#2 (3) { + ["date"]=> + string(26) "1978-12-22 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["current"]=> + NULL + ["end"]=> + object(DateTimeImmutable)#8 (3) { + ["date"]=> + string(26) "2022-04-29 15:51:56.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" + } + ["interval"]=> + object(DateInterval)#9 (10) { + ["y"]=> + int(2) + ["m"]=> + int(6) + ["d"]=> + int(0) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(0) + ["include_start_date"]=> + bool(false) +} + + +Calling __serialize manually: +array(6) { + ["start"]=> + object(DateTimeImmutable)#10 (3) { + ["date"]=> + string(26) "1978-12-22 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["current"]=> + NULL + ["end"]=> + object(DateTimeImmutable)#11 (3) { + ["date"]=> + string(26) "2022-04-29 15:51:56.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" + } + ["interval"]=> + object(DateInterval)#12 (10) { + ["y"]=> + int(2) + ["m"]=> + int(6) + ["d"]=> + int(0) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(0) + ["include_start_date"]=> + bool(false) +} + + +Iterate of unserialised object: +1981-06-22T09:15:00+0200 +1983-12-22T09:15:00+0100 +1986-06-22T09:15:00+0200 +1988-12-22T09:15:00+0100 +1991-06-22T09:15:00+0200 +1993-12-22T09:15:00+0100 +1996-06-22T09:15:00+0200 +1998-12-22T09:15:00+0100 +2001-06-22T09:15:00+0200 +2003-12-22T09:15:00+0100 +2006-06-22T09:15:00+0200 +2008-12-22T09:15:00+0100 +2011-06-22T09:15:00+0200 +2013-12-22T09:15:00+0100 +2016-06-22T09:15:00+0200 +2018-12-22T09:15:00+0100 +2021-06-22T09:15:00+0200 diff --git a/ext/date/tests/DatePeriod_serialize-004.phpt b/ext/date/tests/DatePeriod_serialize-004.phpt new file mode 100644 index 0000000000000..fd62c5e2b7630 --- /dev/null +++ b/ext/date/tests/DatePeriod_serialize-004.phpt @@ -0,0 +1,207 @@ +--TEST-- +Test DatePeriod::__serialize and DatePeriod::__unserialize (start/recurrences) +--FILE-- +format(DateTime::ISO8601), "\n"; +} + +echo "\n\nSerialised object:\n"; +$s = serialize($p); +var_dump($s); + +echo "\n\nUnserialised object:\n"; +$e = unserialize($s); +var_dump($e); + +echo "\n\nCalling __serialize manually:\n"; +var_dump($p->__serialize()); + +echo "\n\nIterate of unserialised object:\n"; +foreach ( $p as $d ) +{ + echo $d->format(DateTime::ISO8601), "\n"; +} +?> +--EXPECTF-- +Original object: +object(DatePeriod)#3 (6) { + ["start"]=> + object(DateTimeImmutable)#4 (3) { + ["date"]=> + string(26) "1978-12-22 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#5 (10) { + ["y"]=> + int(0) + ["m"]=> + int(1) + ["d"]=> + int(0) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(7) + ["include_start_date"]=> + bool(false) +} + + +Iterate of object: +1979-01-01T09:15:00+0100 +1979-02-05T09:15:00+0100 +1979-03-05T09:15:00+0100 +1979-04-02T09:15:00+0200 +1979-05-07T09:15:00+0200 +1979-06-04T09:15:00+0200 +1979-07-02T09:15:00+0200 + + +Serialised object: +string(568) "O:10:"DatePeriod":6:{s:5:"start";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"1978-12-22 09:15:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:16:"Europe/Amsterdam";}s:7:"current";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"1979-08-06 09:15:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:16:"Europe/Amsterdam";}s:3:"end";N;s:8:"interval";O:12:"DateInterval":10:{s:1:"y";i:0;s:1:"m";i:1;s:1:"d";i:0;s:1:"h";i:0;s:1:"i";i:0;s:1:"s";i:0;s:1:"f";d:0;s:6:"invert";i:0;s:4:"days";b:0;s:11:"from_string";b:0;}s:11:"recurrences";i:7;s:18:"include_start_date";b:0;}" + + +Unserialised object: +object(DatePeriod)#1 (6) { + ["start"]=> + object(DateTimeImmutable)#6 (3) { + ["date"]=> + string(26) "1978-12-22 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["current"]=> + object(DateTimeImmutable)#8 (3) { + ["date"]=> + string(26) "1979-08-06 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#9 (10) { + ["y"]=> + int(0) + ["m"]=> + int(1) + ["d"]=> + int(0) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(7) + ["include_start_date"]=> + bool(false) +} + + +Calling __serialize manually: +array(6) { + ["start"]=> + object(DateTimeImmutable)#10 (3) { + ["date"]=> + string(26) "1978-12-22 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["current"]=> + object(DateTimeImmutable)#11 (3) { + ["date"]=> + string(26) "1979-08-06 09:15:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "Europe/Amsterdam" + } + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#12 (10) { + ["y"]=> + int(0) + ["m"]=> + int(1) + ["d"]=> + int(0) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(7) + ["include_start_date"]=> + bool(false) +} + + +Iterate of unserialised object: +1979-01-01T09:15:00+0100 +1979-02-05T09:15:00+0100 +1979-03-05T09:15:00+0100 +1979-04-02T09:15:00+0200 +1979-05-07T09:15:00+0200 +1979-06-04T09:15:00+0200 +1979-07-02T09:15:00+0200 diff --git a/ext/date/tests/DatePeriod_set_state.phpt b/ext/date/tests/DatePeriod_set_state.phpt index eaef2163cc8a3..de41eac50a5f9 100644 --- a/ext/date/tests/DatePeriod_set_state.phpt +++ b/ext/date/tests/DatePeriod_set_state.phpt @@ -34,7 +34,7 @@ object(DatePeriod)#%d (6) { ["end"]=> NULL ["interval"]=> - object(DateInterval)#%d (16) { + object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -49,24 +49,12 @@ object(DatePeriod)#%d (6) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> bool(false) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } ["recurrences"]=> int(25) diff --git a/ext/date/tests/DateTimeImmutable_serialisation.phpt b/ext/date/tests/DateTimeImmutable_serialisation.phpt new file mode 100644 index 0000000000000..9c4c5bacf1a08 --- /dev/null +++ b/ext/date/tests/DateTimeImmutable_serialisation.phpt @@ -0,0 +1,118 @@ +--TEST-- +Test DateTimeImmutable::__serialize and DateTimeImmutable::__unserialize +--FILE-- +__serialize()); + +echo "\n\nCalling __unserialize manually:\n"; +$d = new DateTimeImmutable; +$d->__unserialize( + [ + 'date' => '2022-04-14 11:27:42.541106', + 'timezone_type' => 3, + 'timezone' => 'UTC', + ] +); +var_dump($d); + +echo "\n\nCalling __unserialize a few more times, with abbreviations:\n"; +$d->__unserialize( + [ + 'date' => '2022-04-14 11:27:42.541106', + 'timezone_type' => 2, + 'timezone' => 'CEST', + ] +); +var_dump($d); +$d->__unserialize( + [ + 'date' => '2022-04-14 11:27:42.541106', + 'timezone_type' => 1, + 'timezone' => '+0130', + ] +); +var_dump($d); + +?> +--EXPECTF-- +Original object: +object(DateTimeImmutable)#%d (%d) { + ["date"]=> + string(26) "2022-04-14 11:27:42.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" +} + + +Serialised object: +string(135) "O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"2022-04-14 11:27:42.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:13:"Europe/London";}" + + +Unserialised object: +object(DateTimeImmutable)#%d (%d) { + ["date"]=> + string(26) "2022-04-14 11:27:42.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" +} + + +Calling __serialize manually: +array(3) { + ["date"]=> + string(26) "2022-04-14 11:27:42.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" +} + + +Calling __unserialize manually: +object(DateTimeImmutable)#%d (%d) { + ["date"]=> + string(26) "2022-04-14 11:27:42.541106" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" +} + + +Calling __unserialize a few more times, with abbreviations: +object(DateTimeImmutable)#%d (%d) { + ["date"]=> + string(26) "2022-04-14 11:27:42.541106" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(4) "CEST" +} +object(DateTimeImmutable)#%d (%d) { + ["date"]=> + string(26) "2022-04-14 11:27:42.541106" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+01:30" +} diff --git a/ext/date/tests/DateTimeZone_serialisation.phpt b/ext/date/tests/DateTimeZone_serialisation.phpt new file mode 100644 index 0000000000000..60f6f4c59f5be --- /dev/null +++ b/ext/date/tests/DateTimeZone_serialisation.phpt @@ -0,0 +1,58 @@ +--TEST-- +Test DateTimeZone::__serialize and DateTime::__unserialize +--FILE-- +__serialize()); + +$tz = new DateTimeZone("UTC"); +$tz->__unserialize( + [ + 'timezone_type' => 3, + 'timezone' => 'Europe/London', + ] +); +var_dump($tz); + +$tz->__unserialize( + [ + 'timezone_type' => 2, + 'timezone' => 'CEST', + ] +); +var_dump($tz); + +$tz->__unserialize( + [ + 'timezone_type' => 1, + 'timezone' => '+0130', + ] +); +var_dump($tz); + +?> +--EXPECTF-- +array(2) { + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(4) "CEST" +} +object(DateTimeZone)#%d (%d) { + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" +} +object(DateTimeZone)#%d (%d) { + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(4) "CEST" +} +object(DateTimeZone)#%d (%d) { + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+01:30" +} diff --git a/ext/date/tests/DateTimeZone_serialize_errors.phpt b/ext/date/tests/DateTimeZone_serialize_errors.phpt new file mode 100644 index 0000000000000..f89e3bfafcbf4 --- /dev/null +++ b/ext/date/tests/DateTimeZone_serialize_errors.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test unserialization of DateTimeZone with null byte +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECTF-- +Warning: DateTimeZone::__unserialize(): Timezone must not contain null bytes in %s on line %d +Invalid serialization data for DateTimeZone object diff --git a/ext/date/tests/DateTime_serialisation.phpt b/ext/date/tests/DateTime_serialisation.phpt new file mode 100644 index 0000000000000..f7a34bd7f558b --- /dev/null +++ b/ext/date/tests/DateTime_serialisation.phpt @@ -0,0 +1,118 @@ +--TEST-- +Test DateTime::__serialize and DateTime::__unserialize +--FILE-- +__serialize()); + +echo "\n\nCalling __unserialize manually:\n"; +$d = new DateTime; +$d->__unserialize( + [ + 'date' => '2022-04-14 11:27:42.541106', + 'timezone_type' => 3, + 'timezone' => 'UTC', + ] +); +var_dump($d); + +echo "\n\nCalling __unserialize a few more times, with abbreviations:\n"; +$d->__unserialize( + [ + 'date' => '2022-04-14 11:27:42.541106', + 'timezone_type' => 2, + 'timezone' => 'CEST', + ] +); +var_dump($d); +$d->__unserialize( + [ + 'date' => '2022-04-14 11:27:42.541106', + 'timezone_type' => 1, + 'timezone' => '+0130', + ] +); +var_dump($d); + +?> +--EXPECTF-- +Original object: +object(DateTime)#%d (%d) { + ["date"]=> + string(26) "2022-04-14 11:27:42.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" +} + + +Serialised object: +string(125) "O:8:"DateTime":3:{s:4:"date";s:26:"2022-04-14 11:27:42.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:13:"Europe/London";}" + + +Unserialised object: +object(DateTime)#%d (%d) { + ["date"]=> + string(26) "2022-04-14 11:27:42.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" +} + + +Calling __serialize manually: +array(3) { + ["date"]=> + string(26) "2022-04-14 11:27:42.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" +} + + +Calling __unserialize manually: +object(DateTime)#%d (%d) { + ["date"]=> + string(26) "2022-04-14 11:27:42.541106" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" +} + + +Calling __unserialize a few more times, with abbreviations: +object(DateTime)#%d (%d) { + ["date"]=> + string(26) "2022-04-14 11:27:42.541106" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(4) "CEST" +} +object(DateTime)#%d (%d) { + ["date"]=> + string(26) "2022-04-14 11:27:42.541106" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+01:30" +} diff --git a/ext/date/tests/bug-gh8471.phpt b/ext/date/tests/bug-gh8471.phpt new file mode 100644 index 0000000000000..6857551008e08 --- /dev/null +++ b/ext/date/tests/bug-gh8471.phpt @@ -0,0 +1,50 @@ +--TEST-- +Bug GH-8471: Segmentation fault when converting immutable and mutable DateTime instances created using reflection +--FILE-- +newInstanceWithoutConstructor(); +try { + $immutable = \DateTimeImmutable::createFromMutable($mutable); +} catch (Throwable $t) { + echo $t->getMessage(), "\n"; +} + + +$reflection = new ReflectionClass('\DateTime'); + +$mutable = $reflection->newInstanceWithoutConstructor(); +try { + $immutable = \DateTimeImmutable::createFromInterface($mutable); +} catch (Throwable $t) { + echo $t->getMessage(), "\n"; +} + + +$reflection = new ReflectionClass('\DateTimeImmutable'); + +$immutable = $reflection->newInstanceWithoutConstructor(); +try { + $mutable = \DateTime::createFromImmutable($immutable); +} catch (Throwable $t) { + echo $t->getMessage(), "\n"; +} + + +$reflection = new ReflectionClass('\DateTimeImmutable'); + +$immutable = $reflection->newInstanceWithoutConstructor(); +try { + $mutable = \DateTime::createFromInterface($immutable); +} catch (Throwable $t) { + echo $t->getMessage(), "\n"; +} + + +?> +--EXPECTF-- +The DateTime object has not been correctly initialized by its constructor +The DateTimeInterface object has not been correctly initialized by its constructor +The DateTimeImmutable object has not been correctly initialized by its constructor +The DateTimeInterface object has not been correctly initialized by its constructor diff --git a/ext/date/tests/bug45682.phpt b/ext/date/tests/bug45682.phpt index 636381dcfeda0..84178aadb8447 100644 --- a/ext/date/tests/bug45682.phpt +++ b/ext/date/tests/bug45682.phpt @@ -13,7 +13,7 @@ $diff = date_diff($date, $other); var_dump($diff); ?> --EXPECTF-- -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -28,22 +28,10 @@ object(DateInterval)#%d (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(3) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } diff --git a/ext/date/tests/bug48678.phpt b/ext/date/tests/bug48678.phpt index 9c1cecd2df780..3934b187e7098 100644 --- a/ext/date/tests/bug48678.phpt +++ b/ext/date/tests/bug48678.phpt @@ -17,15 +17,9 @@ DateInterval Object [i] => 30 [s] => 5 [f] => 0 - [weekday] => 0 - [weekday_behavior] => 0 - [first_last_day_of] => 0 [invert] => 0 [days] => - [special_type] => 0 - [special_amount] => 0 - [have_weekday_relative] => 0 - [have_special_relative] => 0 + [from_string] => ) DateInterval Object ( @@ -36,13 +30,7 @@ DateInterval Object [i] => 30 [s] => 5 [f] => 0 - [weekday] => 0 - [weekday_behavior] => 0 - [first_last_day_of] => 0 [invert] => 0 [days] => - [special_type] => 0 - [special_amount] => 0 - [have_weekday_relative] => 0 - [have_special_relative] => 0 + [from_string] => ) diff --git a/ext/date/tests/bug49081.phpt b/ext/date/tests/bug49081.phpt index b5d17a6c264b6..6f98041e8f74d 100644 --- a/ext/date/tests/bug49081.phpt +++ b/ext/date/tests/bug49081.phpt @@ -18,13 +18,7 @@ DateInterval Object [i] => 0 [s] => 0 [f] => 0 - [weekday] => 0 - [weekday_behavior] => 0 - [first_last_day_of] => 0 [invert] => 0 [days] => 30 - [special_type] => 0 - [special_amount] => 0 - [have_weekday_relative] => 0 - [have_special_relative] => 0 + [from_string] => ) diff --git a/ext/date/tests/bug49778.phpt b/ext/date/tests/bug49778.phpt index 56ce135179222..d4e1a2c0ace03 100644 --- a/ext/date/tests/bug49778.phpt +++ b/ext/date/tests/bug49778.phpt @@ -8,7 +8,7 @@ echo $i->format("%d"), "\n"; echo $i->format("%a"), "\n"; ?> --EXPECTF-- -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -23,24 +23,12 @@ object(DateInterval)#%d (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> bool(false) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } 7 (unknown) diff --git a/ext/date/tests/bug52113.phpt b/ext/date/tests/bug52113.phpt index f6d0962625db4..2e02195bd1d1a 100644 --- a/ext/date/tests/bug52113.phpt +++ b/ext/date/tests/bug52113.phpt @@ -16,7 +16,7 @@ $diff_un = unserialize($diff_s); $p = new DatePeriod($start, $diff_un, 2); var_dump($diff_un, $p); -$unser = DateInterval::__set_state(array( +$unser = \DateInterval::__set_state(array( 'y' => 7, 'm' => 6, 'd' => 5, @@ -33,7 +33,7 @@ var_dump($unser, $p); ?> --EXPECTF-- -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -48,27 +48,15 @@ object(DateInterval)#%d (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(0) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } -string(332) "O:12:"DateInterval":16:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:4;s:1:"i";i:0;s:1:"s";i:0;s:1:"f";d:0;s:7:"weekday";i:0;s:16:"weekday_behavior";i:0;s:17:"first_last_day_of";i:0;s:6:"invert";i:0;s:4:"days";i:0;s:12:"special_type";i:0;s:14:"special_amount";i:0;s:21:"have_weekday_relative";i:0;s:21:"have_special_relative";i:0;}" -DateInterval::__set_state(array( +string(164) "O:12:"DateInterval":10:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:4;s:1:"i";i:0;s:1:"s";i:0;s:1:"f";d:0;s:6:"invert";i:0;s:4:"days";i:0;s:11:"from_string";b:0;}" +\DateInterval::__set_state(array( 'y' => 0, 'm' => 0, 'd' => 0, @@ -76,16 +64,10 @@ DateInterval::__set_state(array( 'i' => 0, 's' => 0, 'f' => 0.0, - 'weekday' => 0, - 'weekday_behavior' => 0, - 'first_last_day_of' => 0, 'invert' => 0, 'days' => 0, - 'special_type' => 0, - 'special_amount' => 0, - 'have_weekday_relative' => 0, - 'have_special_relative' => 0, -))object(DateInterval)#%d (16) { + 'from_string' => false, +))object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -100,24 +82,12 @@ DateInterval::__set_state(array( int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(0) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } object(DatePeriod)#%d (6) { ["start"]=> @@ -134,7 +104,7 @@ object(DatePeriod)#%d (6) { ["end"]=> NULL ["interval"]=> - object(DateInterval)#%d (16) { + object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -149,31 +119,19 @@ object(DatePeriod)#%d (6) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(0) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } ["recurrences"]=> int(3) ["include_start_date"]=> bool(true) } -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(7) ["m"]=> @@ -188,24 +146,12 @@ object(DateInterval)#%d (16) { int(2) ["f"]=> float(0.876543) - ["weekday"]=> - int(-1) - ["weekday_behavior"]=> - int(-1) - ["first_last_day_of"]=> - int(-1) ["invert"]=> int(1) ["days"]=> int(2400) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(-1) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } object(DatePeriod)#%d (6) { ["start"]=> @@ -222,7 +168,7 @@ object(DatePeriod)#%d (6) { ["end"]=> NULL ["interval"]=> - object(DateInterval)#%d (16) { + object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -237,24 +183,12 @@ object(DatePeriod)#%d (6) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(0) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } ["recurrences"]=> int(3) diff --git a/ext/date/tests/bug52738.phpt b/ext/date/tests/bug52738.phpt index 4f51fc38988a4..e0f3a1ef5c84b 100644 --- a/ext/date/tests/bug52738.phpt +++ b/ext/date/tests/bug52738.phpt @@ -29,13 +29,7 @@ di Object [i] => 0 [s] => 0 [f] => 0 - [weekday] => 0 - [weekday_behavior] => 0 - [first_last_day_of] => 0 [invert] => 0 [days] => - [special_type] => 0 - [special_amount] => 0 - [have_weekday_relative] => 0 - [have_special_relative] => 0 + [from_string] => ) diff --git a/ext/date/tests/bug52808.phpt b/ext/date/tests/bug52808.phpt index c0ab817bcc84b..a059624fdd7a0 100644 --- a/ext/date/tests/bug52808.phpt +++ b/ext/date/tests/bug52808.phpt @@ -25,7 +25,7 @@ foreach($intervals as $iv) { echo "==DONE==\n"; ?> --EXPECTF-- -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(1) ["m"]=> @@ -40,26 +40,14 @@ object(DateInterval)#%d (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(1) ["days"]=> int(437) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -74,26 +62,14 @@ object(DateInterval)#%d (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(294) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -108,24 +84,12 @@ object(DateInterval)#%d (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(294) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } Failed to parse interval (2007-05-11T15:30:00Z/) Failed to parse interval (2007-05-11T15:30:00Z) diff --git a/ext/date/tests/bug53437.phpt b/ext/date/tests/bug53437_var0.phpt similarity index 78% rename from ext/date/tests/bug53437.phpt rename to ext/date/tests/bug53437_var0.phpt index f19f073aa9430..36b6c317177f2 100644 --- a/ext/date/tests/bug53437.phpt +++ b/ext/date/tests/bug53437_var0.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #53437 (Crash when using unserialized DatePeriod instance), variation 1 +Bug #53437 (Crash when using unserialized DatePeriod instance), variation 0 --FILE-- NULL ["interval"]=> - object(DateInterval)#%d (16) { + object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -65,24 +65,12 @@ object(DatePeriod)#%d (6) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> bool(false) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } ["recurrences"]=> int(3) @@ -111,7 +99,7 @@ object(DatePeriod)#%d (6) { ["end"]=> NULL ["interval"]=> - object(DateInterval)#%d (16) { + object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -126,24 +114,12 @@ object(DatePeriod)#%d (6) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> bool(false) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } ["recurrences"]=> int(3) diff --git a/ext/date/tests/bug53437_var1.phpt b/ext/date/tests/bug53437_var1.phpt index 938439abe8837..9413c6ffdab3f 100644 --- a/ext/date/tests/bug53437_var1.phpt +++ b/ext/date/tests/bug53437_var1.phpt @@ -12,7 +12,7 @@ var_dump($dp); --EXPECTF-- Fatal error: Uncaught Error: Invalid serialization data for DatePeriod object in %sbug53437_var1.php:%d Stack trace: -#0 [internal function]: DatePeriod->__wakeup() +#0 [internal function]: DatePeriod->__unserialize(Array) #1 %sbug53437_var1.php(%d): unserialize('O:10:"DatePerio...') #2 {main} thrown in %sbug53437_var1.php on line %d diff --git a/ext/date/tests/bug53437_var2.phpt b/ext/date/tests/bug53437_var2.phpt index 7a87b38421a50..9ca6a0f6b2762 100644 --- a/ext/date/tests/bug53437_var2.phpt +++ b/ext/date/tests/bug53437_var2.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #53437 DateInterval basic serialization +Bug #53437 (DateInterval basic serialization) --FILE-- ---EXPECT-- -object(DateInterval)#1 (16) { +--EXPECTF-- +object(DateInterval)#1 (%d) { ["y"]=> int(2) ["m"]=> @@ -27,26 +27,14 @@ object(DateInterval)#1 (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> bool(false) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } -object(DateInterval)#2 (16) { +object(DateInterval)#2 (%d) { ["y"]=> int(2) ["m"]=> @@ -61,22 +49,10 @@ object(DateInterval)#2 (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> bool(false) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } diff --git a/ext/date/tests/bug53437_var3.phpt b/ext/date/tests/bug53437_var3.phpt index eb043398e2daa..6fd5f11f0301b 100644 --- a/ext/date/tests/bug53437_var3.phpt +++ b/ext/date/tests/bug53437_var3.phpt @@ -11,7 +11,7 @@ var_dump($di); ?> --EXPECTF-- -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(2) ["m"]=> @@ -24,24 +24,12 @@ object(DateInterval)#%d (16) { int(8) ["s"]=> int(0) - ["weekday"]=> - int(10) - ["weekday_behavior"]=> - int(10) - ["first_last_day_of"]=> - int(0) + ["f"]=> + float(0) ["invert"]=> int(0) ["days"]=> int(0) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(-1) - ["have_weekday_relative"]=> - int(%d) - ["have_special_relative"]=> - int(0) - ["f"]=> - float(0) + ["from_string"]=> + bool(false) } diff --git a/ext/date/tests/bug53437_var4.phpt b/ext/date/tests/bug53437_var4.phpt index b53483ab7fa2b..14823fb4ba47f 100644 --- a/ext/date/tests/bug53437_var4.phpt +++ b/ext/date/tests/bug53437_var4.phpt @@ -21,7 +21,7 @@ var_dump($df, ?> --EXPECTF-- -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -36,24 +36,12 @@ object(DateInterval)#%d (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(2) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } int(0) int(0) diff --git a/ext/date/tests/bug53437_var5.phpt b/ext/date/tests/bug53437_var5.phpt index 55bba9ed59d8f..eb3722f38bb36 100644 --- a/ext/date/tests/bug53437_var5.phpt +++ b/ext/date/tests/bug53437_var5.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #53437 DateInterval unserialize bad data, 64 bit +Bug #53437 (DateInterval unserialize bad data, 64 bit) --SKIPIF-- --FILE-- @@ -11,7 +11,7 @@ var_dump($di); ?> --EXPECTF-- -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(2) ["m"]=> @@ -24,24 +24,12 @@ object(DateInterval)#%d (16) { int(8) ["s"]=> int(0) - ["weekday"]=> - int(10) - ["weekday_behavior"]=> - int(10) - ["first_last_day_of"]=> - int(0) + ["f"]=> + float(0) ["invert"]=> int(0) ["days"]=> int(0) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(9223372036854775807) - ["have_weekday_relative"]=> - int(9) - ["have_special_relative"]=> - int(0) - ["f"]=> - float(0) + ["from_string"]=> + bool(false) } diff --git a/ext/date/tests/bug53437_var6.phpt b/ext/date/tests/bug53437_var6.phpt index f5ff22c4a4612..cb76c66d4d9d3 100644 --- a/ext/date/tests/bug53437_var6.phpt +++ b/ext/date/tests/bug53437_var6.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #53437 DateInterval unserialize bad data, 64 bit +Bug #53437 (DateInterval unserialize bad data, 64 bit) --SKIPIF-- --FILE-- @@ -11,7 +11,7 @@ var_dump($di); ?> --EXPECTF-- -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(2) ["m"]=> @@ -26,22 +26,10 @@ object(DateInterval)#%d (16) { int(0) ["f"]=> float(0.123654) - ["weekday"]=> - int(10) - ["weekday_behavior"]=> - int(10) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(0) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(9223372036854775807) - ["have_weekday_relative"]=> - int(9) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } diff --git a/ext/date/tests/bug55397.phpt b/ext/date/tests/bug55397.phpt index 98f29a25b5356..559490dfa3bfa 100644 --- a/ext/date/tests/bug55397.phpt +++ b/ext/date/tests/bug55397.phpt @@ -8,7 +8,7 @@ var_dump(unserialize('O:8:"DateTime":0:{}') == new DateTime); --EXPECTF-- Fatal error: Uncaught Error: Invalid serialization data for DateTime object in %sbug55397.php:%d Stack trace: -#0 [internal function]: DateTime->__wakeup() +#0 [internal function]: DateTime->__unserialize(Array) #1 %sbug55397.php(%d): unserialize('O:8:"DateTime":...') #2 {main} thrown in %sbug55397.php on line %d diff --git a/ext/date/tests/bug60774.phpt b/ext/date/tests/bug60774.phpt index 0a9c4223c37c3..2f3de6bafd141 100644 --- a/ext/date/tests/bug60774.phpt +++ b/ext/date/tests/bug60774.phpt @@ -9,38 +9,10 @@ echo $i->format("%a"), "\n"; ?> --EXPECTF-- object(DateInterval)#1 (%d) { - ["y"]=> - int(0) - ["m"]=> - int(0) - ["d"]=> - int(2) - ["h"]=> - int(0) - ["i"]=> - int(0) - ["s"]=> - int(0) - ["f"]=> - float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) - ["invert"]=> - int(0) - ["days"]=> - bool(false) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(true) + ["date_string"]=> + string(6) "2 days" } 2 (unknown) diff --git a/ext/date/tests/bug62852.phpt b/ext/date/tests/bug62852.phpt index 4ec9a0eab1ca6..120c08faf2393 100644 --- a/ext/date/tests/bug62852.phpt +++ b/ext/date/tests/bug62852.phpt @@ -13,7 +13,7 @@ try { --EXPECTF-- Fatal error: Uncaught Error: Invalid serialization data for DateTime object in %sbug62852.php:%d Stack trace: -#0 [internal function]: DateTime->__wakeup() +#0 [internal function]: DateTime->__unserialize(Array) #1 %sbug62852.php(%d): unserialize('O:8:"DateTime":...') #2 {main} thrown in %sbug62852.php on line %d diff --git a/ext/date/tests/bug62852_var2.phpt b/ext/date/tests/bug62852_var2.phpt index 57fbd6e94e955..4749d2a9bb21f 100644 --- a/ext/date/tests/bug62852_var2.phpt +++ b/ext/date/tests/bug62852_var2.phpt @@ -24,8 +24,7 @@ var_dump( $foo ); --EXPECTF-- Fatal error: Uncaught Error: Invalid serialization data for DateTime object in %sbug62852_var2.php:%d Stack trace: -#0 %sbug62852_var2.php(%d): DateTime->__wakeup() -#1 [internal function]: Foo->__wakeup() -#2 %sbug62852_var2.php(%d): unserialize('O:3:"Foo":3:{s:...') -#3 {main} +#0 [internal function]: DateTime->__unserialize(Array) +#1 %sbug62852_var2.php(%d): unserialize('O:3:"Foo":3:{s:...') +#2 {main} thrown in %sbug62852_var2.php on line %d diff --git a/ext/date/tests/bug62852_var3.phpt b/ext/date/tests/bug62852_var3.phpt index df3669893f257..7049efcebd84f 100644 --- a/ext/date/tests/bug62852_var3.phpt +++ b/ext/date/tests/bug62852_var3.phpt @@ -24,8 +24,7 @@ var_dump( $foo ); --EXPECTF-- Fatal error: Uncaught Error: Invalid serialization data for DateTime object in %sbug62852_var3.php:%d Stack trace: -#0 %sbug62852_var3.php(%d): DateTime->__wakeup() -#1 [internal function]: Foo->__wakeup() -#2 %sbug62852_var3.php(%d): unserialize('O:3:"Foo":3:{s:...') -#3 {main} +#0 [internal function]: DateTime->__unserialize(Array) +#1 %sbug62852_var3.php(%d): unserialize('O:3:"Foo":3:{s:...') +#2 {main} thrown in %sbug62852_var3.php on line %d diff --git a/ext/date/tests/bug66545.phpt b/ext/date/tests/bug66545.phpt index 276c6d5f67581..0d2f337570698 100644 --- a/ext/date/tests/bug66545.phpt +++ b/ext/date/tests/bug66545.phpt @@ -25,13 +25,7 @@ DateInterval Object [i] => 59 [s] => 59 [f] => 0 - [weekday] => 0 - [weekday_behavior] => 0 - [first_last_day_of] => 0 [invert] => 0 [days] => 14 - [special_type] => 0 - [special_amount] => 0 - [have_weekday_relative] => 0 - [have_special_relative] => 0 + [from_string] => ) diff --git a/ext/date/tests/bug66721.phpt b/ext/date/tests/bug66721.phpt index 9effb7ca5622e..5636aa6036b9f 100644 --- a/ext/date/tests/bug66721.phpt +++ b/ext/date/tests/bug66721.phpt @@ -1,5 +1,5 @@ --TEST-- -Test for bug #66721: __wakeup of DateTime segfaults when invalid object data is supplied +Test for bug #66721: __unserialize of DateTime segfaults when invalid object data is supplied --CREDITS-- Boro Sitnikovski --FILE-- @@ -10,7 +10,7 @@ var_dump(unserialize($y)); --EXPECTF-- Fatal error: Uncaught Error: Invalid serialization data for DateTime object in %sbug66721.php:%d Stack trace: -#0 [internal function]: DateTime->__wakeup() +#0 [internal function]: DateTime->__unserialize(Array) #1 %sbug66721.php(%d): unserialize('O:8:"DateTime":...') #2 {main} thrown in %sbug66721.php on line %d diff --git a/ext/date/tests/bug68942.phpt b/ext/date/tests/bug68942.phpt index 9a9a5cfb888f0..91df60b007b62 100644 --- a/ext/date/tests/bug68942.phpt +++ b/ext/date/tests/bug68942.phpt @@ -6,9 +6,9 @@ $data = unserialize('a:2:{i:0;O:12:"DateTimeZone":2:{s:13:"timezone_type";a:2:{i var_dump($data); ?> --EXPECTF-- -Fatal error: Uncaught Error: Timezone initialization failed in %s:%d +Fatal error: Uncaught Error: Invalid serialization data for DateTimeZone object in %s:%d Stack trace: -#0 [internal function]: DateTimeZone->__wakeup() +#0 [internal function]: DateTimeZone->__unserialize(Array) #1 %s(%d): unserialize('a:2:{i:0;O:12:"...') #2 {main} thrown in %s on line %d diff --git a/ext/date/tests/bug68942_2.phpt b/ext/date/tests/bug68942_2.phpt index 9870bbce5c997..5718db92ce37b 100644 --- a/ext/date/tests/bug68942_2.phpt +++ b/ext/date/tests/bug68942_2.phpt @@ -8,7 +8,7 @@ var_dump($data); --EXPECTF-- Fatal error: Uncaught Error: Invalid serialization data for DateTime object in %sbug68942_2.php:%d Stack trace: -#0 [internal function]: DateTime->__wakeup() +#0 [internal function]: DateTime->__unserialize(Array) #1 %sbug68942_2.php(%d): unserialize('a:2:{i:0;O:8:"D...') #2 {main} thrown in %sbug68942_2.php on line %d diff --git a/ext/date/tests/bug70153.phpt b/ext/date/tests/bug70153.phpt index 5b965207fc27d..9aaa0e7d538fa 100644 --- a/ext/date/tests/bug70153.phpt +++ b/ext/date/tests/bug70153.phpt @@ -3,12 +3,29 @@ Bug #70153 (\DateInterval incorrectly unserialized) --FILE-- days, $i2->days); -var_dump($i2->special_amount, $i2->special_amount); ?> --EXPECT-- +DateInterval Object +( + [from_string] => 1 + [date_string] => +1 month +) +O:12:"DateInterval":2:{s:11:"from_string";b:1;s:11:"date_string";s:8:"+1 month";} +DateInterval Object +( + [from_string] => 1 + [date_string] => +1 month +) bool(false) bool(false) -int(0) -int(0) diff --git a/ext/date/tests/bug71700.phpt b/ext/date/tests/bug71700.phpt index 53a6f9db20992..09f6e76058c52 100644 --- a/ext/date/tests/bug71700.phpt +++ b/ext/date/tests/bug71700.phpt @@ -11,8 +11,8 @@ $diff = date_diff($date1, $date2, true); var_dump($diff); ?> ---EXPECT-- -object(DateInterval)#3 (16) { +--EXPECTF-- +object(DateInterval)#3 (%d) { ["y"]=> int(0) ["m"]=> @@ -27,22 +27,10 @@ object(DateInterval)#3 (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(30) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } diff --git a/ext/date/tests/bug73091.phpt b/ext/date/tests/bug73091.phpt index 918170d823fb1..440f2bbca60d2 100644 --- a/ext/date/tests/bug73091.phpt +++ b/ext/date/tests/bug73091.phpt @@ -12,9 +12,7 @@ class foo { var_dump(unserialize('O:12:"DateInterval":1:{s:4:"days";O:3:"foo":0:{}}')); ?> --EXPECTF-- -object(DateInterval)#%d (16) { - ["days"]=> - int(-1) +object(DateInterval)#%d (%d) { ["y"]=> int(-1) ["m"]=> @@ -29,20 +27,10 @@ object(DateInterval)#%d (16) { int(-1) ["f"]=> float(0) - ["weekday"]=> - int(-1) - ["weekday_behavior"]=> - int(-1) - ["first_last_day_of"]=> - int(-1) ["invert"]=> int(0) - ["special_type"]=> - int(0) - ["special_amount"]=> + ["days"]=> int(-1) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } diff --git a/ext/date/tests/bug73837.phpt b/ext/date/tests/bug73837.phpt index de7c8d7079ac2..86fd0a871f8fe 100644 --- a/ext/date/tests/bug73837.phpt +++ b/ext/date/tests/bug73837.phpt @@ -1,20 +1,24 @@ --TEST-- Bug #73837: Milliseconds in DateTime() +--SKIPIF-- + --FILE-- format( "u" ); - $collect[$key] = true; +$startTS = time(); +$prev_dt = new DateTime(); +while (time() < $startTS + 2) { + $dt = new DateTime(); + if ($prev_dt > $dt) { + var_dump($prev_dt->format("Y-m-d H:i:s.u")); + var_dump($dt->format("Y-m-d H:i:s.u")); + break; + } + $prev_dt = $dt; } -// For low-resolution clocks, we may construct many objects in the same tick. -var_dump($n = count( $collect )); -echo $n > 200 ? "microseconds differ\n" : "microseconds do not differ enough ($n)\n"; +echo "Finished\n"; ?> --EXPECTF-- -int(%d) -microseconds differ +Finished diff --git a/ext/date/tests/bug74274.phpt b/ext/date/tests/bug74274.phpt index e03d40cf88da7..20387419728de 100644 --- a/ext/date/tests/bug74274.phpt +++ b/ext/date/tests/bug74274.phpt @@ -18,13 +18,7 @@ DateInterval Object [i] => 0 [s] => 0 [f] => 0 - [weekday] => 0 - [weekday_behavior] => 0 - [first_last_day_of] => 0 [invert] => 0 [days] => 1 - [special_type] => 0 - [special_amount] => 0 - [have_weekday_relative] => 0 - [have_special_relative] => 0 + [from_string] => ) diff --git a/ext/date/tests/bug74524.phpt b/ext/date/tests/bug74524.phpt index f49a5340185e9..825fb0be8b301 100644 --- a/ext/date/tests/bug74524.phpt +++ b/ext/date/tests/bug74524.phpt @@ -20,13 +20,7 @@ DateInterval Object [i] => 36 [s] => 10 [f] => 0.920541 - [weekday] => 0 - [weekday_behavior] => 0 - [first_last_day_of] => 0 [invert] => 1 [days] => 227 - [special_type] => 0 - [special_amount] => 0 - [have_weekday_relative] => 0 - [have_special_relative] => 0 + [from_string] => ) diff --git a/ext/date/tests/bug77571.phpt b/ext/date/tests/bug77571.phpt index f6a5b55dab0f6..84790e0cd67b9 100644 --- a/ext/date/tests/bug77571.phpt +++ b/ext/date/tests/bug77571.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #77571 (DateTime's diff DateInterval incorrect in timezones from UTC+01:00 to UTC+12:00 +Bug #77571 (DateTime's diff DateInterval incorrect in timezones from UTC+01:00 to UTC+12:00) --FILE-- 0 [s] => 0 [f] => 0 - [weekday] => 0 - [weekday_behavior] => 0 - [first_last_day_of] => 0 [invert] => 0 [days] => 35 - [special_type] => 0 - [special_amount] => 0 - [have_weekday_relative] => 0 - [have_special_relative] => 0 + [from_string] => ) diff --git a/ext/date/tests/bug78452.phpt b/ext/date/tests/bug78452.phpt index a4b095de03abb..ba6936551168b 100644 --- a/ext/date/tests/bug78452.phpt +++ b/ext/date/tests/bug78452.phpt @@ -7,8 +7,8 @@ $date1 = new \DateTime('2019-09-24 11:47:24'); $date2 = new \DateTime('2019-08-21 12:47:24'); var_dump($date1->diff($date2)); ?> ---EXPECT-- -object(DateInterval)#3 (16) { +--EXPECTF-- +object(DateInterval)#3 (%d) { ["y"]=> int(0) ["m"]=> @@ -23,22 +23,10 @@ object(DateInterval)#3 (16) { int(0) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(1) ["days"]=> int(33) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } diff --git a/ext/date/tests/bug79015.phpt b/ext/date/tests/bug79015.phpt index 9d752dee7221e..63dac799c5403 100644 --- a/ext/date/tests/bug79015.phpt +++ b/ext/date/tests/bug79015.phpt @@ -6,7 +6,7 @@ $payload = 'O:12:"DateInterval":16:{s:1:"y";i:1;s:1:"m";i:0;s:1:"d";i:4;s:1:"h"; var_dump(unserialize($payload)); ?> --EXPECTF-- -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(1) ["m"]=> @@ -21,22 +21,10 @@ object(DateInterval)#%d (16) { int(0) ["f"]=> float(%f) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> bool(false) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } diff --git a/ext/date/tests/date_diff1.phpt b/ext/date/tests/date_diff1.phpt index 2b73eae6a8cc3..fa2c64ddd59d4 100644 --- a/ext/date/tests/date_diff1.phpt +++ b/ext/date/tests/date_diff1.phpt @@ -28,7 +28,7 @@ object(DateTime)#2 (3) { ["timezone"]=> string(3) "EDT" } -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -36,29 +36,17 @@ object(DateInterval)#%d (16) { ["d"]=> int(2) ["h"]=> - int(16) + int(%d) ["i"]=> int(19) ["s"]=> int(40) ["f"]=> float(0) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(33) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } diff --git a/ext/date/tests/date_interval_non_relative_warning.phpt b/ext/date/tests/date_interval_non_relative_warning.phpt new file mode 100644 index 0000000000000..fc0b246277940 --- /dev/null +++ b/ext/date/tests/date_interval_non_relative_warning.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-8458 (DateInterval::createFromDateString does not warn when non-relative items are present) +--FILE-- + +--EXPECTF-- +Warning: DateInterval::createFromDateString(): String 'next weekday 15:30' contains non-relative elements in %sdate_interval_non_relative_warning.php on line %d + +Warning: DateInterval::createFromDateString(): String '+5 hours noon' contains non-relative elements in %sdate_interval_non_relative_warning.php on line %d + +Warning: DateInterval::createFromDateString(): String '-8 days March 23' contains non-relative elements in %sdate_interval_non_relative_warning.php on line %d + +Warning: DateInterval::createFromDateString(): String '+72 seconds UTC' contains non-relative elements in %sdate_interval_non_relative_warning.php on line %d + +Warning: date_interval_create_from_date_string(): String 'next weekday 15:30' contains non-relative elements in %sdate_interval_non_relative_warning.php on line %d + +Warning: date_interval_create_from_date_string(): String '+5 hours noon' contains non-relative elements in %sdate_interval_non_relative_warning.php on line %d + +Warning: date_interval_create_from_date_string(): String '-8 days March 23' contains non-relative elements in %sdate_interval_non_relative_warning.php on line %d + +Warning: date_interval_create_from_date_string(): String '+72 seconds UTC' contains non-relative elements in %sdate_interval_non_relative_warning.php on line %d diff --git a/ext/date/tests/date_time_fractions.phpt b/ext/date/tests/date_time_fractions.phpt index 29f7cd0d14103..4536e0f2eb21e 100644 --- a/ext/date/tests/date_time_fractions.phpt +++ b/ext/date/tests/date_time_fractions.phpt @@ -58,7 +58,7 @@ microseconds = true 2016-10-02 00:00:00.000000 2016-10-03 12:00:00.000000 2016-10-17 12:47:18.081921 -object(DateInterval)#%d (16) { +object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -73,24 +73,12 @@ object(DateInterval)#%d (16) { int(0) ["f"]=> float(0.378189) - ["weekday"]=> - int(0) - ["weekday_behavior"]=> - int(0) - ["first_last_day_of"]=> - int(0) ["invert"]=> int(0) ["days"]=> int(0) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(0) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } 2016-10-03 13:20:06.724934 2016-10-03 13:20:07.103123 diff --git a/ext/dl_test/config.m4 b/ext/dl_test/config.m4 new file mode 100644 index 0000000000000..10f1adae71b08 --- /dev/null +++ b/ext/dl_test/config.m4 @@ -0,0 +1,8 @@ +PHP_ARG_ENABLE([dl-test], + [whether to enable dl-test extension], + [AS_HELP_STRING([--enable-dl-test], + [Enable dl_test extension])]) + +if test "$PHP_DL_TEST" != "no"; then + PHP_NEW_EXTENSION(dl_test, dl_test.c, [shared],, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) +fi diff --git a/ext/dl_test/config.w32 b/ext/dl_test/config.w32 new file mode 100644 index 0000000000000..8f50eb58c3448 --- /dev/null +++ b/ext/dl_test/config.w32 @@ -0,0 +1,8 @@ +// vim:ft=javascript + +ARG_ENABLE("dl-test", "enable dl_test extension", "no"); + +if (PHP_DL_TEST != "no") { + EXTENSION("dl_test", "dl_test.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + ADD_FLAG("CFLAGS_DL_TEST", "/D PHP_DL_TEST_EXPORTS "); +} diff --git a/ext/dl_test/dl_test.c b/ext/dl_test/dl_test.c new file mode 100644 index 0000000000000..88a298b0ec88a --- /dev/null +++ b/ext/dl_test/dl_test.c @@ -0,0 +1,146 @@ +/* + +----------------------------------------------------------------------+ + | 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: Arnaud Le Blanc | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "php.h" +#include "ext/standard/info.h" +#include "php_dl_test.h" +#include "dl_test_arginfo.h" + +ZEND_DECLARE_MODULE_GLOBALS(dl_test) + +/* {{{ void dl_test_test1() */ +PHP_FUNCTION(dl_test_test1) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + php_printf("The extension %s is loaded and working!\r\n", "dl_test"); +} +/* }}} */ + +/* {{{ string dl_test_test2( [ string $var ] ) */ +PHP_FUNCTION(dl_test_test2) +{ + char *var = "World"; + size_t var_len = sizeof("World") - 1; + zend_string *retval; + + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_STRING(var, var_len) + ZEND_PARSE_PARAMETERS_END(); + + retval = strpprintf(0, "Hello %s", var); + + RETURN_STR(retval); +} +/* }}}*/ + +/* {{{ INI */ +PHP_INI_BEGIN() + STD_PHP_INI_BOOLEAN("dl_test.long", "0", PHP_INI_ALL, OnUpdateLong, long_value, zend_dl_test_globals, dl_test_globals) + STD_PHP_INI_ENTRY("dl_test.string", "hello", PHP_INI_ALL, OnUpdateString, string_value, zend_dl_test_globals, dl_test_globals) +PHP_INI_END() +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION */ +PHP_MINIT_FUNCTION(dl_test) +{ + /* Test backwards compatibility */ + if (getenv("PHP_DL_TEST_USE_OLD_REGISTER_INI_ENTRIES")) { + zend_register_ini_entries(ini_entries, module_number); + } else { + REGISTER_INI_ENTRIES(); + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MSHUTDOWN_FUNCTION */ +static PHP_MSHUTDOWN_FUNCTION(dl_test) +{ + /* Test backwards compatibility */ + if (getenv("PHP_DL_TEST_USE_OLD_REGISTER_INI_ENTRIES")) { + zend_unregister_ini_entries(module_number); + } else { + UNREGISTER_INI_ENTRIES(); + } + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_RINIT_FUNCTION */ +PHP_RINIT_FUNCTION(dl_test) +{ +#if defined(ZTS) && defined(COMPILE_DL_DL_TEST) + ZEND_TSRMLS_CACHE_UPDATE(); +#endif + + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION */ +PHP_MINFO_FUNCTION(dl_test) +{ + php_info_print_table_start(); + php_info_print_table_header(2, "dl_test support", "enabled"); + php_info_print_table_end(); + + DISPLAY_INI_ENTRIES(); +} +/* }}} */ + +/* {{{ PHP_GINIT_FUNCTION */ +static PHP_GINIT_FUNCTION(dl_test) +{ +#if defined(COMPILE_DL_DL_TEST) && defined(ZTS) + ZEND_TSRMLS_CACHE_UPDATE(); +#endif + memset(dl_test_globals, 0, sizeof(*dl_test_globals)); +} +/* }}} */ + +/* {{{ dl_test_module_entry */ +zend_module_entry dl_test_module_entry = { + STANDARD_MODULE_HEADER, + "dl_test", + ext_functions, + PHP_MINIT(dl_test), + PHP_MSHUTDOWN(dl_test), + PHP_RINIT(dl_test), + NULL, + PHP_MINFO(dl_test), + PHP_DL_TEST_VERSION, + PHP_MODULE_GLOBALS(dl_test), + PHP_GINIT(dl_test), + NULL, + NULL, + STANDARD_MODULE_PROPERTIES_EX +}; +/* }}} */ + +#ifdef COMPILE_DL_DL_TEST +# ifdef ZTS +ZEND_TSRMLS_CACHE_DEFINE() +# endif +ZEND_GET_MODULE(dl_test) +#endif diff --git a/ext/dl_test/dl_test.stub.php b/ext/dl_test/dl_test.stub.php new file mode 100644 index 0000000000000..36d59480a8d25 --- /dev/null +++ b/ext/dl_test/dl_test.stub.php @@ -0,0 +1,7 @@ +fcc.function_handler->common.fn_flags & ZEND_ACC_CLOSURE) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(callback_data->fcc.function_handler)); } + for (int i = 0; i < callback_data->arg_count; ++i) { + if (callback_data->arg_types[i]->type == FFI_TYPE_STRUCT) { + efree(callback_data->arg_types[i]); + } + } + if (callback_data->ret_type->type == FFI_TYPE_STRUCT) { + efree(callback_data->ret_type); + } efree(callback_data); } /* }}} */ @@ -914,6 +922,8 @@ static void zend_ffi_callback_trampoline(ffi_cif* cif, void* ret, void** args, v if (ret_type->kind != ZEND_FFI_TYPE_VOID) { zend_ffi_zval_to_cdata(ret, ret_type, &retval); } + + zval_ptr_dtor(&retval); } /* }}} */ @@ -964,6 +974,11 @@ static void *zend_ffi_create_callback(zend_ffi_type *type, zval *value) /* {{{ * callback_data->arg_types[n] = zend_ffi_get_type(arg_type); if (!callback_data->arg_types[n]) { zend_ffi_pass_unsupported(arg_type); + for (int i = 0; i < n; ++i) { + if (callback_data->arg_types[i]->type == FFI_TYPE_STRUCT) { + efree(callback_data->arg_types[i]); + } + } efree(callback_data); ffi_closure_free(callback); return NULL; @@ -974,6 +989,11 @@ static void *zend_ffi_create_callback(zend_ffi_type *type, zval *value) /* {{{ * callback_data->ret_type = zend_ffi_get_type(ZEND_FFI_TYPE(type->func.ret_type)); if (!callback_data->ret_type) { zend_ffi_return_unsupported(type->func.ret_type); + for (int i = 0; i < callback_data->arg_count; ++i) { + if (callback_data->arg_types[i]->type == FFI_TYPE_STRUCT) { + efree(callback_data->arg_types[i]); + } + } efree(callback_data); ffi_closure_free(callback); return NULL; @@ -981,13 +1001,20 @@ static void *zend_ffi_create_callback(zend_ffi_type *type, zval *value) /* {{{ * if (ffi_prep_cif(&callback_data->cif, type->func.abi, callback_data->arg_count, callback_data->ret_type, callback_data->arg_types) != FFI_OK) { zend_throw_error(zend_ffi_exception_ce, "Cannot prepare callback CIF"); - efree(callback_data); - ffi_closure_free(callback); - return NULL; + goto free_on_failure; } if (ffi_prep_closure_loc(callback, &callback_data->cif, zend_ffi_callback_trampoline, callback_data, code) != FFI_OK) { zend_throw_error(zend_ffi_exception_ce, "Cannot prepare callback"); +free_on_failure: ; + for (int i = 0; i < callback_data->arg_count; ++i) { + if (callback_data->arg_types[i]->type == FFI_TYPE_STRUCT) { + efree(callback_data->arg_types[i]); + } + } + if (callback_data->ret_type->type == FFI_TYPE_STRUCT) { + efree(callback_data->ret_type); + } efree(callback_data); ffi_closure_free(callback); return NULL; diff --git a/ext/ffi/tests/gh7867.phpt b/ext/ffi/tests/gh7867.phpt index 7728d15b1c616..b85659aa70568 100644 --- a/ext/ffi/tests/gh7867.phpt +++ b/ext/ffi/tests/gh7867.phpt @@ -1,9 +1,9 @@ --TEST-- GH-7867 (FFI::cast() from pointer to array is broken) ---SKIPIF-- - +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 --FILE-- new("bar(*)(void)"); +FFI::addr($x)[0] = function() use ($ffi) { + $bar = $ffi->new("bar"); + $bar->a = 2; + return $bar; +}; +var_dump($x()); + +?> +--EXPECTF-- +object(FFI\CData:struct )#%d (1) { + ["a"]=> + int(2) +} diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index 90919e706e83e..9a0e21545756c 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -129,10 +129,7 @@ PHP_MINIT_FUNCTION(finfo) #ifdef MAGIC_RAW REGISTER_LONG_CONSTANT("FILEINFO_RAW", MAGIC_RAW, CONST_CS|CONST_PERSISTENT); #endif -#if 0 - /* seems not usable yet. */ REGISTER_LONG_CONSTANT("FILEINFO_APPLE", MAGIC_APPLE, CONST_CS|CONST_PERSISTENT); -#endif REGISTER_LONG_CONSTANT("FILEINFO_EXTENSION", MAGIC_EXTENSION, CONST_CS|CONST_PERSISTENT); return SUCCESS; diff --git a/ext/fileinfo/tests/finfo_apple_flag.phpt b/ext/fileinfo/tests/finfo_apple_flag.phpt new file mode 100644 index 0000000000000..7f037c149594b --- /dev/null +++ b/ext/fileinfo/tests/finfo_apple_flag.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test FILEINFO_APPLE flag +--EXTENSIONS-- +fileinfo +--FILE-- +file(__DIR__ . "/resources/test.jpg", FILEINFO_APPLE)); +var_dump($f->file(__DIR__ . "/resources/test.gif", FILEINFO_APPLE)); +var_dump($f->file(__DIR__ . "/resources/test.ppt", FILEINFO_APPLE)); + +?> +--EXPECT-- +string(8) "8BIMJPEG" +string(8) "8BIMGIFf" +string(8) "????PPT3" diff --git a/ext/gd/gd.stub.php b/ext/gd/gd.stub.php index 5b48af2376129..ec4a9ea3ae028 100644 --- a/ext/gd/gd.stub.php +++ b/ext/gd/gd.stub.php @@ -190,8 +190,7 @@ function imagecolorresolve(GdImage $image, int $red, int $green, int $blue): int function imagecolorexact(GdImage $image, int $red, int $green, int $blue): int {} -/** @return false|null */ -function imagecolorset(GdImage $image, int $color, int $red, int $green, int $blue, int $alpha = 0): ?bool {} +function imagecolorset(GdImage $image, int $color, int $red, int $green, int $blue, int $alpha = 0): false|null {} /** * @return array diff --git a/ext/gd/gd_arginfo.h b/ext/gd/gd_arginfo.h index 19b12eddb7897..b0f22ace5e679 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: 4de3d369fad259705acc5bf5de0e935b7e142ec7 */ + * Stub hash: a60454e502813da9aba42100fdbfd619c8da54d2 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -315,7 +315,7 @@ ZEND_END_ARG_INFO() #define arginfo_imagecolorexact arginfo_imagecolorclosest -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecolorset, 0, 5, _IS_BOOL, 1) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagecolorset, 0, 5, IS_FALSE, 1) ZEND_ARG_OBJ_INFO(0, image, GdImage, 0) ZEND_ARG_TYPE_INFO(0, color, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, red, IS_LONG, 0) diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 39de76a5e4243..f05e58aa1d953 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -311,7 +311,7 @@ static int php_iconv_output_handler(void **nothing, php_output_context *output_c mimetype = SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE; } - if (mimetype != NULL && (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN) || (output_context->op & PHP_OUTPUT_HANDLER_START))) { + if (mimetype != NULL && (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN) || ((output_context->op & PHP_OUTPUT_HANDLER_START) && !(output_context->op & PHP_OUTPUT_HANDLER_FINAL)))) { size_t len; char *p = strstr(get_output_encoding(), "//"); diff --git a/ext/imap/tests/imap_append_basic.phpt b/ext/imap/tests/imap_append_basic.phpt index 42764c181db38..3ed1229ca8eff 100644 --- a/ext/imap/tests/imap_append_basic.phpt +++ b/ext/imap/tests/imap_append_basic.phpt @@ -18,16 +18,16 @@ $imap_stream = setup_test_mailbox("imapappendbaisc", 0); $mb_details = imap_mailboxmsginfo($imap_stream); echo "Add a couple of msgs to the new mailbox\n"; var_dump(imap_append($imap_stream, $mb_details->Mailbox - , "From: webmaster@something.com\r\n" - . "To: info@something.com\r\n" + , "From: webmaster@example.com\r\n" + . "To: info@example.com\r\n" . "Subject: Test message\r\n" . "\r\n" . "this is a test message, please ignore\r\n" )); var_dump(imap_append($imap_stream, $mb_details->Mailbox - , "From: webmaster@something.com\r\n" - . "To: info@something.com\r\n" + , "From: webmaster@example.com\r\n" + . "To: info@example.com\r\n" . "Subject: Another test\r\n" . "\r\n" . "this is another test message, please ignore it too!!\r\n" @@ -58,7 +58,7 @@ Msg Count after append : 2 List the msg headers array(2) { [0]=> - string(%d) "%w%s 1)%s webmaster@something. Test message (%d chars)" + string(%d) "%w%s 1)%s webmaster@example.co Test message (%d chars)" [1]=> - string(%d) "%w%s 2)%s webmaster@something. Another test (%d chars)" + string(%d) "%w%s 2)%s webmaster@example.co Another test (%d chars)" } diff --git a/ext/imap/tests/setup/dovecotpass b/ext/imap/tests/setup/dovecotpass index 86a069fc4f699..f036e583007a4 100644 --- a/ext/imap/tests/setup/dovecotpass +++ b/ext/imap/tests/setup/dovecotpass @@ -1 +1 @@ -webmaster@something.com:{CRAM-MD5}be5f3177e9c7c06403272f25d983ba630df4ef40476b353bb3087a8401713451:vmail:vmail +webmaster@example.com:{CRAM-MD5}be5f3177e9c7c06403272f25d983ba630df4ef40476b353bb3087a8401713451:vmail:vmail diff --git a/ext/imap/tests/setup/imap_include.inc b/ext/imap/tests/setup/imap_include.inc index 0c07f9ae2d7d5..f6ee14db7c4b7 100644 --- a/ext/imap/tests/setup/imap_include.inc +++ b/ext/imap/tests/setup/imap_include.inc @@ -4,7 +4,7 @@ const IMAP_SERVER_NO_DEBUG = '{127.0.0.1:143/norsh}'; const IMAP_SERVER_DEBUG = '{127.0.0.1:143/debug/norsh}'; const IMAP_SERVER = IMAP_SERVER_DEBUG; const IMAP_DEFAULT_MAILBOX = IMAP_SERVER . 'INBOX'; -const IMAP_MAIL_DOMAIN = 'something.com'; +const IMAP_MAIL_DOMAIN = 'example.com'; const IMAP_ADMIN_USER = 'webmaster'; // a user with admin access const IMAP_MAILBOX_USERNAME = IMAP_ADMIN_USER . '@' . IMAP_MAIL_DOMAIN; const IMAP_MAILBOX_PASSWORD = 'p4ssw0rd'; diff --git a/ext/intl/msgformat/msgformat_helpers.cpp b/ext/intl/msgformat/msgformat_helpers.cpp index 5ca44b8ab346b..430d5a741115f 100644 --- a/ext/intl/msgformat/msgformat_helpers.cpp +++ b/ext/intl/msgformat/msgformat_helpers.cpp @@ -392,6 +392,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo, zend_ulong num_index; ZEND_HASH_FOREACH_KEY_VAL(args, num_index, str_index, elem) { + ZVAL_DEREF(elem); Formattable& formattable = fargs[argNum]; UnicodeString& key = farg_names[argNum]; Formattable::Type argType = Formattable::kObject, //unknown diff --git a/ext/intl/tests/dateformat_format.phpt b/ext/intl/tests/dateformat_format.phpt index a545d909b8f12..98b3d5bb078b5 100644 --- a/ext/intl/tests/dateformat_format.phpt +++ b/ext/intl/tests/dateformat_format.phpt @@ -318,7 +318,7 @@ Formatted localtime_array is : 12/17/95 12:13 AM IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1 Formatted localtime_array is : 18951217 12:13 AM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -326,7 +326,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Thursday, December 31, 2009 3:02:03 PM GMT-10:00 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -334,7 +334,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : December 31, 2009 3:02:03 PM GMT-10:00 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -342,7 +342,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Dec 31, 2009 3:02:03 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -350,7 +350,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 12/31/09 3:02 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -358,7 +358,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 20091231 03:02 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 2, 'timezone' => 'PDT', @@ -366,7 +366,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Saturday, December 30, 2000 5:04:05 PM GMT-10:00 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 2, 'timezone' => 'PDT', @@ -374,7 +374,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : December 30, 2000 5:04:05 PM GMT-10:00 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 2, 'timezone' => 'PDT', @@ -382,7 +382,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Dec 30, 2000 5:04:05 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 2, 'timezone' => 'PDT', @@ -390,7 +390,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 12/30/00 5:04 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 2, 'timezone' => 'PDT', diff --git a/ext/intl/tests/dateformat_format_variant2.phpt b/ext/intl/tests/dateformat_format_variant2.phpt index d70e2312564b9..6053ce07c8f72 100644 --- a/ext/intl/tests/dateformat_format_variant2.phpt +++ b/ext/intl/tests/dateformat_format_variant2.phpt @@ -318,7 +318,7 @@ Formatted localtime_array is : 12/17/95, 12:13 AM IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1 Formatted localtime_array is : 18951217 12:13 AM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -326,7 +326,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Thursday, December 31, 2009 at 3:02:03 PM GMT-10:00 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -334,7 +334,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : December 31, 2009 at 3:02:03 PM GMT-10 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -342,7 +342,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Dec 31, 2009, 3:02:03 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -350,7 +350,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 12/31/09, 3:02 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -358,7 +358,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 20091231 03:02 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 3, 'timezone' => 'America/Los_Angeles', @@ -366,7 +366,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Saturday, December 30, 2000 at 5:04:05 PM GMT-10:00 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 3, 'timezone' => 'America/Los_Angeles', @@ -374,7 +374,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : December 30, 2000 at 5:04:05 PM GMT-10 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 3, 'timezone' => 'America/Los_Angeles', @@ -382,7 +382,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Dec 30, 2000, 5:04:05 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 3, 'timezone' => 'America/Los_Angeles', @@ -390,7 +390,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 12/30/00, 5:04 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 3, 'timezone' => 'America/Los_Angeles', diff --git a/ext/intl/tests/dateformat_format_variant3.phpt b/ext/intl/tests/dateformat_format_variant3.phpt index c8601aadefd88..9d9fab6e92a45 100644 --- a/ext/intl/tests/dateformat_format_variant3.phpt +++ b/ext/intl/tests/dateformat_format_variant3.phpt @@ -318,7 +318,7 @@ Formatted localtime_array is : 12/17/95, 12:13 AM IntlDateFormatter locale= en_US ,datetype = -1 ,timetype =-1 Formatted localtime_array is : 18951217 12:13 AM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -326,7 +326,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Thursday, December 31, 2009 at 3:02:03 PM GMT-10:00 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -334,7 +334,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : December 31, 2009 at 3:02:03 PM GMT-10 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -342,7 +342,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Dec 31, 2009, 3:02:03 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -350,7 +350,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 12/31/09, 3:02 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2010-01-01 01:02:03.000000', 'timezone_type' => 3, 'timezone' => 'UTC', @@ -358,7 +358,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 20091231 03:02 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 2, 'timezone' => 'PDT', @@ -366,7 +366,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Saturday, December 30, 2000 at 5:04:05 PM GMT-10:00 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 2, 'timezone' => 'PDT', @@ -374,7 +374,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : December 30, 2000 at 5:04:05 PM GMT-10 ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 2, 'timezone' => 'PDT', @@ -382,7 +382,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : Dec 30, 2000, 5:04:05 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 2, 'timezone' => 'PDT', @@ -390,7 +390,7 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 12/30/00, 5:04 PM ------------ -Date is: DateTime::__set_state(array( +Date is: \DateTime::__set_state(array( 'date' => '2000-12-30 19:04:05.000000', 'timezone_type' => 2, 'timezone' => 'PDT', diff --git a/ext/intl/tests/gh8364.phpt b/ext/intl/tests/gh8364.phpt new file mode 100644 index 0000000000000..74a0b5629ec9c --- /dev/null +++ b/ext/intl/tests/gh8364.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug GH-8364 (msgfmt_format $values may not support references) +--SKIPIF-- + +--FILE-- +format($args); +var_dump($result); +var_dump(intl_get_error_code()); +?> +--EXPECT-- +string(16) "translate string" +int(0) diff --git a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c index 83d2158c37d10..3705259b452b9 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_utf8.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_utf8.c @@ -127,9 +127,7 @@ int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter) CK((*filter->output_function)(s, filter->data)); } else { CK(mbfl_filt_put_invalid_char(filter)); - if (c < 0x80 || (c >= 0xc2 && c <= 0xf4)) { - goto retry; - } + goto retry; } break; case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */ @@ -144,9 +142,7 @@ int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter) filter->status++; } else { CK(mbfl_filt_put_invalid_char(filter)); - if (c < 0x80 || (c >= 0xc2 && c <= 0xf4)) { - goto retry; - } + goto retry; } break; case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */ @@ -161,9 +157,7 @@ int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter) filter->status++; } else { CK(mbfl_filt_put_invalid_char(filter)); - if (c < 0x80 || (c >= 0xc2 && c <= 0xf4)) { - goto retry; - } + goto retry; } break; case 0x31: /* 4byte code 3rd char: 0x80-0xbf */ @@ -172,9 +166,7 @@ int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter) filter->status++; } else { CK(mbfl_filt_put_invalid_char(filter)); - if (c < 0x80 || (c >= 0xc2 && c <= 0xf4)) { - goto retry; - } + goto retry; } break; @@ -237,9 +229,7 @@ static size_t mb_utf8_to_wchar(unsigned char **in, size_t *in_len, uint32_t *buf unsigned char c2 = *p++; if ((c2 & 0xC0) != 0x80) { *out++ = MBFL_BAD_INPUT; - if (c2 < 0x80 || (c2 >= 0xC2 && c2 <= 0xF4)) { - p--; - } + p--; } else { *out++ = ((c & 0x1F) << 6) | (c2 & 0x3F); } @@ -252,34 +242,21 @@ static size_t mb_utf8_to_wchar(unsigned char **in, size_t *in_len, uint32_t *buf unsigned char c3 = *p++; if ((c2 & 0xC0) != 0x80 || !((c2 >= 0x80 && c2 <= 0xBF) && ((c == 0xE0 && c2 >= 0xA0) || (c == 0xED && c2 < 0xA0) || (c > 0xE0 && c != 0xED)))) { *out++ = MBFL_BAD_INPUT; - if (c2 < 0x80 || (c2 >= 0xC2 && c2 <= 0xF4)) { - p -= 2; - } else { - p--; - } + p -= 2; } else if ((c3 & 0xC0) != 0x80) { *out++ = MBFL_BAD_INPUT; - if (c3 < 0x80 || (c3 >= 0xC2 && c3 <= 0xF4)) { - p--; - } + p--; } else { uint32_t decoded = ((c & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F); - if (decoded >= 0xD800 && decoded <= 0xDFFF) { + if (decoded < 0x800 || (decoded >= 0xD800 && decoded <= 0xDFFF)) { *out++ = MBFL_BAD_INPUT; } else { - *out++ = (decoded < 0x800) ? MBFL_BAD_INPUT : decoded; + *out++ = decoded; } } } else { *out++ = MBFL_BAD_INPUT; - /* Skip over some number of bytes to duplicate error-handling behavior of old implementation */ - while (p < e) { - c = *p; - if ((c & 0xC0) != 0x80) { - if (c >= 0x80 && (c < 0xC2 || c > 0xF4)) - p++; - break; - } + while (p < e && (*p & 0xC0) == 0x80) { p++; } } @@ -288,51 +265,28 @@ static size_t mb_utf8_to_wchar(unsigned char **in, size_t *in_len, uint32_t *buf unsigned char c2 = *p++; unsigned char c3 = *p++; unsigned char c4 = *p++; - if ((c2 & 0xC0) != 0x80) { + /* If c == 0xF0 and c2 < 0x90, then this is an over-long code unit; it could have + * fit in 3 bytes only. If c == 0xF4 and c2 >= 0x90, then this codepoint is + * greater than U+10FFFF, which is the highest legal codepoint */ + if ((c2 & 0xC0) != 0x80 || (c == 0xF0 && c2 < 0x90) || (c == 0xF4 && c2 >= 0x90)) { *out++ = MBFL_BAD_INPUT; - if (c2 < 0x80 || (c2 >= 0xC2 && c2 <= 0xF4)) { - p -= 3; - } else { - p -= 2; - } - } else if ((c3 & 0xC0) != 0x80 || !((c == 0xF0 && c2 >= 0x90) || (c == 0xF4 && c2 < 0x90) || (c > 0xF0 && c < 0xF4))) { + p -= 3; + } else if ((c3 & 0xC0) != 0x80) { *out++ = MBFL_BAD_INPUT; - if (!((c == 0xF0 && c2 >= 0x90) || (c == 0xF4 && c2 < 0x90) || (c > 0xF0 && c < 0xF4))) { - if (c2 >= 0x80 && (c2 < 0xC2 || c2 > 0xF4)) { - p -= 2; - } else { - p -= 3; - } - } else if (c3 < 0x80 || (c3 >= 0xC2 && c3 <= 0xF4)) { - p -= 2; - } else { - p--; - } + p -= 2; } else if ((c4 & 0xC0) != 0x80) { *out++ = MBFL_BAD_INPUT; - if (c4 < 0x80 || (c4 >= 0xC2 && c4 <= 0xF4)) { - p--; - } + p--; } else { uint32_t decoded = ((c & 0x7) << 18) | ((c2 & 0x3F) << 12) | ((c3 & 0x3F) << 6) | (c4 & 0x3F); *out++ = (decoded < 0x10000) ? MBFL_BAD_INPUT : decoded; } } else { *out++ = MBFL_BAD_INPUT; - /* Skip over some number of bytes to duplicate error-handling behavior of old implementation */ if (p < e) { unsigned char c2 = *p; - if (!((c == 0xF0 && c2 >= 0x90) || (c == 0xF4 && c2 < 0x90) || (c > 0xF0 && c < 0xF4))) { - if (c2 >= 0x80 && (c2 < 0xC2 || c2 > 0xF4)) - p++; - } else { - while (p < e) { - c = *p; - if ((c & 0xC0) != 0x80) { - if (c >= 0x80 && (c < 0xC2 || c > 0xF4)) - p++; - break; - } + if ((c == 0xF0 && c2 >= 0x90) || (c == 0xF4 && c2 < 0x90) || c == 0xF2 || c == 0xF3) { + while (p < e && (*p & 0xC0) == 0x80) { p++; } } diff --git a/ext/mbstring/tests/illformed_utf_sequences.phpt b/ext/mbstring/tests/illformed_utf_sequences.phpt index b29827be44d6f..6eddaf341e097 100644 --- a/ext/mbstring/tests/illformed_utf_sequences.phpt +++ b/ext/mbstring/tests/illformed_utf_sequences.phpt @@ -21,28 +21,28 @@ var_dump(chk_enc("\x31\x32\x33", 0)); var_dump(chk_enc("\x41\x42\x43", 0)); var_dump(chk_enc("\xc0\xb1\xc0\xb2\xc0\xb3", 6)); var_dump(chk_enc("\xc1\x81\xc1\x82\xc1\x83", 6)); -var_dump(chk_enc("\xe0\x80\xb1\xe0\x80\xb2\xe0\x80\xb3", 6)); -var_dump(chk_enc("\xe0\x81\x81\xe0\x81\x82\xe0\x81\x83", 6)); -var_dump(chk_enc("\xf0\x80\x80\xb1\xf0\x80\x80\xb2\xf0\x80\x80\xb3", 9)); -var_dump(chk_enc("\xf0\x80\x81\x81\xf0\x80\x81\x82\xf0\x81\x83", 8)); +var_dump(chk_enc("\xe0\x80\xb1\xe0\x80\xb2\xe0\x80\xb3", 9)); +var_dump(chk_enc("\xe0\x81\x81\xe0\x81\x82\xe0\x81\x83", 9)); +var_dump(chk_enc("\xf0\x80\x80\xb1\xf0\x80\x80\xb2\xf0\x80\x80\xb3", 12)); +var_dump(chk_enc("\xf0\x80\x81\x81\xf0\x80\x81\x82\xf0\x81\x83", 11)); var_dump(chk_enc("\xf8\x80\x80\x80\xb1\xf8\x80\x80\x80\xb2\xf8\x80\x80\x80\xb3", 15)); var_dump(chk_enc("\xf8\x80\x80\x81\x81\xf8\x80\x80\x81\x82\xf8\x80\x80\x81\x83", 15)); var_dump(chk_enc("\xfc\x80\x80\x80\x80\xb1\xfc\x80\x80\x80\x80\xb2\xfc\x80\x80\x80\x80\xb3", 18)); var_dump(chk_enc("\xfc\x80\x80\x80\x81\x81\xfc\x80\x80\x80\x81\x82\xfc\x80\x80\x80\x81\x83", 18)); var_dump(chk_enc("\xc2\xa2\xc2\xa3\xc2\xa5", 0)); -var_dump(chk_enc("\xe0\x82\xa2\xe0\x82\xa3\xe0\x82\xa5", 6)); -var_dump(chk_enc("\xf0\x80\x82\xa2\xf0\x80\x82\xa3\xf0\x80\x82\xa5", 9)); +var_dump(chk_enc("\xe0\x82\xa2\xe0\x82\xa3\xe0\x82\xa5", 9)); +var_dump(chk_enc("\xf0\x80\x82\xa2\xf0\x80\x82\xa3\xf0\x80\x82\xa5", 12)); var_dump(chk_enc("\xf8\x80\x80\x82\xa2\xf8\x80\x80\x82\xa3\xf8\x80\x80\x82\xa5", 15)); var_dump(chk_enc("\xfc\x80\x80\x80\x82\xa2\xfc\x80\x80\x80\x82\xa3\xfc\x80\x80\x80\x82\xa5", 18)); var_dump(chk_enc("\xc1\xbf", 2)); var_dump(chk_enc("\xc2\x80", 0)); var_dump(chk_enc("\xdf\xbf", 0)); -var_dump(chk_enc("\xe0\x9f\xff", 2)); +var_dump(chk_enc("\xe0\x9f\xff", 3)); var_dump(chk_enc("\xe0\xa0\x80", 2)); var_dump(chk_enc("\xef\xbf\xbf", 0)); -var_dump(chk_enc("\xf0\x8f\xbf\xbf", 3)); +var_dump(chk_enc("\xf0\x8f\xbf\xbf", 4)); var_dump(chk_enc("\xf0\x90\x80\x80", 0)); var_dump(chk_enc("\xf7\xbf\xbf\xbf", 4)); var_dump(chk_enc("\xf8\x87\xbf\xbf\xbf", 5)); @@ -57,7 +57,7 @@ echo "UTF-8 and surrogates area\n"; $out = ''; $cnt = 0; for ($i = 0xd7ff; $i <= 0xe000; ++$i) { - $s = chk_enc(pack('C3', 0xe0 | ($i >> 12), 0x80 | ($i >> 6) & 0x3f, 0x80 | $i & 0x3f), 2); + $s = chk_enc(pack('C3', 0xe0 | ($i >> 12), 0x80 | ($i >> 6) & 0x3f, 0x80 | $i & 0x3f), 3); if ($s === false) { $cnt++; } else { diff --git a/ext/mbstring/tests/mb_ereg_search_syntax.phpt b/ext/mbstring/tests/mb_ereg_search_syntax.phpt index 4e28ebfb8f742..5e16a91c36956 100644 --- a/ext/mbstring/tests/mb_ereg_search_syntax.phpt +++ b/ext/mbstring/tests/mb_ereg_search_syntax.phpt @@ -4,7 +4,7 @@ Specifying non-default syntax in mb_ereg_search() mbstring --SKIPIF-- --FILE-- +--EXPECT-- +All done! diff --git a/ext/mbstring/tests/utf_encodings.phpt b/ext/mbstring/tests/utf_encodings.phpt index 038a770330006..37fd7f32426c0 100644 --- a/ext/mbstring/tests/utf_encodings.phpt +++ b/ext/mbstring/tests/utf_encodings.phpt @@ -761,14 +761,14 @@ testValidString('', '', 'UTF-8', 'UTF-32BE'); $invalid = array( // Codepoints outside of valid 0-0x10FFFF range for Unicode - "\xF4\x90\x80\x80" => str_repeat("\x00\x00\x00%", 3), // CP 0x110000 + "\xF4\x90\x80\x80" => str_repeat("\x00\x00\x00%", 4), // CP 0x110000 "\xF7\x80\x80\x80" => str_repeat("\x00\x00\x00%", 4), // CP 0x1C0000 "\xF7\xBF\xBF\xBF" => str_repeat("\x00\x00\x00%", 4), // CP 0x1FFFFF // Reserved range for UTF-16 surrogate pairs - "\xED\xA0\x80" => str_repeat("\x00\x00\x00%", 2), // CP 0xD800 - "\xED\xAF\xBF" => str_repeat("\x00\x00\x00%", 2), // CP 0xDBFF - "\xED\xBF\xBF" => str_repeat("\x00\x00\x00%", 2), // CP 0xDFFF + "\xED\xA0\x80" => str_repeat("\x00\x00\x00%", 3), // CP 0xD800 + "\xED\xAF\xBF" => str_repeat("\x00\x00\x00%", 3), // CP 0xDBFF + "\xED\xBF\xBF" => str_repeat("\x00\x00\x00%", 3), // CP 0xDFFF // Truncated characters "\xDF" => "\x00\x00\x00%", // should have been 2-byte @@ -788,8 +788,8 @@ $invalid = array( // Multi-byte characters which end too soon and go to a junk byte // (Which isn't even valid to start a new character) - "\xF0\xBF\xBF\xFF" => "\x00\x00\x00%", - "\xF0\xBF\xFF" => "\x00\x00\x00%", + "\xF0\xBF\xBF\xFF" => str_repeat("\x00\x00\x00%", 2), + "\xF0\xBF\xFF" => str_repeat("\x00\x00\x00%", 2), // Continuation bytes which appear outside of a MB char "\x80" => "\x00\x00\x00%", @@ -799,8 +799,8 @@ $invalid = array( // Overlong code units // (Using more bytes than needed to encode a character) "\xC1\xBF" => str_repeat("\x00\x00\x00%", 2), // didn't need 2 bytes - "\xE0\x9F\xBF" => str_repeat("\x00\x00\x00%", 2), // didn't need 3 bytes - "\xF0\x8F\xBF\xBF" => str_repeat("\x00\x00\x00%", 3) // didn't need 4 bytes + "\xE0\x9F\xBF" => str_repeat("\x00\x00\x00%", 3), // didn't need 3 bytes + "\xF0\x8F\xBF\xBF" => str_repeat("\x00\x00\x00%", 4) // didn't need 4 bytes ); testInvalidCodepoints($invalid, 'UTF-8'); diff --git a/ext/mysqli/tests/mysqli_character_set.phpt b/ext/mysqli/tests/mysqli_character_set.phpt index 3398af2b2f29e..8e9e943528d5d 100644 --- a/ext/mysqli/tests/mysqli_character_set.phpt +++ b/ext/mysqli/tests/mysqli_character_set.phpt @@ -45,7 +45,8 @@ if (!function_exists('mysqli_set_charset')) { /* The server currently 17.07.2007 can't handle data sent in ucs2 */ /* The server currently 16.08.2010 can't handle data sent in utf16 and utf32 */ /* The server currently 02.09.2011 can't handle data sent in utf16le */ - if ($charset['Charset'] == 'ucs2' || $charset['Charset'] == 'utf16' || $charset['Charset'] == 'utf32' || 'utf16le' == $charset['Charset']) { + /* As of MySQL 8.0.28, `SHOW CHARACTER SET` contains utf8mb3, but that is not yet supported by mysqlnd */ + if ($charset['Charset'] == 'ucs2' || $charset['Charset'] == 'utf16' || $charset['Charset'] == 'utf32' || 'utf16le' == $charset['Charset'] || 'utf8mb3' == $charset['Charset']) { continue; } diff --git a/ext/mysqli/tests/mysqli_options.phpt b/ext/mysqli/tests/mysqli_options.phpt index 613a19cef7f9d..522f60889a6bd 100644 --- a/ext/mysqli/tests/mysqli_options.phpt +++ b/ext/mysqli/tests/mysqli_options.phpt @@ -58,7 +58,8 @@ mysqli_close($link2); foreach ($charsets as $charset) { /* The server currently 17.07.2007 can't handle data sent in ucs2 */ /* The server currently 16.08.2010 can't handle data sent in utf16 and utf32 */ - if ($charset['Charset'] == 'ucs2' || $charset['Charset'] == 'utf16' || $charset['Charset'] == 'utf32') { + /* As of MySQL 8.0.28, `SHOW CHARACTER SET` contains utf8mb3, but that is not yet supported by mysqlnd */ + if ($charset['Charset'] == 'ucs2' || $charset['Charset'] == 'utf16' || $charset['Charset'] == 'utf32' || $charset['Charset'] == 'utf8mb3') { continue; } if (true !== mysqli_options($link, MYSQLI_SET_CHARSET_NAME, $charset['Charset'])) { diff --git a/ext/mysqli/tests/mysqli_set_charset.phpt b/ext/mysqli/tests/mysqli_set_charset.phpt index 5ddc2f4aa8930..50da0c217e347 100644 --- a/ext/mysqli/tests/mysqli_set_charset.phpt +++ b/ext/mysqli/tests/mysqli_set_charset.phpt @@ -82,7 +82,8 @@ if ((($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "latin1"', MYSQLI_STOR printf("[016] Cannot get list of character sets\n"); while ($tmp = mysqli_fetch_assoc($res)) { - if ('ucs2' == $tmp['Charset'] || 'utf16' == $tmp['Charset'] || 'utf32' == $tmp['Charset'] || 'utf16le' == $tmp['Charset']) + /* As of MySQL 8.0.28, `SHOW CHARACTER SET` contains utf8mb3, but that is not yet supported by mysqlnd */ + if ('ucs2' == $tmp['Charset'] || 'utf16' == $tmp['Charset'] || 'utf32' == $tmp['Charset'] || 'utf16le' == $tmp['Charset'] || 'utf8mb3' == $tmp['Charset']) continue; /* Uncomment to see where it hangs - var_dump($tmp); flush(); */ diff --git a/ext/oci8/tests/lob_prefetch.phpt b/ext/oci8/tests/lob_prefetch.phpt index 94a85585a8e8a..909e20b38605d 100755 --- a/ext/oci8/tests/lob_prefetch.phpt +++ b/ext/oci8/tests/lob_prefetch.phpt @@ -35,7 +35,7 @@ $ora_sql = end loop; dbms_lob.createtemporary(b, false); dbms_lob.converttoblob(b, c, dbms_lob.lobmaxsize, dest_offset, src_offset, dbms_lob.default_csid, ctx, warn); - insert /*+ APPEND */ into ${schema}${table_name} (id, clob, blob) values (j, c, b); + insert /*+ APPEND */ into {$schema}{$table_name} (id, clob, blob) values (j, c, b); end loop; commit; end;"; @@ -119,7 +119,7 @@ try { print("Test 3 - CLOB prefetch_lob_size 100000\n"); -$sql = "select clob from ${schema}${table_name}" . " order by id"; +$sql = "select clob from {$schema}{$table_name}" . " order by id"; $locarr = get_clob_loc($c, $sql, 100000); $inlinearr = get_clob_inline($c, $sql, 100000); @@ -138,7 +138,7 @@ check_clobs($locarr, $inlinearr); print("Test 4 - BLOB prefetch_lob_size 100000\n"); -$sql = "select blob from ${schema}${table_name}" . " order by id"; +$sql = "select blob from {$schema}{$table_name}" . " order by id"; $locarr = get_blob_loc($c, $sql, 100000); print(count($locarr) . "\n"); diff --git a/ext/oci8/tests/lob_prefetch_ini.phpt b/ext/oci8/tests/lob_prefetch_ini.phpt index 2142a8e0ece01..b37217d034469 100755 --- a/ext/oci8/tests/lob_prefetch_ini.phpt +++ b/ext/oci8/tests/lob_prefetch_ini.phpt @@ -37,7 +37,7 @@ $ora_sql = end loop; dbms_lob.createtemporary(b, false); dbms_lob.converttoblob(b, c, dbms_lob.lobmaxsize, dest_offset, src_offset, dbms_lob.default_csid, ctx, warn); - insert /*+ APPEND */ into ${schema}${table_name} (id, clob, blob) values (j, c, b); + insert /*+ APPEND */ into {$schema}{$table_name} (id, clob, blob) values (j, c, b); end loop; commit; end;"; @@ -108,7 +108,7 @@ var_dump($r); print("Test 2 - CLOB with current oci8.prefetch_lob_size\n"); -$sql = "select clob from ${schema}${table_name}" . " order by id"; +$sql = "select clob from {$schema}{$table_name}" . " order by id"; $locarr = get_clob_loc($c, $sql, -1); $inlinearr = get_clob_inline($c, $sql, -1); @@ -136,7 +136,7 @@ check_clobs($locarr, $inlinearr); print("Test 5 - BLOB with current ocig8.prefetch_lob_size \n"); -$sql = "select blob from ${schema}${table_name}" . " order by id"; +$sql = "select blob from {$schema}{$table_name}" . " order by id"; $locarr = get_blob_loc($c, $sql, -1); print(count($locarr) . "\n"); diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index af040eba9ca93..8ed0caae85ee7 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -994,7 +994,7 @@ static accel_time_t zend_get_file_handle_timestamp_win(zend_file_handle *file_ha accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size) { - zend_stat_t statbuf; + zend_stat_t statbuf = {0}; #ifdef ZEND_WIN32 accel_time_t res; #endif @@ -3409,7 +3409,7 @@ void zend_accel_schedule_restart(zend_accel_restart_reason reason) HANDLE_UNBLOCK_INTERRUPTIONS(); } -static void accel_deactivate_now() +static void accel_deactivate_now(void) { /* this is needed because on WIN32 lock is not decreased unless ZCG(counted) is set */ #ifdef ZEND_WIN32 @@ -3713,19 +3713,6 @@ static zend_result preload_resolve_deps(preload_error *error, const zend_class_e return SUCCESS; } -static zend_result preload_update_constant(zval *val, zend_class_entry *scope) -{ - zval tmp; - ZVAL_COPY(&tmp, val); - if (zval_update_constant_ex(&tmp, scope) == FAILURE || Z_TYPE(tmp) == IS_OBJECT) { - zval_ptr_dtor(&tmp); - return FAILURE; - } - zval_ptr_dtor_nogc(val); - ZVAL_COPY_VALUE(val, &tmp); - return SUCCESS; -} - static bool preload_try_resolve_constants(zend_class_entry *ce) { bool ok, changed, was_changed = false; @@ -3739,7 +3726,7 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) ZEND_HASH_MAP_FOREACH_PTR(&ce->constants_table, c) { val = &c->value; if (Z_TYPE_P(val) == IS_CONSTANT_AST) { - if (EXPECTED(preload_update_constant(val, c->ce) == SUCCESS)) { + if (EXPECTED(zval_update_constant_ex(val, c->ce) == SUCCESS)) { was_changed = changed = true; } else { ok = false; @@ -3757,7 +3744,7 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) val = &ce->default_properties_table[i]; if (Z_TYPE_P(val) == IS_CONSTANT_AST) { zend_property_info *prop = ce->properties_info_table[i]; - if (UNEXPECTED(preload_update_constant(val, prop->ce) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(val, prop->ce) != SUCCESS)) { resolved = ok = false; } } @@ -3773,7 +3760,7 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) val = ce->default_static_members_table + ce->default_static_members_count - 1; while (count) { if (Z_TYPE_P(val) == IS_CONSTANT_AST) { - if (UNEXPECTED(preload_update_constant(val, ce) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) { resolved = ok = false; } } diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 3100153f3fb99..3f2ec70546968 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -4565,7 +4565,10 @@ static int zend_jit_math_helper(dasm_State **Dst, | FREE_OP op1_type, op1, op1_info, 0, NULL, ZREG_TMP1, ZREG_TMP2 | FREE_OP op2_type, op2, op2_info, 0, NULL, ZREG_TMP1, ZREG_TMP2 if (may_throw) { - if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RX) { + if (opline->opcode == ZEND_ASSIGN_DIM_OP && (opline->op2_type & (IS_VAR|IS_TMP_VAR))) { + | MEM_LOAD_64_ZTS ldr, TMP2, executor_globals, exception, TMP1 + | cbnz TMP2, ->exception_handler_free_op2 + } else if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RX) { zend_jit_check_exception_undef_result(Dst, opline); } else { zend_jit_check_exception(Dst); @@ -8706,7 +8709,8 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t | // Get the return value of function zend_jit_find_func_helper/zend_jit_find_ns_func_helper | mov REG0, RETVALx if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) { - int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); + int32_t exit_point = zend_jit_trace_get_exit_point(opline, + func && (func->common.fn_flags & ZEND_ACC_IMMUTABLE) ? ZEND_JIT_EXIT_INVALIDATE : 0); const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!exit_addr) { diff --git a/ext/opcache/jit/zend_jit_internal.h b/ext/opcache/jit/zend_jit_internal.h index 1b6f88ead0197..79c44d4d59122 100644 --- a/ext/opcache/jit/zend_jit_internal.h +++ b/ext/opcache/jit/zend_jit_internal.h @@ -412,6 +412,7 @@ typedef enum _zend_jit_trace_stop { #define ZEND_JIT_EXIT_PACKED_GUARD (1<<7) #define ZEND_JIT_EXIT_CLOSURE_CALL (1<<8) /* exit because of polymorphic INIT_DYNAMIC_CALL call */ #define ZEND_JIT_EXIT_METHOD_CALL (1<<9) /* exit because of polymorphic INIT_METHOD_CALL call */ +#define ZEND_JIT_EXIT_INVALIDATE (1<<10) /* invalidate current trace */ typedef union _zend_op_trace_info { zend_op dummy; /* the size of this structure must be the same as zend_op */ @@ -562,6 +563,9 @@ typedef union _zend_jit_trace_stack { (_stack)[_slot].reg = _reg; \ (_stack)[_slot].flags = _flags; \ } while (0) +#define RESET_STACK_MEM_TYPE(_stack, _slot) do { \ + (_stack)[_slot].mem_type = IS_UNKNOWN; \ + } while (0) /* trace info flags */ #define ZEND_JIT_TRACE_CHECK_INTERRUPT (1<<0) @@ -581,6 +585,7 @@ typedef struct _zend_jit_trace_info { uint32_t flags; /* See ZEND_JIT_TRACE_... defines above */ uint32_t polymorphism; /* Counter of polymorphic calls */ uint32_t jmp_table_size;/* number of jmp_table slots */ + const zend_op_array *op_array; /* function */ const zend_op *opline; /* first opline */ const void *code_start; /* address of native code */ zend_jit_trace_exit_info *exit_info; /* info about side exits */ diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index ad19722dead4f..b45846896afcc 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -365,6 +365,26 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op return 0; } +static bool zend_jit_may_be_modified(const zend_function *func, const zend_op_array *called_from) +{ + if (func->type == ZEND_INTERNAL_FUNCTION) { +#ifdef _WIN32 + /* ASLR */ + return 1; +#else + return 0; +#endif + } else if (func->type == ZEND_USER_FUNCTION) { + if (func->common.fn_flags & ZEND_ACC_PRELOADED) { + return 0; + } + if (func->op_array.filename == called_from->filename && !func->op_array.scope) { + return 0; + } + } + return 1; +} + static zend_always_inline uint32_t zend_jit_trace_type_to_info_ex(zend_uchar type, uint32_t info) { if (type == IS_UNKNOWN) { @@ -2038,7 +2058,9 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') { break; } - ADD_OP1_TRACE_GUARD(); + if (opline->op1_type != IS_UNUSED && op1_type == IS_OBJECT) { + ADD_OP1_TRACE_GUARD(); + } break; case ZEND_INIT_METHOD_CALL: if (opline->op2_type != IS_CONST @@ -6083,10 +6105,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par if (!zend_jit_trace_handler(&dasm_state, op_array, opline, zend_may_throw(opline, ssa_op, op_array, ssa), p + 1)) { goto jit_failure; } - if ((opline->opcode != ZEND_INIT_STATIC_METHOD_CALL + if ((p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func + && (opline->opcode != ZEND_INIT_STATIC_METHOD_CALL || opline->op1_type != IS_CONST - || opline->op2_type != IS_CONST) - && (p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func) { + || opline->op2_type != IS_CONST + || zend_jit_may_be_modified((p+1)->func, op_array))) { if (!zend_jit_init_fcall_guard(&dasm_state, 0, (p+1)->func, opline+1)) { goto jit_failure; } @@ -6096,8 +6119,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par if (!zend_jit_trace_handler(&dasm_state, op_array, opline, zend_may_throw(opline, ssa_op, op_array, ssa), p + 1)) { goto jit_failure; } - if (opline->op2_type != IS_CONST - && (p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func) { + if ((p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func + && (opline->op2_type != IS_CONST + || zend_jit_may_be_modified((p+1)->func, op_array))) { if (!zend_jit_init_fcall_guard(&dasm_state, 0, (p+1)->func, opline+1)) { goto jit_failure; } @@ -6107,8 +6131,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par if (!zend_jit_trace_handler(&dasm_state, op_array, opline, zend_may_throw(opline, ssa_op, op_array, ssa), p + 1)) { goto jit_failure; } - if (opline->op1_type != IS_CONST - && (p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func) { + if ((p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func + && (opline->op1_type != IS_CONST + || zend_jit_may_be_modified((p+1)->func, op_array))) { SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_OBJECT, 1); if (!zend_jit_init_fcall_guard(&dasm_state, 0, (p+1)->func, opline+1)) { goto jit_failure; @@ -6229,6 +6254,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } else { SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), type, (type == IS_UNKNOWN || !ra || !ra[ssa_op->result_def])); + if (ssa->var_info[ssa_op->result_def].type & MAY_BE_INDIRECT) { + RESET_STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var)); + } if (type != IS_UNKNOWN) { ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD; if (opline->opcode == ZEND_FETCH_THIS @@ -6684,8 +6712,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par call_info = call_info->next_callee; } if (!skip_guard - && !zend_jit_may_be_polymorphic_call(init_opline)) { - // TODO: recompilation may change target ??? + && !zend_jit_may_be_polymorphic_call(init_opline) + && !zend_jit_may_be_modified(p->func, op_array)) { skip_guard = 1; } } @@ -7018,6 +7046,7 @@ static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace t->flags = 0; t->polymorphism = 0; t->jmp_table_size = 0; + t->op_array = trace_buffer[0].op_array; t->opline = trace_buffer[1].opline; t->exit_info = exit_info; t->stack_map = NULL; @@ -8046,6 +8075,35 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf EX(opline)->lineno); } + if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_INVALIDATE) { + zend_jit_op_array_trace_extension *jit_extension; + uint32_t num = trace_num; + + while (t->root != num) { + num = t->root; + t = &zend_jit_traces[num]; + } + + SHM_UNPROTECT(); + zend_jit_unprotect(); + + jit_extension = (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(t->op_array); + 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; + } 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; + } 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_TRACE_INFO(t->opline, jit_extension->offset)->trace_flags &= + ZEND_JIT_TRACE_START_LOOP|ZEND_JIT_TRACE_START_ENTER|ZEND_JIT_TRACE_START_RETURN; + + zend_jit_protect(); + SHM_PROTECT(); + + return 0; + } + if (t->exit_info[exit_num].flags & ZEND_JIT_EXIT_TO_VM) { if (zend_jit_trace_exit_is_bad(trace_num, exit_num)) { zend_jit_blacklist_trace_exit(trace_num, exit_num); diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index d8fdc49db63d4..6bb65422e3d03 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -4986,7 +4986,10 @@ static int zend_jit_math_helper(dasm_State **Dst, | FREE_OP op1_type, op1, op1_info, 0, NULL | FREE_OP op2_type, op2, op2_info, 0, NULL if (may_throw) { - if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RX) { + if (opline->opcode == ZEND_ASSIGN_DIM_OP && (opline->op2_type & (IS_VAR|IS_TMP_VAR))) { + | MEM_CMP_ZTS aword, executor_globals, exception, 0, r0 + | jne ->exception_handler_free_op2 + } else if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RX) { zend_jit_check_exception_undef_result(Dst, opline); } else { zend_jit_check_exception(Dst); @@ -9316,13 +9319,13 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t ZEND_UNREACHABLE(); } if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) { - int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0); + int32_t exit_point = zend_jit_trace_get_exit_point(opline, + func && (func->common.fn_flags & ZEND_ACC_IMMUTABLE) ? ZEND_JIT_EXIT_INVALIDATE : 0); const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point); if (!exit_addr) { return 0; } - if (!func || opline->opcode == ZEND_INIT_FCALL) { | test r0, r0 | jnz >3 diff --git a/ext/opcache/tests/gh8063-001.phpt b/ext/opcache/tests/gh8063-001.phpt new file mode 100644 index 0000000000000..320d40aa3a8c0 --- /dev/null +++ b/ext/opcache/tests/gh8063-001.phpt @@ -0,0 +1,31 @@ +--TEST-- +Bug GH-8063 (Opcache breaks autoloading after E_COMPILE_ERROR) 001 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.record_warnings=0 +--EXTENSIONS-- +opcache +--FILE-- + +--FILE-- + +--EXPECT-- +array(2) { + [0]=> + enum(Foo::Bar) + [1]=> + enum(Foo::Baz) +} +array(2) { + [0]=> + enum(Foo::Bar) + [1]=> + enum(Foo::Baz) +} diff --git a/ext/opcache/tests/gh8466.phpt b/ext/opcache/tests/gh8466.phpt new file mode 100644 index 0000000000000..a85a39f549977 --- /dev/null +++ b/ext/opcache/tests/gh8466.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug GH-8466: ini_get() is optimized out when the option does not exist during compilation +--SKIPIF-- + +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/jit/fetch_obj_010.phpt b/ext/opcache/tests/jit/fetch_obj_010.phpt new file mode 100644 index 0000000000000..2755590f11077 --- /dev/null +++ b/ext/opcache/tests/jit/fetch_obj_010.phpt @@ -0,0 +1,19 @@ +--TEST-- +JIT: FETCH_OBJ 010 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +ary["bas"] ??= $obj = new stdClass; + } +} +foo(); +?> +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/jit/gh8461-001.inc b/ext/opcache/tests/jit/gh8461-001.inc new file mode 100644 index 0000000000000..0d37455f96880 --- /dev/null +++ b/ext/opcache/tests/jit/gh8461-001.inc @@ -0,0 +1,14 @@ +foo = self::A + $b; + } +} diff --git a/ext/opcache/tests/jit/gh8461-003.phpt b/ext/opcache/tests/jit/gh8461-003.phpt new file mode 100644 index 0000000000000..c2e8b07a67c14 --- /dev/null +++ b/ext/opcache/tests/jit/gh8461-003.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug GH-8461 003 (JIT does not account for class re-compile) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit_buffer_size=1M +opcache.jit=1255 +opcache.file_update_protection=0 +opcache.revalidate_freq=0 +opcache.protect_memory=1 +--FILE-- +foo = self::A + $b; + } +} diff --git a/ext/opcache/tests/jit/gh8461-004.phpt b/ext/opcache/tests/jit/gh8461-004.phpt new file mode 100644 index 0000000000000..d673cd1c68f0d --- /dev/null +++ b/ext/opcache/tests/jit/gh8461-004.phpt @@ -0,0 +1,60 @@ +--TEST-- +Bug GH-8461 004 (JIT does not account for class re-compile) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit_buffer_size=1M +opcache.jit=1255 +opcache.file_update_protection=0 +opcache.revalidate_freq=0 +opcache.protect_memory=1 +--FILE-- +foo = self::A + $b; + } + } +} + +class UniqueListLast extends UniqueList +{ + public function __construct() + { + parent::__construct(self::B); + } +} + +for ($i = 0; $i < 10; $i++) { + new UniqueListLast(); +} + +var_dump($initialRequest ? $x : $y); +print "OK"; +--EXPECT-- +int(10) +OK diff --git a/ext/opcache/tests/jit/gh8461-005.inc b/ext/opcache/tests/jit/gh8461-005.inc new file mode 100644 index 0000000000000..e4837fd1e153f --- /dev/null +++ b/ext/opcache/tests/jit/gh8461-005.inc @@ -0,0 +1,8 @@ +foo = self::A + $b; + } + + public static function foo() + { + global $x; + $x += self::A; + } +} + +class UniqueListLast extends UniqueList +{ + public function __construct() + { + parent::__construct(self::B); + } + + public static function bar() { + parent::foo(); + } +} + +function test() { + global $x; + $x += 1; +} diff --git a/ext/opcache/tests/jit/gh8461-007.phpt b/ext/opcache/tests/jit/gh8461-007.phpt new file mode 100644 index 0000000000000..03e0c5876030b --- /dev/null +++ b/ext/opcache/tests/jit/gh8461-007.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug GH-8461 007 (JIT does not account for function re-compile) +--EXTENSIONS-- +opcache +--SKIPIF-- + +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit_buffer_size=1M +opcache.jit=1255 +opcache.file_update_protection=0 +opcache.revalidate_freq=0 +opcache.protect_memory=1 +opcache.preload={PWD}/gh8461-007.inc +--FILE-- +foo = self::A + $b; + } + + public static function foo() + { + global $x; + $x += self::A; + } +} + +class UniqueListLast extends UniqueList +{ + public function __construct() + { + parent::__construct(self::B); + } + + public static function bar() { + parent::foo(); + } +} + +function test() { + global $x; + $x += 1; +} + +for ($i = 0; $i < 100; $i++) { + UniqueListLast::bar(); +} + +for ($i = 0; $i < 100; $i++) { + new UniqueListLast(); +} + +for ($i = 0; $i < 10; $i++) { + test(); +} + +print "OK"; +--EXPECT-- +OK diff --git a/ext/opcache/tests/jit/mul_009.phpt b/ext/opcache/tests/jit/mul_009.phpt new file mode 100644 index 0000000000000..51789527115f2 --- /dev/null +++ b/ext/opcache/tests/jit/mul_009.phpt @@ -0,0 +1,20 @@ +--TEST-- +JIT MUL: 009 memory leak +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.protect_memory=1 +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $y in %smul_009.php on line 3 + +Fatal error: Uncaught TypeError: Unsupported operand types: array * int in %smul_009.php:3 +Stack trace: +#0 {main} + thrown in %smul_009.php on line 3 \ No newline at end of file diff --git a/ext/opcache/tests/opt/gh8140a.phpt b/ext/opcache/tests/opt/gh8140a.phpt index 03f097c77c5ce..998b33e75685b 100644 --- a/ext/opcache/tests/opt/gh8140a.phpt +++ b/ext/opcache/tests/opt/gh8140a.phpt @@ -5,7 +5,7 @@ GH-8140 (Wrong first class callable by name optimization) namespace Test; function greeter(string $name) { - echo "Hello, ${name}!"; + echo "Hello, {$name}!"; } $mycallable = greeter(...); diff --git a/ext/opcache/tests/opt/gh8140b.phpt b/ext/opcache/tests/opt/gh8140b.phpt index 60da3a79e1408..cdffab4463b5e 100644 --- a/ext/opcache/tests/opt/gh8140b.phpt +++ b/ext/opcache/tests/opt/gh8140b.phpt @@ -5,7 +5,7 @@ GH-8140 (Wrong first class callable by name optimization) $mycallable = greeter(...); function greeter(string $name) { - echo "Hello, ${name}!"; + echo "Hello, {$name}!"; } $mycallable("world"); diff --git a/ext/opcache/tests/opt/inference_004.phpt b/ext/opcache/tests/opt/inference_004.phpt new file mode 100644 index 0000000000000..377cef95d7cbe --- /dev/null +++ b/ext/opcache/tests/opt/inference_004.phpt @@ -0,0 +1,18 @@ +--TEST-- +Type inference 004: Type narrowing warning during type inference of ZEND_FETCH_DIM_W +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- +y = c; + $arr = c; + } +} +?> +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/opt/inference_005.phpt b/ext/opcache/tests/opt/inference_005.phpt new file mode 100644 index 0000000000000..35d9c7b1a6fe0 --- /dev/null +++ b/ext/opcache/tests/opt/inference_005.phpt @@ -0,0 +1,16 @@ +--TEST-- +Type inference 005: Use MAY_BE_NULL result (insted of empty) for ASSIGN_DIM with invalid arguments +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/opt/inference_006.phpt b/ext/opcache/tests/opt/inference_006.phpt new file mode 100644 index 0000000000000..245b1f6c6d7fe --- /dev/null +++ b/ext/opcache/tests/opt/inference_006.phpt @@ -0,0 +1,16 @@ +--TEST-- +Type inference 006: FETCH_DIM_W with invalid key type +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/opt/inference_007.phpt b/ext/opcache/tests/opt/inference_007.phpt new file mode 100644 index 0000000000000..4bf61601ce1e2 --- /dev/null +++ b/ext/opcache/tests/opt/inference_007.phpt @@ -0,0 +1,18 @@ +--TEST-- +Type inference 007: Incorrect array key type inference +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- +""); + } +} +?> +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/opt/isset_var_001.phpt b/ext/opcache/tests/opt/isset_var_001.phpt new file mode 100644 index 0000000000000..4efdbb59786b3 --- /dev/null +++ b/ext/opcache/tests/opt/isset_var_001.phpt @@ -0,0 +1,19 @@ +--TEST-- +ISSET_ISEMPTY_VAR 001: CONST operand of ISSET_ISEMPTY_VAR must be converted to STRING +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/opt/nullsafe_002.phpt b/ext/opcache/tests/opt/nullsafe_002.phpt index 32dc25de15878..73e607a66cf22 100644 --- a/ext/opcache/tests/opt/nullsafe_002.phpt +++ b/ext/opcache/tests/opt/nullsafe_002.phpt @@ -30,7 +30,7 @@ BB0: 0000 RETURN int(1) test: - ; (lines=7, args=1, vars=1, tmps=1, ssa_vars=6, no_loops) + ; (lines=7, args=1, vars=1, tmps=2, ssa_vars=6, no_loops) ; (before dfa pass) ; %s ; return [null] RANGE[0..0] diff --git a/ext/opcache/tests/opt/prop_types.phpt b/ext/opcache/tests/opt/prop_types.phpt index 063a7f04efc74..44e8f3d9767d2 100644 --- a/ext/opcache/tests/opt/prop_types.phpt +++ b/ext/opcache/tests/opt/prop_types.phpt @@ -50,7 +50,7 @@ BB0: 0000 RETURN int(1) noScope: - ; (lines=10, args=1, vars=1, tmps=1, ssa_vars=5, no_loops) + ; (lines=10, args=1, vars=1, tmps=4, ssa_vars=5, no_loops) ; (before dfa pass) ; %s ; return [null] RANGE[0..0] @@ -62,15 +62,15 @@ BB0: 0001 INIT_FCALL 3 %d string("var_dump") 0002 #2.T1 [bool] = FETCH_OBJ_R #1.CV0($test) [object (instanceof Test)] string("public") 0003 SEND_VAL #2.T1 [bool] 1 -0004 #3.T1 [any] = FETCH_OBJ_R #1.CV0($test) [object (instanceof Test)] string("protected") -0005 SEND_VAL #3.T1 [any] 2 -0006 #4.T1 [any] = FETCH_OBJ_R #1.CV0($test) [object (instanceof Test)] string("private") -0007 SEND_VAL #4.T1 [any] 3 +0004 #3.T2 [any] = FETCH_OBJ_R #1.CV0($test) [object (instanceof Test)] string("protected") +0005 SEND_VAL #3.T2 [any] 2 +0006 #4.T3 [any] = FETCH_OBJ_R #1.CV0($test) [object (instanceof Test)] string("private") +0007 SEND_VAL #4.T3 [any] 3 0008 DO_ICALL 0009 RETURN null Test::inTest: - ; (lines=9, args=0, vars=0, tmps=1, ssa_vars=3, no_loops) + ; (lines=9, args=0, vars=0, tmps=4, ssa_vars=3, no_loops) ; (before dfa pass) ; %s ; return [null] RANGE[0..0] @@ -80,15 +80,15 @@ BB0: 0000 INIT_FCALL 3 %d string("var_dump") 0001 #0.T0 [bool] = FETCH_OBJ_R THIS string("public") 0002 SEND_VAL #0.T0 [bool] 1 -0003 #1.T0 [long] = FETCH_OBJ_R THIS string("protected") -0004 SEND_VAL #1.T0 [long] 2 -0005 #2.T0 [double] = FETCH_OBJ_R THIS string("private") -0006 SEND_VAL #2.T0 [double] 3 +0003 #1.T1 [long] = FETCH_OBJ_R THIS string("protected") +0004 SEND_VAL #1.T1 [long] 2 +0005 #2.T2 [double] = FETCH_OBJ_R THIS string("private") +0006 SEND_VAL #2.T2 [double] 3 0007 DO_ICALL 0008 RETURN null Test::inTestWithTest2: - ; (lines=10, args=1, vars=1, tmps=1, ssa_vars=5, no_loops) + ; (lines=10, args=1, vars=1, tmps=4, ssa_vars=5, no_loops) ; (before dfa pass) ; %s ; return [null] RANGE[0..0] @@ -100,15 +100,15 @@ BB0: 0001 INIT_FCALL 3 %d string("var_dump") 0002 #2.T1 [bool] = FETCH_OBJ_R #1.CV0($test2) [object (instanceof Test2)] string("public") 0003 SEND_VAL #2.T1 [bool] 1 -0004 #3.T1 [long] = FETCH_OBJ_R #1.CV0($test2) [object (instanceof Test2)] string("protected") -0005 SEND_VAL #3.T1 [long] 2 -0006 #4.T1 [double] = FETCH_OBJ_R #1.CV0($test2) [object (instanceof Test2)] string("private") -0007 SEND_VAL #4.T1 [double] 3 +0004 #3.T2 [long] = FETCH_OBJ_R #1.CV0($test2) [object (instanceof Test2)] string("protected") +0005 SEND_VAL #3.T2 [long] 2 +0006 #4.T3 [double] = FETCH_OBJ_R #1.CV0($test2) [object (instanceof Test2)] string("private") +0007 SEND_VAL #4.T3 [double] 3 0008 DO_ICALL 0009 RETURN null Test2::inTest2: - ; (lines=9, args=0, vars=0, tmps=1, ssa_vars=3, no_loops) + ; (lines=9, args=0, vars=0, tmps=4, ssa_vars=3, no_loops) ; (before dfa pass) ; %s ; return [null] RANGE[0..0] @@ -118,9 +118,9 @@ BB0: 0000 INIT_FCALL 3 %d string("var_dump") 0001 #0.T0 [bool] = FETCH_OBJ_R THIS string("public") 0002 SEND_VAL #0.T0 [bool] 1 -0003 #1.T0 [long] = FETCH_OBJ_R THIS string("protected") -0004 SEND_VAL #1.T0 [long] 2 -0005 #2.T0 [array of [any, ref]] = FETCH_OBJ_R THIS string("private") -0006 SEND_VAL #2.T0 [array of [any, ref]] 3 +0003 #1.T1 [long] = FETCH_OBJ_R THIS string("protected") +0004 SEND_VAL #1.T1 [long] 2 +0005 #2.T2 [array of [any, ref]] = FETCH_OBJ_R THIS string("private") +0006 SEND_VAL #2.T2 [array of [any, ref]] 3 0007 DO_ICALL 0008 RETURN null diff --git a/ext/opcache/tests/opt/sccp_039.phpt b/ext/opcache/tests/opt/sccp_039.phpt new file mode 100644 index 0000000000000..f4e7933b2a712 --- /dev/null +++ b/ext/opcache/tests/opt/sccp_039.phpt @@ -0,0 +1,15 @@ +--TEST-- +SCCP 039: Incorrect constant propagation for VERIFY_RETURN_TYPE +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/opt/tmp_001.phpt b/ext/opcache/tests/opt/tmp_001.phpt new file mode 100644 index 0000000000000..83b679f5f76f1 --- /dev/null +++ b/ext/opcache/tests/opt/tmp_001.phpt @@ -0,0 +1,18 @@ +--TEST-- +TMP variable optimization 001: TMP variable renumbering should be done after DFA optimizations +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $y in %stmp_001.php on line 2 + +Fatal error: Uncaught ArgumentCountError: is_a() expects at least 2 arguments, 1 given in %stmp_001.php:2 +Stack trace: +#0 %stmp_001.php(2): is_a(0) +#1 {main} + thrown in %stmp_001.php on line 2 \ No newline at end of file diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index b09eb9ff41ad9..5bdfe7a373a73 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -134,7 +134,7 @@ static ZEND_INI_MH(OnUpdateFileCache) if (!ZSTR_LEN(new_value)) { new_value = NULL; } else { - zend_stat_t buf; + zend_stat_t buf = {0}; if (!IS_ABSOLUTE_PATH(ZSTR_VAL(new_value), ZSTR_LEN(new_value)) || zend_stat(ZSTR_VAL(new_value), &buf) != 0 || diff --git a/ext/openssl/openssl.stub.php b/ext/openssl/openssl.stub.php index b1e5a06b4f07d..316df87893b08 100644 --- a/ext/openssl/openssl.stub.php +++ b/ext/openssl/openssl.stub.php @@ -66,7 +66,7 @@ function openssl_pkcs12_read(string $pkcs12, &$certificates, string $passphrase) function openssl_csr_export_to_file(OpenSSLCertificateSigningRequest|string $csr, string $output_filename, bool $no_text = true): bool {} -/** @param OpenSSLAsymmetricKey $output */ +/** @param string $output */ function openssl_csr_export(OpenSSLCertificateSigningRequest|string $csr, &$output, bool $no_text = true): bool {} /** @param OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key */ diff --git a/ext/openssl/openssl_arginfo.h b/ext/openssl/openssl_arginfo.h index ea6bc4bdb09fe..9ed898b28a607 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: 320aca9647019329a42dc3e7937420610a8a4419 */ + * Stub hash: b820bb89ed3a0612473de268b057663ee237f876 */ 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) diff --git a/ext/openssl/tests/bug79589.phpt b/ext/openssl/tests/bug79589.phpt new file mode 100644 index 0000000000000..5d277e8c63ce6 --- /dev/null +++ b/ext/openssl/tests/bug79589.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #65538: TLS unexpected EOF failure +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + ['verify_peer'=> false]]) +); +echo gettype($release); + +?> +--EXPECT-- +string diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 5564bf6f08681..3faf0e2161a8d 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -1634,6 +1634,11 @@ int php_openssl_setup_crypto(php_stream *stream, ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; +#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF + /* Only for OpenSSL 3+ to keep OpenSSL 1.1.1 behavior */ + ssl_ctx_options |= SSL_OP_IGNORE_UNEXPECTED_EOF; +#endif + if (!GET_VER_OPT("disable_compression") || zend_is_true(val)) { ssl_ctx_options |= SSL_OP_NO_COMPRESSION; } diff --git a/ext/pdo_mysql/tests/pdo_mysql___construct_uri.phpt b/ext/pdo_mysql/tests/pdo_mysql___construct_uri.phpt index 59cb144e1917d..2c8364a90271a 100644 --- a/ext/pdo_mysql/tests/pdo_mysql___construct_uri.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql___construct_uri.phpt @@ -19,10 +19,9 @@ MySQLPDOTest::skip(); $dsn = MySQLPDOTest::getDSN(); $user = PDO_MYSQL_TEST_USER; $pass = PDO_MYSQL_TEST_PASS; - $uri = sprintf('uri:file://%s', (substr(PHP_OS, 0, 3) == 'WIN' ? str_replace('\\', '/', $file) : $file)); + $uri = 'uri:file://' . $file; if ($fp = @fopen($file, 'w')) { - // ok, great we can create a file with a DSN in it fwrite($fp, $dsn); fclose($fp); clearstatcache(); @@ -39,38 +38,23 @@ MySQLPDOTest::skip(); } if ($fp = @fopen($file, 'w')) { - fwrite($fp, sprintf('mysql:dbname=letshopeinvalid;%s%s', - chr(0), $dsn)); + fwrite($fp, $dsn . chr(0) . ';host=nonsense;unix_socket=nonsense'); fclose($fp); clearstatcache(); assert(file_exists($file)); try { $db = new PDO($uri, $user, $pass); } catch (PDOException $e) { - $expected = array( - "SQLSTATE[HY000] [1049]", - "SQLSTATE[42000] [1049]", - "SQLSTATE[HY000] [2002]" - ); - $isExpected = false; - foreach ($expected as $prefix) { - if (str_starts_with($e->getMessage(), $prefix)) { - $isExpected = true; - } - } - - printf("[003] URI=%s, DSN=%s, File=%s (%d bytes, '%s'), chr(0) test, %s\n", - $uri, $dsn, - $file, filesize($file), file_get_contents($file), - ($isExpected ? 'EXPECTED ERROR' : $e->getMessage())); + printf("[003] URI=%s, DSN=%s, File=%s (%d bytes, '%s'), %s\n", + $uri, $dsn, + $file, filesize($file), file_get_contents($file), + $e->getMessage()); } unlink($file); } } - /* TODO: safe mode */ - } catch (PDOException $e) { printf("[001] %s, [%s] %s\n", $e->getMessage(), @@ -81,5 +65,4 @@ MySQLPDOTest::skip(); print "done!"; ?> --EXPECTF-- -[003] URI=uri:file://%spdomuri.tst, DSN=mysql%sdbname=%s, File=%spdomuri.tst (%d bytes, 'mysql%sdbname=letshopeinvalid%s'), chr(0) test, EXPECTED ERROR done! diff --git a/ext/pgsql/tests/80_bug14383.phpt b/ext/pgsql/tests/80_bug14383.phpt index 0859d65f0849c..c9848e30c1d64 100644 --- a/ext/pgsql/tests/80_bug14383.phpt +++ b/ext/pgsql/tests/80_bug14383.phpt @@ -21,6 +21,10 @@ pg_close($dbh); require_once(__DIR__.'/../../dba/tests/test.inc'); require_once(__DIR__.'/../../dba/tests/dba_handler.inc'); +?> +--CLEAN-- + --EXPECTF-- database handler: %s diff --git a/ext/pgsql/tests/README.md b/ext/pgsql/tests/README.md index ecc2919eb86f6..b649e4f2793ee 100644 --- a/ext/pgsql/tests/README.md +++ b/ext/pgsql/tests/README.md @@ -15,4 +15,4 @@ as the same user running the tests you ensure that the user is granted access to the database. If you find problems in PostgreSQL extension, please report a -[bug](https://bugs.php.net). +[bug](https://github.com/php/php-src/issues). diff --git a/ext/pgsql/tests/config.inc b/ext/pgsql/tests/config.inc index fbe58588a208f..66ba4810203af 100644 --- a/ext/pgsql/tests/config.inc +++ b/ext/pgsql/tests/config.inc @@ -16,8 +16,8 @@ $view_name = "php_pgsql_viewtest"; $view_def = "CREATE VIEW {$view_name} AS SELECT * FROM {$table_name};"; // Test table -$table_def = "CREATE TABLE ${table_name} (num int, str text, bin bytea);"; -$table_def_92 = "CREATE TABLE ${table_name_92} (textary text[], jsn json);"; +$table_def = "CREATE TABLE {$table_name} (num int, str text, bin bytea);"; +$table_def_92 = "CREATE TABLE {$table_name_92} (textary text[], jsn json);"; $field_name = "num"; // For pg_field_num() ?> diff --git a/ext/phar/phar.1.in b/ext/phar/phar.1.in index 75c3a354825be..ac314fe9d5807 100644 --- a/ext/phar/phar.1.in +++ b/ext/phar/phar.1.in @@ -497,7 +497,7 @@ You can view the list of known bugs or report any new bug you found at: .PD 0 .P -.B http://bugs.php.net +.B https://github.com/php/php-src/issues .PD 1 .SH AUTHORS The PHP Group: Thies C. Arntzen, Stig Bakken, Andi Gutmans, Rasmus Lerdorf, Sam Ruby, Sascha Schumann, Zeev Suraski, Jim Winstead, Andrei Zmievski. diff --git a/ext/phar/phar/clicommand.inc b/ext/phar/phar/clicommand.inc index 7527e1c4d9e7d..0b84bd6030b4f 100644 --- a/ext/phar/phar/clicommand.inc +++ b/ext/phar/phar/clicommand.inc @@ -30,9 +30,9 @@ abstract class CLICommand $this->typs = self::getArgTyps($this); if ($argc < 2) { - self::error("No command given, check ${argv[0]} help\n"); + self::error("No command given, check {$argv[0]} help\n"); } elseif (!isset($this->cmds[$argv[1]]['run'])) { - self::error("Unknown command '${argv[1]}', check ${argv[0]} help\n"); + self::error("Unknown command '{$argv[1]}', check {$argv[0]} help\n"); } else { $command = $argv[1]; } @@ -46,12 +46,12 @@ abstract class CLICommand if (strlen($argv[$i]) == 2 && isset($this->args[$argv[$i][1]])) { $arg = $argv[$i][1]; if (++$i >= $argc) { - self::error("Missing argument to parameter '$arg' of command '$command', check ${argv[0]} help\n"); + self::error("Missing argument to parameter '$arg' of command '$command', check {$argv[0]} help\n"); } else { $this->args[$arg]['val'] = $this->checkArgTyp($arg, $i, $argc, $argv); } } else { - self::error("Unknown parameter '${argv[$i]}' to command $command, check ${argv[0]} help\n"); + self::error("Unknown parameter '{$argv[$i]}' to command $command, check {$argv[0]} help\n"); } } else { break; @@ -61,7 +61,7 @@ abstract class CLICommand if (isset($this->args[''])) { if ($i >= $argc) { if (isset($this->args['']['require']) && $this->args['']['require']) { - self::error("Missing default trailing arguments to command $command, check ${argv[0]} help\n"); + self::error("Missing default trailing arguments to command $command, check {$argv[0]} help\n"); } } else { $this->args['']['val'] = array(); @@ -70,12 +70,12 @@ abstract class CLICommand } } } else if ($i < $argc) { - self::error("Unexpected default arguments to command $command, check ${argv[0]} help\n"); + self::error("Unexpected default arguments to command $command, check {$argv[0]} help\n"); } foreach($this->args as $arg => $inf) { if (strlen($arg) && !isset($inf['val']) && isset($inf['required']) && $inf['required']) { - $missing .= "Missing parameter '-$arg' to command $command, check ${argv[0]} help\n"; + $missing .= "Missing parameter '-$arg' to command $command, check {$argv[0]} help\n"; } } @@ -265,7 +265,7 @@ abstract class CLICommand $sp3 = $this->cli_get_SP3($l, $ls, $inf); $l3 = strlen($sp3); foreach($conf['select'] as $opt => $what) { - $inf .= $this->cli_wordwrap($sp2 . " " . sprintf("%-${ls}s ", $opt) . $what, $l3, $sp3) . "\n"; + $inf .= $this->cli_wordwrap($sp2 . " " . sprintf("%-{$ls}s ", $opt) . $what, $l3, $sp3) . "\n"; } } } diff --git a/ext/phar/phar/pharcommand.inc b/ext/phar/phar/pharcommand.inc index 1b1eeca59c560..fdc43654dd7eb 100644 --- a/ext/phar/phar/pharcommand.inc +++ b/ext/phar/phar/pharcommand.inc @@ -1598,7 +1598,7 @@ class PharCommand extends CLICommand if (is_bool($v)) { $v = $v ? 'enabled' : 'disabled'; } - printf("%-${klen}s %s\n", $k.':', $v); + printf("%-{$klen}s %s\n", $k.':', $v); } } // }}} diff --git a/ext/phar/tests/fatal_error_webphar.phpt b/ext/phar/tests/fatal_error_webphar.phpt index 9ac1e03503a50..4617ee0c45745 100644 --- a/ext/phar/tests/fatal_error_webphar.phpt +++ b/ext/phar/tests/fatal_error_webphar.phpt @@ -1,7 +1,5 @@ --TEST-- Phar web-based phar with fatal error ---XFAIL-- -Uses no longer supported __autoload() function, new phar needed --INI-- default_charset=UTF-8 --EXTENSIONS-- @@ -15,7 +13,6 @@ files/pear2coverage.phar --EXPECTHEADERS-- Content-type: text/html; charset=UTF-8 --EXPECTF-- -Deprecated: __autoload() is deprecated, use spl_autoload_register() instead in %s on line %d string(9) "\Web\View" Parse error: syntax error, unexpected %s, expecting %s in phar://%r([A-Za-z]:)?%r/%sfatal_error_webphar.php/Web/View.php on line 380 diff --git a/ext/phar/tests/files/pear2coverage.phar b/ext/phar/tests/files/pear2coverage.phar index 621b0d07f8de1..4382d4fd8110e 100644 Binary files a/ext/phar/tests/files/pear2coverage.phar and b/ext/phar/tests/files/pear2coverage.phar differ diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 4f30cc2fca700..5ca89f0d2a742 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -638,6 +638,13 @@ static int format_default_value(smart_str *str, zval *value) { format_default_value(str, zv); } ZEND_HASH_FOREACH_END(); smart_str_appendc(str, ']'); + } else if (Z_TYPE_P(value) == IS_OBJECT) { + zend_object *obj = Z_OBJ_P(value); + zend_class_entry *class = obj->ce; + ZEND_ASSERT(class->ce_flags & ZEND_ACC_ENUM); + smart_str_append(str, class->name); + smart_str_appends(str, "::"); + smart_str_append(str, Z_STR_P(zend_enum_fetch_case_name(obj))); } else { ZEND_ASSERT(Z_TYPE_P(value) == IS_CONSTANT_AST); zend_string *ast_str = zend_ast_export("", Z_ASTVAL_P(value), ""); @@ -1783,6 +1790,19 @@ ZEND_METHOD(ReflectionFunctionAbstract, isUserDefined) } /* }}} */ +/* {{{ Returns whether this function is an anonymous closure or not */ +ZEND_METHOD(ReflectionFunction, isAnonymous) +{ + reflection_object *intern; + zend_function *fptr; + + ZEND_PARSE_PARAMETERS_NONE(); + + GET_REFLECTION_OBJECT_PTR(fptr); + RETURN_BOOL((fptr->common.fn_flags & (ZEND_ACC_CLOSURE | ZEND_ACC_FAKE_CLOSURE)) == ZEND_ACC_CLOSURE); +} +/* }}} */ + /* {{{ Returns whether this function has been disabled or not */ ZEND_METHOD(ReflectionFunction, isDisabled) { @@ -1872,7 +1892,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, getAttributes) GET_REFLECTION_OBJECT_PTR(fptr); - if (fptr->common.scope) { + if (fptr->common.scope && !(fptr->common.fn_flags & ZEND_ACC_CLOSURE)) { target = ZEND_ATTRIBUTE_TARGET_METHOD; } else { target = ZEND_ATTRIBUTE_TARGET_FUNCTION; @@ -1981,12 +2001,12 @@ ZEND_METHOD(ReflectionFunction, invokeArgs) zend_function *fptr; HashTable *params; - GET_REFLECTION_OBJECT_PTR(fptr); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "h", ¶ms) == FAILURE) { RETURN_THROWS(); } + GET_REFLECTION_OBJECT_PTR(fptr); + fci.size = sizeof(fci); ZVAL_UNDEF(&fci.function_name); fci.object = NULL; @@ -2027,12 +2047,12 @@ ZEND_METHOD(ReflectionFunctionAbstract, returnsReference) reflection_object *intern; zend_function *fptr; - GET_REFLECTION_OBJECT_PTR(fptr); - if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } + GET_REFLECTION_OBJECT_PTR(fptr); + RETURN_BOOL((fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0); } /* }}} */ @@ -2044,12 +2064,12 @@ ZEND_METHOD(ReflectionFunctionAbstract, getNumberOfParameters) zend_function *fptr; uint32_t num_args; - GET_REFLECTION_OBJECT_PTR(fptr); - if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } + GET_REFLECTION_OBJECT_PTR(fptr); + num_args = fptr->common.num_args; if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) { num_args++; @@ -2065,12 +2085,12 @@ ZEND_METHOD(ReflectionFunctionAbstract, getNumberOfRequiredParameters) reflection_object *intern; zend_function *fptr; - GET_REFLECTION_OBJECT_PTR(fptr); - if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } + GET_REFLECTION_OBJECT_PTR(fptr); + RETURN_LONG(fptr->common.required_num_args); } /* }}} */ @@ -2083,12 +2103,12 @@ ZEND_METHOD(ReflectionFunctionAbstract, getParameters) uint32_t i, num_args; struct _zend_arg_info *arg_info; - GET_REFLECTION_OBJECT_PTR(fptr); - if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } + GET_REFLECTION_OBJECT_PTR(fptr); + arg_info= fptr->common.arg_info; num_args = fptr->common.num_args; if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) { @@ -2125,12 +2145,12 @@ ZEND_METHOD(ReflectionFunctionAbstract, getExtension) zend_function *fptr; zend_internal_function *internal; - GET_REFLECTION_OBJECT_PTR(fptr); - if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } + GET_REFLECTION_OBJECT_PTR(fptr); + if (fptr->type != ZEND_INTERNAL_FUNCTION) { RETURN_NULL(); } @@ -2151,12 +2171,12 @@ ZEND_METHOD(ReflectionFunctionAbstract, getExtensionName) zend_function *fptr; zend_internal_function *internal; - GET_REFLECTION_OBJECT_PTR(fptr); - if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } + GET_REFLECTION_OBJECT_PTR(fptr); + if (fptr->type != ZEND_INTERNAL_FUNCTION) { RETURN_FALSE; } @@ -3637,28 +3657,43 @@ ZEND_METHOD(ReflectionMethod, getDeclaringClass) reflection_object *intern; zend_function *mptr; - GET_REFLECTION_OBJECT_PTR(mptr); - if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } + GET_REFLECTION_OBJECT_PTR(mptr); + zend_reflection_class_factory(mptr->common.scope, return_value); } /* }}} */ +/* {{{ Returns whether a method has a prototype or not */ +ZEND_METHOD(ReflectionMethod, hasPrototype) +{ + reflection_object *intern; + zend_function *mptr; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + GET_REFLECTION_OBJECT_PTR(mptr); + RETURN_BOOL(mptr->common.prototype != NULL); +} +/* }}} */ + /* {{{ Get the prototype */ ZEND_METHOD(ReflectionMethod, getPrototype) { reflection_object *intern; zend_function *mptr; - GET_REFLECTION_OBJECT_PTR(mptr); - if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } + GET_REFLECTION_OBJECT_PTR(mptr); + if (!mptr->common.prototype) { zend_throw_exception_ex(reflection_exception_ptr, 0, "Method %s::%s does not have a prototype", ZSTR_VAL(intern->ce->name), ZSTR_VAL(mptr->common.function_name)); @@ -6388,6 +6423,7 @@ ZEND_METHOD(ReflectionReference, getId) ZEND_METHOD(ReflectionAttribute, __construct) { + _DO_THROW("Cannot directly instantiate ReflectionAttribute"); } ZEND_METHOD(ReflectionAttribute, __clone) diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index 8f2ef6ec6f44e..22d01b6905168 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -117,6 +117,8 @@ public function __construct(Closure|string $function) {} public function __toString(): string {} + public function isAnonymous(): bool {} + /** * @tentative-return-type * @deprecated ReflectionFunction can no longer be constructed for disabled functions @@ -204,6 +206,8 @@ public function getDeclaringClass(): ReflectionClass {} /** @tentative-return-type */ public function getPrototype(): ReflectionMethod {} + public function hasPrototype(): bool {} + /** @tentative-return-type */ public function setAccessible(bool $accessible): void {} } diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index 12b01c4d264fd..25a750f2bdcac 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: 62fcf63d2f3e93537560c3a03e71fda131a31586 */ + * Stub hash: c9656b23db965e890e73d0064005b981ee1991cf */ 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) @@ -91,6 +91,8 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFunction___toString, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() +#define arginfo_class_ReflectionFunction_isAnonymous arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType + #define arginfo_class_ReflectionFunction_isDisabled arginfo_class_ReflectionFunctionAbstract_inNamespace ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFunction_invoke, 0, 0, IS_MIXED, 0) @@ -167,6 +169,8 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionMethod_getPrototype, 0, 0, ReflectionMethod, 0) ZEND_END_ARG_INFO() +#define arginfo_class_ReflectionMethod_hasPrototype arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType + ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionMethod_setAccessible, 0, 1, IS_VOID, 0) ZEND_ARG_TYPE_INFO(0, accessible, _IS_BOOL, 0) ZEND_END_ARG_INFO() @@ -630,6 +634,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, getTentativeReturnType); ZEND_METHOD(ReflectionFunctionAbstract, getAttributes); ZEND_METHOD(ReflectionFunction, __construct); ZEND_METHOD(ReflectionFunction, __toString); +ZEND_METHOD(ReflectionFunction, isAnonymous); ZEND_METHOD(ReflectionFunction, isDisabled); ZEND_METHOD(ReflectionFunction, invoke); ZEND_METHOD(ReflectionFunction, invokeArgs); @@ -656,6 +661,7 @@ ZEND_METHOD(ReflectionMethod, invoke); ZEND_METHOD(ReflectionMethod, invokeArgs); ZEND_METHOD(ReflectionMethod, getDeclaringClass); ZEND_METHOD(ReflectionMethod, getPrototype); +ZEND_METHOD(ReflectionMethod, hasPrototype); ZEND_METHOD(ReflectionMethod, setAccessible); ZEND_METHOD(ReflectionClass, __construct); ZEND_METHOD(ReflectionClass, __toString); @@ -878,6 +884,7 @@ static const zend_function_entry class_ReflectionFunctionAbstract_methods[] = { static const zend_function_entry class_ReflectionFunction_methods[] = { ZEND_ME(ReflectionFunction, __construct, arginfo_class_ReflectionFunction___construct, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionFunction, __toString, arginfo_class_ReflectionFunction___toString, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionFunction, isAnonymous, arginfo_class_ReflectionFunction_isAnonymous, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionFunction, isDisabled, arginfo_class_ReflectionFunction_isDisabled, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) ZEND_ME(ReflectionFunction, invoke, arginfo_class_ReflectionFunction_invoke, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionFunction, invokeArgs, arginfo_class_ReflectionFunction_invokeArgs, ZEND_ACC_PUBLIC) @@ -914,6 +921,7 @@ static const zend_function_entry class_ReflectionMethod_methods[] = { ZEND_ME(ReflectionMethod, invokeArgs, arginfo_class_ReflectionMethod_invokeArgs, ZEND_ACC_PUBLIC) 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_FE_END }; diff --git a/ext/reflection/tests/ReflectionAttribute_constructor_001.phpt b/ext/reflection/tests/ReflectionAttribute_constructor_001.phpt new file mode 100644 index 0000000000000..ad895dc424377 --- /dev/null +++ b/ext/reflection/tests/ReflectionAttribute_constructor_001.phpt @@ -0,0 +1,25 @@ +--TEST-- +ReflectionAttribute cannot be instantiated directly +--FILE-- +getAttributes()[0]; + +$rm = new ReflectionMethod($attribute, "__construct"); + +try { + var_dump($rm->invoke($attribute, 0, 1, 2)); +} catch (ReflectionException $exception) { + echo $exception->getMessage(); +} +?> +--EXPECT-- +Cannot directly instantiate ReflectionAttribute diff --git a/ext/reflection/tests/ReflectionFunction_isAnonymous.phpt b/ext/reflection/tests/ReflectionFunction_isAnonymous.phpt new file mode 100644 index 0000000000000..004e0b09af0e0 --- /dev/null +++ b/ext/reflection/tests/ReflectionFunction_isAnonymous.phpt @@ -0,0 +1,17 @@ +--TEST-- +ReflectionFunction::isAnonymous +--FILE-- +isAnonymous()); + +$rf = new ReflectionFunction('strlen'); +var_dump($rf->isAnonymous()); + +$rf = new ReflectionFunction(strlen(...)); +var_dump($rf->isAnonymous()); +?> +--EXPECT-- +bool(true) +bool(false) +bool(false) diff --git a/ext/reflection/tests/ReflectionMethod_hasPrototype_basic.phpt b/ext/reflection/tests/ReflectionMethod_hasPrototype_basic.phpt new file mode 100644 index 0000000000000..d94c8962e11b3 --- /dev/null +++ b/ext/reflection/tests/ReflectionMethod_hasPrototype_basic.phpt @@ -0,0 +1,34 @@ +--TEST-- +public ReflectionMethod ReflectionMethod::hasPrototype ( void ); +--FILE-- +hasPrototype()); + +$reflectionMethod2 = new ReflectionMethod('Hello', 'sayHelloTo'); +var_dump($reflectionMethod2->hasPrototype()); + +$reflectionMethod3 = new ReflectionMethod('HelloWorld', 'sayHiTo'); +var_dump($reflectionMethod3->hasPrototype()); + +?> +--EXPECT-- +bool(true) +bool(false) +bool(false) diff --git a/ext/reflection/tests/gh8444.phpt b/ext/reflection/tests/gh8444.phpt new file mode 100644 index 0000000000000..9629a8db38171 --- /dev/null +++ b/ext/reflection/tests/gh8444.phpt @@ -0,0 +1,31 @@ +--TEST-- +GH-8444 (Fix ReflectionProperty::__toString() of properties containing instantiated enums) +--FILE-- + +--EXPECT-- +Property [ public Foo $enum = Foo::Bar ] + +Property [ public $enumInArray = [Foo::Bar] ] + +Property [ public Foo $enum = Foo::Bar ] + +Property [ public $enumInArray = [Foo::Bar] ] diff --git a/ext/session/tests/save_handler.inc b/ext/session/tests/save_handler.inc index 56b3505284bb5..43475d33b8029 100644 --- a/ext/session/tests/save_handler.inc +++ b/ext/session/tests/save_handler.inc @@ -27,7 +27,7 @@ function open($save_path, $session_name) { global $session_save_path, $name; $session_save_path = $save_path; $name = $session_name; - echo "Open [${session_save_path},${session_name}]\n"; + echo "Open [{$session_save_path},{$session_name}]\n"; // MUST return bool. Return TRUE for success. return true; @@ -39,7 +39,7 @@ function close() { // NOTE: This function should unlock session data, if write() does not unlock it. global $session_save_path, $name; - echo "Close [${session_save_path},${name}]\n"; + echo "Close [{$session_save_path},{$name}]\n"; // MUST return bool. Return TRUE for success. return true; @@ -54,7 +54,7 @@ function read($id) { global $session_save_path, $name, $session_id; $session_id = $id; - echo "Read [${session_save_path},${id}]\n"; + echo "Read [{$session_save_path},{$id}]\n"; $session_file = "$session_save_path/".SESSION_FILE_PREFIX.$id; // read MUST create file. Otherwise, strict mode will not work touch($session_file); @@ -74,7 +74,7 @@ function write($id, $session_data) { global $session_save_path, $name, $session_id; $session_id = $id; - echo "Write [${session_save_path},${id},${session_data}]\n"; + echo "Write [{$session_save_path},{$id},{$session_data}]\n"; $session_file = "$session_save_path/".SESSION_FILE_PREFIX.$id; if ($fp = fopen($session_file, "w")) { $return = fwrite($fp, $session_data); @@ -91,7 +91,7 @@ function destroy($id) { // string $id - Session ID string global $session_save_path, $name; - echo "Destroy [${session_save_path},${id}]\n"; + echo "Destroy [{$session_save_path},{$id}]\n"; $session_file = "$session_save_path/".SESSION_FILE_PREFIX.$id; unlink($session_file); @@ -136,7 +136,7 @@ function create_sid() { // e.g. hash('sha2', random_bytes(64)) or use /dev/urandom $id = ('PHPT-'.time()); - echo "CreateID [${id}]\n"; + echo "CreateID [{$id}]\n"; // MUST return session ID string. // Return FALSE for error. @@ -148,7 +148,7 @@ function validate_sid($id) { // string $id - Session ID string global $session_save_path, $name; - echo "ValidateID [${session_save_path},${id}]\n"; + echo "ValidateID [{$session_save_path},{$id}]\n"; $session_file = "$session_save_path/".SESSION_FILE_PREFIX.$id; $ret = file_exists($session_file); @@ -168,7 +168,7 @@ function update($id, $session_data) { // support time stamp updating, you must not define this. global $session_save_path, $name; - echo "Update [${session_save_path},${id}]\n"; + echo "Update [{$session_save_path},{$id}]\n"; $session_file = "$session_save_path/".SESSION_FILE_PREFIX.$id; $ret = touch($session_file); diff --git a/ext/snmp/tests/bug64159.phpt b/ext/snmp/tests/bug64159.phpt index 24b282be7ec8e..e7cdbd5437796 100644 --- a/ext/snmp/tests/bug64159.phpt +++ b/ext/snmp/tests/bug64159.phpt @@ -7,6 +7,7 @@ snmp --SKIPIF-- --ENV-- MIBS=noneXistent diff --git a/ext/snmp/tests/snmp_getvalue.phpt b/ext/snmp/tests/snmp_getvalue.phpt index 2abc61181cf65..f62482d90d395 100644 --- a/ext/snmp/tests/snmp_getvalue.phpt +++ b/ext/snmp/tests/snmp_getvalue.phpt @@ -7,6 +7,7 @@ snmp --SKIPIF-- --FILE-- ar_flags &= ~SPL_ARRAY_IS_SELF & ~SPL_ARRAY_USE_OTHER; intern->ar_flags |= ar_flags; - intern->ht_iter = (uint32_t)-1; + if (intern->ht_iter != (uint32_t)-1) { + zend_hash_iterator_del(intern->ht_iter); + intern->ht_iter = (uint32_t)-1; + } } /* }}} */ @@ -1304,7 +1307,7 @@ PHP_METHOD(ArrayObject, count) RETURN_LONG(spl_array_object_count_elements_helper(intern)); } /* }}} */ -static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fname_len, int use_arg) /* {{{ */ +static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, size_t fname_len, int use_arg) /* {{{ */ { spl_array_object *intern = Z_SPLARRAY_P(ZEND_THIS); HashTable **ht_ptr = spl_array_get_hash_table_ptr(intern); @@ -1393,12 +1396,12 @@ PHP_METHOD(ArrayIterator, current) } if ((entry = zend_hash_get_current_data_ex(aht, spl_array_get_pos_ptr(aht, intern))) == NULL) { - return; + RETURN_NULL(); } if (Z_TYPE_P(entry) == IS_INDIRECT) { entry = Z_INDIRECT_P(entry); if (Z_TYPE_P(entry) == IS_UNDEF) { - return; + RETURN_NULL(); } } RETURN_COPY_DEREF(entry); @@ -1490,7 +1493,7 @@ PHP_METHOD(RecursiveArrayIterator, getChildren) } if ((entry = zend_hash_get_current_data_ex(aht, spl_array_get_pos_ptr(aht, intern))) == NULL) { - return; + RETURN_NULL(); } if (Z_TYPE_P(entry) == IS_INDIRECT) { @@ -1500,7 +1503,7 @@ PHP_METHOD(RecursiveArrayIterator, getChildren) ZVAL_DEREF(entry); if (Z_TYPE_P(entry) == IS_OBJECT) { if ((intern->ar_flags & SPL_ARRAY_CHILD_ARRAYS_ONLY) != 0) { - return; + RETURN_NULL(); } if (instanceof_function(Z_OBJCE_P(entry), Z_OBJCE_P(ZEND_THIS))) { RETURN_OBJ_COPY(Z_OBJ_P(entry)); diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 8e89b86048750..bfeb7f185327b 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1865,11 +1865,10 @@ static int spl_filesystem_object_cast(zend_object *readobj, zval *writeobj, int } /* }}} */ -static zend_result spl_filesystem_file_read(spl_filesystem_object *intern, bool silent) /* {{{ */ +static zend_result spl_filesystem_file_read_ex(spl_filesystem_object *intern, bool silent, zend_long line_add) /* {{{ */ { char *buf; size_t line_len = 0; - zend_long line_add = (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) ? 1 : 0; spl_filesystem_file_free_line(intern); @@ -1914,6 +1913,12 @@ static zend_result spl_filesystem_file_read(spl_filesystem_object *intern, bool return SUCCESS; } /* }}} */ +static inline zend_result spl_filesystem_file_read(spl_filesystem_object *intern, bool silent) +{ + zend_long line_add = (intern->u.file.current_line) ? 1 : 0; + return spl_filesystem_file_read_ex(intern, silent, line_add); +} + static zend_result spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, int escape, zval *return_value) /* {{{ */ { do { @@ -2183,7 +2188,7 @@ PHP_METHOD(SplFileObject, fgets) CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern); - if (spl_filesystem_file_read(intern, 0) == FAILURE) { + if (spl_filesystem_file_read_ex(intern, /* silent */ false, /* line_add */ 1) == FAILURE) { RETURN_THROWS(); } RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len); @@ -2221,8 +2226,8 @@ PHP_METHOD(SplFileObject, key) RETURN_THROWS(); } -/* Do not read the next line to support correct counting with fgetc() - if (!intern->current_line) { + /* Do not read the next line to support correct counting with fgetc() + if (!intern->u.file.current_line) { spl_filesystem_file_read_line(ZEND_THIS, intern, 1); } */ RETURN_LONG(intern->u.file.current_line_num); diff --git a/ext/spl/spl_directory.stub.php b/ext/spl/spl_directory.stub.php index ceb4b7124b5df..c9a7f9ff9777b 100644 --- a/ext/spl/spl_directory.stub.php +++ b/ext/spl/spl_directory.stub.php @@ -279,10 +279,10 @@ public function setMaxLineLen(int $maxLength): void {} public function getMaxLineLen(): int {} /** @tentative-return-type */ - public function hasChildren(): bool {} + public function hasChildren(): false {} /** @tentative-return-type */ - public function getChildren(): ?RecursiveIterator {} + public function getChildren(): null {} /** @tentative-return-type */ public function seek(int $line): void {} diff --git a/ext/spl/spl_directory_arginfo.h b/ext/spl/spl_directory_arginfo.h index bcdb51ea54254..338bd27c19b84 100644 --- a/ext/spl/spl_directory_arginfo.h +++ b/ext/spl/spl_directory_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3f2caf1c46760d8ef629ccb2e94ab0dba09f713b */ + * Stub hash: 3ada856cfa2e50708b43125f819706176b1953f7 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SplFileInfo___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) @@ -254,9 +254,10 @@ ZEND_END_ARG_INFO() #define arginfo_class_SplFileObject_getMaxLineLen arginfo_class_FilesystemIterator_getFlags -#define arginfo_class_SplFileObject_hasChildren arginfo_class_SplFileInfo_isWritable +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplFileObject_hasChildren, 0, 0, IS_FALSE, 0) +ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_SplFileObject_getChildren, 0, 0, RecursiveIterator, 1) +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplFileObject_getChildren, 0, 0, IS_NULL, 1) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplFileObject_seek, 0, 1, IS_VOID, 0) diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 0daf486e40b60..5fd3830014a3d 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -1215,7 +1215,7 @@ PHP_METHOD(SplDoublyLinkedList, add) PHP_METHOD(SplDoublyLinkedList, __debugInfo) { if (zend_parse_parameters_none() == FAILURE) { - return; + RETURN_THROWS(); } RETURN_ARR(spl_dllist_object_get_debug_info(Z_OBJ_P(ZEND_THIS))); diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 9fdbc34cb7fe5..5f8dca8dd1812 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -781,7 +781,7 @@ PHP_METHOD(SplFixedArray, offsetUnset) PHP_METHOD(SplFixedArray, getIterator) { if (zend_parse_parameters_none() == FAILURE) { - return; + RETURN_THROWS(); } zend_create_internal_iterator_zval(return_value, ZEND_THIS); diff --git a/ext/spl/spl_functions.c b/ext/spl/spl_functions.c index 0f46c2e8b18fb..0fcf389667355 100644 --- a/ext/spl/spl_functions.c +++ b/ext/spl/spl_functions.c @@ -19,8 +19,6 @@ #endif #include "php.h" -#include "php_ini.h" -#include "ext/standard/info.h" #include "php_spl.h" /* {{{ spl_add_class_name */ @@ -41,11 +39,9 @@ void spl_add_class_name(zval *list, zend_class_entry *pce, int allow, int ce_fla /* {{{ spl_add_interfaces */ void spl_add_interfaces(zval *list, zend_class_entry * pce, int allow, int ce_flags) { - uint32_t num_interfaces; - if (pce->num_interfaces) { ZEND_ASSERT(pce->ce_flags & ZEND_ACC_LINKED); - for (num_interfaces = 0; num_interfaces < pce->num_interfaces; num_interfaces++) { + for (uint32_t num_interfaces = 0; num_interfaces < pce->num_interfaces; num_interfaces++) { spl_add_class_name(list, pce->interfaces[num_interfaces], allow, ce_flags); } } @@ -55,10 +51,9 @@ void spl_add_interfaces(zval *list, zend_class_entry * pce, int allow, int ce_fl /* {{{ spl_add_traits */ void spl_add_traits(zval *list, zend_class_entry * pce, int allow, int ce_flags) { - uint32_t num_traits; zend_class_entry *trait; - for (num_traits = 0; num_traits < pce->num_traits; num_traits++) { + for (uint32_t num_traits = 0; num_traits < pce->num_traits; num_traits++) { trait = zend_fetch_class_by_name(pce->trait_names[num_traits].name, pce->trait_names[num_traits].lc_name, ZEND_FETCH_CLASS_TRAIT); ZEND_ASSERT(trait); @@ -69,11 +64,9 @@ void spl_add_traits(zval *list, zend_class_entry * pce, int allow, int ce_flags) /* {{{ spl_add_classes */ -int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int ce_flags) +void spl_add_classes(zend_class_entry *pce, zval *list, bool sub, int allow, int ce_flags) { - if (!pce) { - return 0; - } + ZEND_ASSERT(pce); spl_add_class_name(list, pce, allow, ce_flags); if (sub) { spl_add_interfaces(list, pce, allow, ce_flags); @@ -82,11 +75,10 @@ int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int c spl_add_classes(pce, list, sub, allow, ce_flags); } } - return 0; } /* }}} */ -zend_string * spl_gen_private_prop_name(zend_class_entry *ce, char *prop_name, int prop_len) /* {{{ */ +zend_string * spl_gen_private_prop_name(zend_class_entry *ce, char *prop_name, size_t prop_len) /* {{{ */ { return zend_mangle_property_name(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), prop_name, prop_len, 0); } diff --git a/ext/spl/spl_functions.h b/ext/spl/spl_functions.h index e6c3171c34fd9..20eb323c5fec0 100644 --- a/ext/spl/spl_functions.h +++ b/ext/spl/spl_functions.h @@ -32,9 +32,9 @@ typedef zend_object* (*create_object_func_t)(zend_class_entry *class_type); void spl_add_class_name(zval * list, zend_class_entry * pce, int allow, int ce_flags); void spl_add_interfaces(zval * list, zend_class_entry * pce, int allow, int ce_flags); void spl_add_traits(zval * list, zend_class_entry * pce, int allow, int ce_flags); -int spl_add_classes(zend_class_entry *pce, zval *list, int sub, int allow, int ce_flags); +void spl_add_classes(zend_class_entry *pce, zval *list, bool sub, int allow, int ce_flags); /* caller must efree(return) */ -zend_string *spl_gen_private_prop_name(zend_class_entry *ce, char *prop_name, int prop_len); +zend_string *spl_gen_private_prop_name(zend_class_entry *ce, char *prop_name, size_t prop_len); #endif /* PHP_FUNCTIONS_H */ diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index bb874e47dc828..3112666e33651 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -1053,7 +1053,7 @@ PHP_METHOD(SplPriorityQueue, current) PHP_METHOD(SplHeap, __debugInfo) { if (zend_parse_parameters_none() == FAILURE) { - return; + RETURN_THROWS(); } RETURN_ARR(spl_heap_object_get_debug_info(spl_ce_SplHeap, Z_OBJ_P(ZEND_THIS))); @@ -1063,7 +1063,7 @@ PHP_METHOD(SplHeap, __debugInfo) PHP_METHOD(SplPriorityQueue, __debugInfo) { if (zend_parse_parameters_none() == FAILURE) { - return; + RETURN_THROWS(); } RETURN_ARR(spl_heap_object_get_debug_info(spl_ce_SplPriorityQueue, Z_OBJ_P(ZEND_THIS))); diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 217f3aa19c038..f46c869738ef3 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -870,7 +870,7 @@ PHP_METHOD(RecursiveIteratorIterator, callGetChildren) zobject = &object->iterators[object->level].zobject; if (Z_TYPE_P(zobject) == IS_UNDEF) { - return; + RETURN_NULL(); } else { zend_call_method_with_0_params(Z_OBJ_P(zobject), ce, &object->iterators[object->level].getchildren, "getchildren", return_value); if (Z_TYPE_P(return_value) == IS_UNDEF) { @@ -3181,6 +3181,9 @@ PHP_FUNCTION(iterator_to_array) static int spl_iterator_count_apply(zend_object_iterator *iter, void *puser) /* {{{ */ { + if (UNEXPECTED(*(zend_long*)puser == ZEND_LONG_MAX)) { + return ZEND_HASH_APPLY_STOP; + } (*(zend_long*)puser)++; return ZEND_HASH_APPLY_KEEP; } diff --git a/ext/spl/spl_iterators.stub.php b/ext/spl/spl_iterators.stub.php index 9d80717f85d8f..4235ed100baec 100644 --- a/ext/spl/spl_iterators.stub.php +++ b/ext/spl/spl_iterators.stub.php @@ -14,7 +14,7 @@ public function next(): void {} public function key(): never {} /** @tentative-return-type */ - public function valid(): bool {} + public function valid(): false {} /** @tentative-return-type */ public function rewind(): void {} diff --git a/ext/spl/spl_iterators_arginfo.h b/ext/spl/spl_iterators_arginfo.h index 5b29dc293f186..91735b58d8dd4 100644 --- a/ext/spl/spl_iterators_arginfo.h +++ b/ext/spl/spl_iterators_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 889a6eed2d62fbb6af168146840189d37765dbaa */ + * Stub hash: ca94fd0da2a2ed5ddd7e0a40b377ff18dd9e2ced */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_EmptyIterator_current, 0, 0, IS_NEVER, 0) ZEND_END_ARG_INFO() @@ -9,7 +9,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_EmptyIterator_key arginfo_class_EmptyIterator_current -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_EmptyIterator_valid, 0, 0, _IS_BOOL, 0) +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_EmptyIterator_valid, 0, 0, IS_FALSE, 0) ZEND_END_ARG_INFO() #define arginfo_class_EmptyIterator_rewind arginfo_class_EmptyIterator_next @@ -19,19 +19,20 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_CallbackFilterIterator___construct, 0, 0, 2 ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) ZEND_END_ARG_INFO() -#define arginfo_class_CallbackFilterIterator_accept arginfo_class_EmptyIterator_valid +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_CallbackFilterIterator_accept, 0, 0, _IS_BOOL, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RecursiveCallbackFilterIterator___construct, 0, 0, 2) ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) ZEND_END_ARG_INFO() -#define arginfo_class_RecursiveCallbackFilterIterator_hasChildren arginfo_class_EmptyIterator_valid +#define arginfo_class_RecursiveCallbackFilterIterator_hasChildren arginfo_class_CallbackFilterIterator_accept ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_RecursiveCallbackFilterIterator_getChildren, 0, 0, RecursiveCallbackFilterIterator, 0) ZEND_END_ARG_INFO() -#define arginfo_class_RecursiveIterator_hasChildren arginfo_class_EmptyIterator_valid +#define arginfo_class_RecursiveIterator_hasChildren arginfo_class_CallbackFilterIterator_accept ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_RecursiveIterator_getChildren, 0, 0, RecursiveIterator, 1) ZEND_END_ARG_INFO() @@ -44,7 +45,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_RecursiveIteratorIterator_rewind arginfo_class_EmptyIterator_next -#define arginfo_class_RecursiveIteratorIterator_valid arginfo_class_EmptyIterator_valid +#define arginfo_class_RecursiveIteratorIterator_valid arginfo_class_CallbackFilterIterator_accept ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_RecursiveIteratorIterator_key, 0, 0, IS_MIXED, 0) ZEND_END_ARG_INFO() @@ -67,7 +68,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_RecursiveIteratorIterator_endIteration arginfo_class_EmptyIterator_next -#define arginfo_class_RecursiveIteratorIterator_callHasChildren arginfo_class_EmptyIterator_valid +#define arginfo_class_RecursiveIteratorIterator_callHasChildren arginfo_class_CallbackFilterIterator_accept #define arginfo_class_RecursiveIteratorIterator_callGetChildren arginfo_class_RecursiveIterator_getChildren @@ -96,7 +97,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_IteratorIterator_rewind arginfo_class_EmptyIterator_next -#define arginfo_class_IteratorIterator_valid arginfo_class_EmptyIterator_valid +#define arginfo_class_IteratorIterator_valid arginfo_class_CallbackFilterIterator_accept #define arginfo_class_IteratorIterator_key arginfo_class_RecursiveIteratorIterator_key @@ -104,7 +105,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_IteratorIterator_next arginfo_class_EmptyIterator_next -#define arginfo_class_FilterIterator_accept arginfo_class_EmptyIterator_valid +#define arginfo_class_FilterIterator_accept arginfo_class_CallbackFilterIterator_accept ZEND_BEGIN_ARG_INFO_EX(arginfo_class_FilterIterator___construct, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0) @@ -118,14 +119,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RecursiveFilterIterator___construct, 0, 0, ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0) ZEND_END_ARG_INFO() -#define arginfo_class_RecursiveFilterIterator_hasChildren arginfo_class_EmptyIterator_valid +#define arginfo_class_RecursiveFilterIterator_hasChildren arginfo_class_CallbackFilterIterator_accept ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_RecursiveFilterIterator_getChildren, 0, 0, RecursiveFilterIterator, 1) ZEND_END_ARG_INFO() #define arginfo_class_ParentIterator___construct arginfo_class_RecursiveFilterIterator___construct -#define arginfo_class_ParentIterator_accept arginfo_class_EmptyIterator_valid +#define arginfo_class_ParentIterator_accept arginfo_class_CallbackFilterIterator_accept ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SeekableIterator_seek, 0, 1, IS_VOID, 0) ZEND_ARG_TYPE_INFO(0, offset, IS_LONG, 0) @@ -139,7 +140,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_LimitIterator_rewind arginfo_class_EmptyIterator_next -#define arginfo_class_LimitIterator_valid arginfo_class_EmptyIterator_valid +#define arginfo_class_LimitIterator_valid arginfo_class_CallbackFilterIterator_accept #define arginfo_class_LimitIterator_next arginfo_class_EmptyIterator_next @@ -156,11 +157,11 @@ ZEND_END_ARG_INFO() #define arginfo_class_CachingIterator_rewind arginfo_class_EmptyIterator_next -#define arginfo_class_CachingIterator_valid arginfo_class_EmptyIterator_valid +#define arginfo_class_CachingIterator_valid arginfo_class_CallbackFilterIterator_accept #define arginfo_class_CachingIterator_next arginfo_class_EmptyIterator_next -#define arginfo_class_CachingIterator_hasNext arginfo_class_EmptyIterator_valid +#define arginfo_class_CachingIterator_hasNext arginfo_class_CallbackFilterIterator_accept ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_CachingIterator___toString, 0, 0, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -198,7 +199,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RecursiveCachingIterator___construct, 0, 0, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "RecursiveCachingIterator::CALL_TOSTRING") ZEND_END_ARG_INFO() -#define arginfo_class_RecursiveCachingIterator_hasChildren arginfo_class_EmptyIterator_valid +#define arginfo_class_RecursiveCachingIterator_hasChildren arginfo_class_CallbackFilterIterator_accept ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_RecursiveCachingIterator_getChildren, 0, 0, RecursiveCachingIterator, 1) ZEND_END_ARG_INFO() @@ -207,7 +208,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_NoRewindIterator_rewind arginfo_class_EmptyIterator_next -#define arginfo_class_NoRewindIterator_valid arginfo_class_EmptyIterator_valid +#define arginfo_class_NoRewindIterator_valid arginfo_class_CallbackFilterIterator_accept #define arginfo_class_NoRewindIterator_key arginfo_class_RecursiveIteratorIterator_key @@ -224,7 +225,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_AppendIterator_rewind arginfo_class_EmptyIterator_next -#define arginfo_class_AppendIterator_valid arginfo_class_EmptyIterator_valid +#define arginfo_class_AppendIterator_valid arginfo_class_CallbackFilterIterator_accept #define arginfo_class_AppendIterator_current arginfo_class_RecursiveIteratorIterator_key @@ -248,7 +249,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RegexIterator___construct, 0, 0, 2) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pregFlags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -#define arginfo_class_RegexIterator_accept arginfo_class_EmptyIterator_valid +#define arginfo_class_RegexIterator_accept arginfo_class_CallbackFilterIterator_accept #define arginfo_class_RegexIterator_getMode arginfo_class_RecursiveIteratorIterator_getDepth @@ -277,9 +278,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RecursiveRegexIterator___construct, 0, 0, 2 ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pregFlags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -#define arginfo_class_RecursiveRegexIterator_accept arginfo_class_EmptyIterator_valid +#define arginfo_class_RecursiveRegexIterator_accept arginfo_class_CallbackFilterIterator_accept -#define arginfo_class_RecursiveRegexIterator_hasChildren arginfo_class_EmptyIterator_valid +#define arginfo_class_RecursiveRegexIterator_hasChildren arginfo_class_CallbackFilterIterator_accept ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_RecursiveRegexIterator_getChildren, 0, 0, RecursiveRegexIterator, 0) ZEND_END_ARG_INFO() diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 3ac375c5cd6b5..4c6cef6cb0604 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -82,7 +82,7 @@ void spl_SplObjectStorage_free_storage(zend_object *object) /* {{{ */ zend_hash_destroy(&intern->storage); } /* }}} */ -static int spl_object_storage_get_hash(zend_hash_key *key, spl_SplObjectStorage *intern, zend_object *obj) { +static zend_result spl_object_storage_get_hash(zend_hash_key *key, spl_SplObjectStorage *intern, zend_object *obj) { if (UNEXPECTED(intern->fptr_get_hash)) { zval param; zval rv; @@ -218,12 +218,12 @@ spl_SplObjectStorageElement *spl_object_storage_attach(spl_SplObjectStorage *int return pelement; } /* }}} */ -static int spl_object_storage_detach(spl_SplObjectStorage *intern, zend_object *obj) /* {{{ */ +static zend_result spl_object_storage_detach(spl_SplObjectStorage *intern, zend_object *obj) /* {{{ */ { if (EXPECTED(!(intern->flags & SOS_OVERRIDDEN_UNSET_DIMENSION))) { return zend_hash_index_del(&intern->storage, obj->handle); } - int ret = FAILURE; + zend_result ret = FAILURE; zend_hash_key key; if (spl_object_storage_get_hash(&key, intern, obj) == FAILURE) { return ret; @@ -544,7 +544,7 @@ PHP_METHOD(SplObjectStorage, offsetGet) ZEND_PARSE_PARAMETERS_END(); if (spl_object_storage_get_hash(&key, intern, obj) == FAILURE) { - return; + RETURN_NULL(); } element = spl_object_storage_get(intern, &key); @@ -723,7 +723,7 @@ PHP_METHOD(SplObjectStorage, getInfo) } if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) { - return; + RETURN_NULL(); } ZVAL_COPY(return_value, &element->inf); } /* }}} */ @@ -740,7 +740,7 @@ PHP_METHOD(SplObjectStorage, setInfo) } if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) { - return; + RETURN_NULL(); } zval_ptr_dtor(&element->inf); ZVAL_COPY(&element->inf, inf); @@ -1008,7 +1008,7 @@ PHP_METHOD(SplObjectStorage, __unserialize) PHP_METHOD(SplObjectStorage, __debugInfo) { if (zend_parse_parameters_none() == FAILURE) { - return; + RETURN_THROWS(); } RETURN_ARR(spl_object_storage_debug_info(Z_OBJ_P(ZEND_THIS))); diff --git a/ext/spl/tests/SplFileObject_key_fgets_and seek.phpt b/ext/spl/tests/SplFileObject_key_fgets_and seek.phpt new file mode 100644 index 0000000000000..eef6c37745d09 --- /dev/null +++ b/ext/spl/tests/SplFileObject_key_fgets_and seek.phpt @@ -0,0 +1,39 @@ +--TEST-- +SplFileObject verify interactions between seeking, getting the key and fgets +--FILE-- +fwrite("Foo $i\n"); +} + +$file->seek(50); + +var_dump( + ['line' => $file->key(), 'contents' => trim($file->fgets())], + ['line' => $file->key(), 'contents' => trim($file->fgets())], + ['line' => $file->key(), 'contents' => trim($file->fgets())], +); + +?> +--EXPECT-- +array(2) { + ["line"]=> + int(50) + ["contents"]=> + string(6) "Foo 50" +} +array(2) { + ["line"]=> + int(51) + ["contents"]=> + string(6) "Foo 51" +} +array(2) { + ["line"]=> + int(52) + ["contents"]=> + string(6) "Foo 52" +} diff --git a/ext/spl/tests/bug65967.phpt b/ext/spl/tests/bug65967.phpt index e3bb6471c6969..abb83ebf1b330 100644 --- a/ext/spl/tests/bug65967.phpt +++ b/ext/spl/tests/bug65967.phpt @@ -10,5 +10,5 @@ gc_collect_cycles(); var_export($objstore); ?> --EXPECT-- -SplObjectStorage::__set_state(array( +\SplObjectStorage::__set_state(array( )) diff --git a/ext/spl/tests/fixedarray_022.phpt b/ext/spl/tests/fixedarray_022.phpt index c1cff1a926582..c45401bfb8384 100644 --- a/ext/spl/tests/fixedarray_022.phpt +++ b/ext/spl/tests/fixedarray_022.phpt @@ -11,7 +11,7 @@ call_user_func(function () { ?> --EXPECTF-- Warning: var_export does not handle circular references in %s on line 5 -SplFixedArray::__set_state(array( +\SplFixedArray::__set_state(array( 0 => NULL, )) object(SplFixedArray)#2 (1) refcount(4){ diff --git a/ext/spl/tests/fixedarray_023.phpt b/ext/spl/tests/fixedarray_023.phpt index 1d60a2ce6d9f7..781685b7891d6 100644 --- a/ext/spl/tests/fixedarray_023.phpt +++ b/ext/spl/tests/fixedarray_023.phpt @@ -18,7 +18,7 @@ call_user_func(function () { Warning: var_export does not handle circular references in %s on line 8 Warning: var_export does not handle circular references in %s on line 8 -SplFixedArray::__set_state(array( +\SplFixedArray::__set_state(array( 0 => NAN, 1 => 0.0, 2 => NULL, diff --git a/ext/spl/tests/gh8273.phpt b/ext/spl/tests/gh8273.phpt new file mode 100644 index 0000000000000..87931541653b6 --- /dev/null +++ b/ext/spl/tests/gh8273.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-8273 (SplFileObject: key() returns wrong value) +--FILE-- +fwrite("line {$i}" . PHP_EOL); +} + +// read from file +$file->rewind(); +while ($file->valid()) { + echo $file->key(), ': ', $file->fgets(); +} +?> +--EXPECT-- +0: line 0 +1: line 1 +2: line 2 +3: line 3 +4: line 4 diff --git a/ext/spl/tests/gh8366.phpt b/ext/spl/tests/gh8366.phpt new file mode 100644 index 0000000000000..1da5360cc96b5 --- /dev/null +++ b/ext/spl/tests/gh8366.phpt @@ -0,0 +1,9 @@ +--TEST-- +Bug GH-8366 (ArrayIterator may leak when calling __construct()) +--FILE-- +__construct([]); +?> +--EXPECT-- diff --git a/ext/spl/tests/iterator_009.phpt b/ext/spl/tests/iterator_009.phpt index bd8eb99c4d0db..6fa9c440e1bc8 100644 --- a/ext/spl/tests/iterator_009.phpt +++ b/ext/spl/tests/iterator_009.phpt @@ -10,7 +10,7 @@ class EmptyIteratorEx extends EmptyIterator echo __METHOD__ . "\n"; parent::rewind(); } - function valid(): bool + function valid(): false { echo __METHOD__ . "\n"; return parent::valid(); diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 55ebf911e94d4..f06d373c56f09 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -76,7 +76,7 @@ static void php_sqlite3_error(php_sqlite3_db_object *db_obj, char *format, ...) PHP_INI_BEGIN() STD_PHP_INI_ENTRY("sqlite3.extension_dir", NULL, PHP_INI_SYSTEM, OnUpdateString, extension_dir, zend_sqlite3_globals, sqlite3_globals) #if SQLITE_VERSION_NUMBER >= 3026000 - STD_PHP_INI_BOOLEAN("sqlite3.defensive", "1", PHP_INI_SYSTEM, OnUpdateBool, dbconfig_defensive, zend_sqlite3_globals, sqlite3_globals) + STD_PHP_INI_BOOLEAN("sqlite3.defensive", "1", PHP_INI_USER, OnUpdateBool, dbconfig_defensive, zend_sqlite3_globals, sqlite3_globals) #endif PHP_INI_END() /* }}} */ diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 8239b6d14dba3..540d88722c15c 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -464,8 +464,7 @@ function forward_static_call(callable $callback, mixed ...$args): mixed {} function forward_static_call_array(callable $callback, array $args): mixed {} -/** @return false|null */ -function register_shutdown_function(callable $callback, mixed ...$args): ?bool {} +function register_shutdown_function(callable $callback, mixed ...$args): void {} /** @refcount 1 */ function highlight_file(string $filename, bool $return = false): string|bool {} @@ -1087,11 +1086,8 @@ function exec(string $command, &$output = null, &$result_code = null): string|fa */ function system(string $command, &$result_code = null): string|false {} -/** - * @param int $result_code - * @return false|null - */ -function passthru(string $command, &$result_code = null): ?bool {} +/** @param int $result_code */ +function passthru(string $command, &$result_code = null): false|null {} /** @refcount 1 */ function escapeshellcmd(string $command): string {} diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index b912e503bbe44..8b573cbe2dff3 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: bbcebdb57572133d5f442f220f1e98a1320ed0f6 */ + * Stub hash: b1c51fabe59bba6706500365f3eb7d9676d625f6 */ 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) @@ -459,7 +459,7 @@ ZEND_END_ARG_INFO() #define arginfo_forward_static_call_array arginfo_call_user_func_array -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_register_shutdown_function, 0, 1, _IS_BOOL, 1) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_register_shutdown_function, 0, 1, IS_VOID, 0) ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) ZEND_ARG_VARIADIC_TYPE_INFO(0, args, IS_MIXED, 0) ZEND_END_ARG_INFO() @@ -1151,7 +1151,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_system, 0, 1, MAY_BE_STRING|MAY_ ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, result_code, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_passthru, 0, 1, _IS_BOOL, 1) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_passthru, 0, 1, IS_FALSE, 1) ZEND_ARG_TYPE_INFO(0, command, IS_STRING, 0) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, result_code, "null") ZEND_END_ARG_INFO() diff --git a/ext/standard/dir.c b/ext/standard/dir.c index 8f2ddf742b679..8681c3113193b 100644 --- a/ext/standard/dir.c +++ b/ext/standard/dir.c @@ -505,7 +505,7 @@ PHP_FUNCTION(glob) * able to filter directories out. */ if (flags & GLOB_ONLYDIR) { - zend_stat_t s; + zend_stat_t s = {0}; if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) { continue; diff --git a/ext/standard/dns.c b/ext/standard/dns.c index 01d97ce0c4e7b..ba147e353e3ef 100644 --- a/ext/standard/dns.c +++ b/ext/standard/dns.c @@ -384,7 +384,7 @@ static void _php_dns_free_res(struct __res_state *res) { /* {{{ */ PHP_FUNCTION(dns_check_record) { HEADER *hp; - querybuf answer; + querybuf answer = {0}; char *hostname; size_t hostname_len; zend_string *rectype = NULL; @@ -470,7 +470,7 @@ static u_char *php_parserr(u_char *cp, u_char *end, querybuf *answer, int type_t long n, i; u_short s; u_char *tp, *p; - char name[MAXHOSTNAMELEN]; + char name[MAXHOSTNAMELEN] = {0}; int have_v6_break = 0, in_v6_break = 0; ZVAL_UNDEF(subarray); @@ -839,7 +839,7 @@ PHP_FUNCTION(dns_get_record) struct __res_state *handle = &state; #endif HEADER *hp; - querybuf answer; + querybuf answer = {0}; u_char *cp = NULL, *end = NULL; int n, qd, an, ns = 0, ar = 0; int type, first_query = 1, store_results = 1; @@ -1069,8 +1069,8 @@ PHP_FUNCTION(dns_get_mx) zval *mx_list, *weight_list = NULL; int count, qdc; u_short type, weight; - querybuf answer; - char buf[MAXHOSTNAMELEN]; + querybuf answer = {0}; + char buf[MAXHOSTNAMELEN] = {0}; HEADER *hp; u_char *cp, *end; int i; diff --git a/ext/standard/file.h b/ext/standard/file.h index 7fe9c4738faa6..24de0dcf80e71 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -53,11 +53,11 @@ PHPAPI ssize_t php_fputcsv(php_stream *stream, zval *fields, char delimiter, cha #define META_DEF_BUFSIZE 8192 -#define PHP_FILE_USE_INCLUDE_PATH 1 -#define PHP_FILE_IGNORE_NEW_LINES 2 -#define PHP_FILE_SKIP_EMPTY_LINES 4 -#define PHP_FILE_APPEND 8 -#define PHP_FILE_NO_DEFAULT_CONTEXT 16 +#define PHP_FILE_USE_INCLUDE_PATH (1 << 0) +#define PHP_FILE_IGNORE_NEW_LINES (1 << 1) +#define PHP_FILE_SKIP_EMPTY_LINES (1 << 2) +#define PHP_FILE_APPEND (1 << 3) +#define PHP_FILE_NO_DEFAULT_CONTEXT (1 << 4) typedef enum _php_meta_tags_token { TOK_EOF = 0, diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c index a11ecf09f8f13..aaf7e730d0a54 100644 --- a/ext/standard/filestat.c +++ b/ext/standard/filestat.c @@ -740,8 +740,8 @@ PHP_FUNCTION(clearstatcache) /* {{{ php_stat */ PHPAPI void php_stat(zend_string *filename, int type, zval *return_value) { - zend_stat_t *stat_sb; - php_stream_statbuf ssb; + zend_stat_t *stat_sb = {0}; + php_stream_statbuf ssb = {0}; int flags = 0, rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */ const char *local = NULL; php_stream_wrapper *wrapper = NULL; diff --git a/ext/standard/iptc.c b/ext/standard/iptc.c index ce0f172426a3c..e4dd38637570a 100644 --- a/ext/standard/iptc.c +++ b/ext/standard/iptc.c @@ -178,7 +178,7 @@ PHP_FUNCTION(iptcembed) size_t inx; zend_string *spoolbuf = NULL; unsigned char *poi = NULL; - zend_stat_t sb; + zend_stat_t sb = {0}; bool written = 0; ZEND_PARSE_PARAMETERS_START(2, 3) diff --git a/ext/standard/link.c b/ext/standard/link.c index 2f29b5bcc0288..c63f7ff268343 100644 --- a/ext/standard/link.c +++ b/ext/standard/link.c @@ -94,7 +94,7 @@ PHP_FUNCTION(linkinfo) char *link; char *dirname; size_t link_len; - zend_stat_t sb; + zend_stat_t sb = {0}; int ret; ZEND_PARSE_PARAMETERS_START(1, 1) diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h index d0c40817fa33f..b87601a1241ed 100644 --- a/ext/standard/php_string.h +++ b/ext/standard/php_string.h @@ -33,7 +33,7 @@ PHP_MINIT_FUNCTION(string_intrin); strnatcmp_ex(a, strlen(a), b, strlen(b), 0) #define strnatcasecmp(a, b) \ strnatcmp_ex(a, strlen(a), b, strlen(b), 1) -PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len, int fold_case); +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_strtoupper(char *s, size_t len); PHPAPI char *php_strtolower(char *s, size_t len); diff --git a/ext/standard/string.c b/ext/standard/string.c index 59f633fd18587..699bccbae6af9 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -89,8 +89,6 @@ void register_string_constants(INIT_FUNC_ARGS) } /* }}} */ -int php_tag_find(char *tag, size_t len, const char *set); - /* this is read-only, so it's ok */ ZEND_SET_ALIGNED(16, static const char hexconvtab[]) = "0123456789abcdef"; @@ -695,11 +693,11 @@ PHP_FUNCTION(strcoll) * it needs to be incrementing. * Returns: FAILURE/SUCCESS whether the input was correct (i.e. no range errors) */ -static inline int php_charmask(const unsigned char *input, size_t len, char *mask) +static inline zend_result php_charmask(const unsigned char *input, size_t len, char *mask) { const unsigned char *end; unsigned char c; - int result = SUCCESS; + zend_result result = SUCCESS; memset(mask, 0, 256); for (end = input+len; input < end; input++) { @@ -1144,7 +1142,7 @@ PHP_FUNCTION(explode) PHPAPI void php_implode(const zend_string *glue, HashTable *pieces, zval *return_value) { zval *tmp; - int numelems; + uint32_t numelems; zend_string *str; char *cptr; size_t len = 0; @@ -1606,7 +1604,7 @@ PHP_FUNCTION(pathinfo) zval tmp; char *path, *dirname; size_t path_len; - int have_basename; + bool have_basename; zend_long opt = PHP_PATHINFO_ALL; zend_string *ret = NULL; @@ -1744,16 +1742,14 @@ PHP_FUNCTION(stristr) found = php_stristr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(haystack), ZSTR_LEN(needle)); - if (found) { - found_offset = found - ZSTR_VAL(haystack); - if (part) { - RETVAL_STRINGL(ZSTR_VAL(haystack), found_offset); - } else { - RETVAL_STRINGL(ZSTR_VAL(haystack) + found_offset, ZSTR_LEN(haystack) - found_offset); - } - } else { - RETVAL_FALSE; + if (UNEXPECTED(!found)) { + RETURN_FALSE; + } + found_offset = found - ZSTR_VAL(haystack); + if (part) { + RETURN_STRINGL(ZSTR_VAL(haystack), found_offset); } + RETURN_STRINGL(ZSTR_VAL(haystack) + found_offset, ZSTR_LEN(haystack) - found_offset); } /* }}} */ @@ -1774,15 +1770,14 @@ PHP_FUNCTION(strstr) found = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); - if (found) { - found_offset = found - ZSTR_VAL(haystack); - if (part) { - RETURN_STRINGL(ZSTR_VAL(haystack), found_offset); - } else { - RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset); - } + if (UNEXPECTED(!found)) { + RETURN_FALSE; } - RETURN_FALSE; + found_offset = found - ZSTR_VAL(haystack); + if (part) { + RETURN_STRINGL(ZSTR_VAL(haystack), found_offset); + } + RETURN_STRINGL(ZSTR_VAL(haystack) + found_offset, ZSTR_LEN(haystack) - found_offset); } /* }}} */ @@ -1863,11 +1858,10 @@ PHP_FUNCTION(strpos) ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); - if (found) { - RETURN_LONG(found - ZSTR_VAL(haystack)); - } else { + if (UNEXPECTED(!found)) { RETURN_FALSE; } + RETURN_LONG(found - ZSTR_VAL(haystack)); } /* }}} */ @@ -1896,11 +1890,10 @@ PHP_FUNCTION(stripos) found = (char*)php_memnistr(ZSTR_VAL(haystack) + offset, ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); - if (found) { - RETVAL_LONG(found - ZSTR_VAL(haystack)); - } else { - RETVAL_FALSE; + if (UNEXPECTED(!found)) { + RETURN_FALSE; } + RETURN_LONG(found - ZSTR_VAL(haystack)); } /* }}} */ @@ -1940,11 +1933,12 @@ PHP_FUNCTION(strrpos) } } - if ((found = zend_memnrstr(p, ZSTR_VAL(needle), ZSTR_LEN(needle), e))) { - RETURN_LONG(found - ZSTR_VAL(haystack)); - } + found = zend_memnrstr(p, ZSTR_VAL(needle), ZSTR_LEN(needle), e); - RETURN_FALSE; + if (UNEXPECTED(!found)) { + RETURN_FALSE; + } + RETURN_LONG(found - ZSTR_VAL(haystack)); } /* }}} */ @@ -2043,12 +2037,11 @@ PHP_FUNCTION(strrchr) ZEND_PARSE_PARAMETERS_END(); found = zend_memrchr(ZSTR_VAL(haystack), *ZSTR_VAL(needle), ZSTR_LEN(haystack)); - if (found) { - found_offset = found - ZSTR_VAL(haystack); - RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset); - } else { + if (UNEXPECTED(!found)) { RETURN_FALSE; } + found_offset = found - ZSTR_VAL(haystack); + RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset); } /* }}} */ @@ -2782,7 +2775,7 @@ static void php_strtr_array(zval *return_value, zend_string *input, HashTable *p zend_ulong num_key; zend_string *str_key; size_t len, pos, old_pos; - int num_keys = 0; + bool has_num_keys = false; size_t minlen = 128*1024; size_t maxlen = 0; HashTable str_hash; @@ -2799,10 +2792,10 @@ static void php_strtr_array(zval *return_value, zend_string *input, HashTable *p /* check if original array has numeric keys */ ZEND_HASH_FOREACH_STR_KEY(pats, str_key) { if (UNEXPECTED(!str_key)) { - num_keys = 1; + has_num_keys = true; } else { len = ZSTR_LEN(str_key); - if (UNEXPECTED(len < 1)) { + if (UNEXPECTED(len == 0)) { php_error_docref(NULL, E_WARNING, "Ignoring replacement of empty string"); continue; } else if (UNEXPECTED(len > slen)) { @@ -2821,7 +2814,7 @@ static void php_strtr_array(zval *return_value, zend_string *input, HashTable *p } } ZEND_HASH_FOREACH_END(); - if (UNEXPECTED(num_keys)) { + if (UNEXPECTED(has_num_keys)) { zend_string *key_used; /* we have to rebuild HashTable with numeric keys */ zend_hash_init(&str_hash, zend_hash_num_elements(pats), NULL, NULL, 0); @@ -2961,7 +2954,7 @@ static zend_always_inline zend_long count_chars(const char *p, zend_long length, /* }}} */ /* {{{ php_char_to_str_ex */ -static zend_string* php_char_to_str_ex(zend_string *str, char from, char *to, size_t to_len, int case_sensitivity, zend_long *replace_count) +static zend_string* php_char_to_str_ex(zend_string *str, char from, char *to, size_t to_len, bool case_sensitivity, zend_long *replace_count) { zend_string *result; size_t char_count; @@ -3319,7 +3312,7 @@ PHP_FUNCTION(strtr) ZSTR_VAL(str_key)[0], ZSTR_VAL(replace), ZSTR_LEN(replace), - 1, + /* case_sensitive */ true, NULL)); } else { zend_long dummy; @@ -3455,7 +3448,7 @@ PHP_FUNCTION(similar_text) { zend_string *t1, *t2; zval *percent = NULL; - int ac = ZEND_NUM_ARGS(); + bool compute_percentage = ZEND_NUM_ARGS() >= 3; size_t sim; ZEND_PARSE_PARAMETERS_START(2, 3) @@ -3466,7 +3459,7 @@ PHP_FUNCTION(similar_text) ZEND_PARSE_PARAMETERS_END(); if (ZSTR_LEN(t1) + ZSTR_LEN(t2) == 0) { - if (ac > 2) { + if (compute_percentage) { ZEND_TRY_ASSIGN_REF_DOUBLE(percent, 0); } @@ -3475,7 +3468,7 @@ PHP_FUNCTION(similar_text) sim = php_similar_char(ZSTR_VAL(t1), ZSTR_LEN(t1), ZSTR_VAL(t2), ZSTR_LEN(t2)); - if (ac > 2) { + if (compute_percentage) { ZEND_TRY_ASSIGN_REF_DOUBLE(percent, sim * 200.0 / (ZSTR_LEN(t1) + ZSTR_LEN(t2))); } @@ -3893,8 +3886,7 @@ static zend_always_inline quad_word aarch64_contains_slash_chars(uint8x16_t x) { static zend_always_inline char *aarch64_add_slashes(quad_word res, const char *source, char *target) { - int i = 0; - for (; i < 16; i++) { + for (int i = 0; i < 16; i++) { char s = source[i]; if (res.mem[i] == 0) *target++ = s; @@ -4156,7 +4148,7 @@ PHPAPI void php_stripslashes(zend_string *str) /* {{{ php_str_replace_in_subject */ static zend_long php_str_replace_in_subject( zend_string *search_str, HashTable *search_ht, zend_string *replace_str, HashTable *replace_ht, - zend_string *subject_str, zval *result, int case_sensitivity + zend_string *subject_str, zval *result, bool case_sensitivity ) { zval *search_entry; zend_string *tmp_result; @@ -4317,7 +4309,7 @@ static zend_long php_str_replace_in_subject( /* }}} */ /* {{{ php_str_replace_common */ -static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensitivity) +static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, bool case_sensitivity) { zend_string *search_str; HashTable *search_ht; @@ -4832,10 +4824,11 @@ PHP_FUNCTION(parse_str) * 0 start tag * 1 first non-whitespace char seen */ -int php_tag_find(char *tag, size_t len, const char *set) { +static bool php_tag_find(char *tag, size_t len, const char *set) { char c, *n; const char *t; - int state=0, done=0; + int state = 0; + bool done = 0; char *norm; if (len == 0) { @@ -5387,7 +5380,7 @@ PHP_FUNCTION(count_chars) /* }}} */ /* {{{ php_strnatcmp */ -static void php_strnatcmp(INTERNAL_FUNCTION_PARAMETERS, int fold_case) +static void php_strnatcmp(INTERNAL_FUNCTION_PARAMETERS, bool is_case_insensitive) { zend_string *s1, *s2; @@ -5398,7 +5391,7 @@ static void php_strnatcmp(INTERNAL_FUNCTION_PARAMETERS, int fold_case) RETURN_LONG(strnatcmp_ex(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), - fold_case)); + is_case_insensitive)); } /* }}} */ @@ -5409,11 +5402,18 @@ PHP_FUNCTION(strnatcmp) } /* }}} */ +/* {{{ Returns the result of case-insensitive string comparison using 'natural' algorithm */ +PHP_FUNCTION(strnatcasecmp) +{ + php_strnatcmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + /* {{{ Returns numeric formatting information based on the current locale */ PHP_FUNCTION(localeconv) { zval grouping, mon_grouping; - int len, i; + size_t len, i; ZEND_PARSE_PARAMETERS_NONE(); @@ -5427,14 +5427,14 @@ PHP_FUNCTION(localeconv) localeconv_r( &currlocdata ); /* Grab the grouping data out of the array */ - len = (int)strlen(currlocdata.grouping); + len = strlen(currlocdata.grouping); for (i = 0; i < len; i++) { add_index_long(&grouping, i, currlocdata.grouping[i]); } /* Grab the monetary grouping data out of the array */ - len = (int)strlen(currlocdata.mon_grouping); + len = strlen(currlocdata.mon_grouping); for (i = 0; i < len; i++) { add_index_long(&mon_grouping, i, currlocdata.mon_grouping[i]); @@ -5463,13 +5463,6 @@ PHP_FUNCTION(localeconv) } /* }}} */ -/* {{{ Returns the result of case-insensitive string comparison using 'natural' algorithm */ -PHP_FUNCTION(strnatcasecmp) -{ - php_strnatcmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ - /* {{{ Returns the number of times a substring occurs in the string */ PHP_FUNCTION(substr_count) { @@ -5741,7 +5734,7 @@ PHP_FUNCTION(str_rot13) } /* }}} */ -static void php_string_shuffle(char *str, zend_long len) /* {{{ */ +static void php_string_shuffle(char *str, size_t len) /* {{{ */ { zend_long n_elems, rnd_idx, n_left; char temp; @@ -5777,7 +5770,7 @@ PHP_FUNCTION(str_shuffle) RETVAL_STRINGL(ZSTR_VAL(arg), ZSTR_LEN(arg)); if (Z_STRLEN_P(return_value) > 1) { - php_string_shuffle(Z_STRVAL_P(return_value), (zend_long) Z_STRLEN_P(return_value)); + php_string_shuffle(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value)); } } /* }}} */ diff --git a/ext/standard/strnatcmp.c b/ext/standard/strnatcmp.c index 8cbc0db1c3f08..3c3f5a99232ff 100644 --- a/ext/standard/strnatcmp.c +++ b/ext/standard/strnatcmp.c @@ -85,7 +85,7 @@ compare_left(char const **a, char const *aend, char const **b, char const *bend) /* }}} */ /* {{{ strnatcmp_ex */ -PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len, int fold_case) +PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len, bool is_case_insensitive) { unsigned char ca, cb; char const *ap, *bp; @@ -146,7 +146,7 @@ PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len } } - if (fold_case) { + if (is_case_insensitive) { ca = toupper((int)(unsigned char)ca); cb = toupper((int)(unsigned char)cb); } diff --git a/ext/standard/tests/array/007.phpt b/ext/standard/tests/array/007.phpt index a1c984a18be14..fcb6326721bb7 100644 --- a/ext/standard/tests/array/007.phpt +++ b/ext/standard/tests/array/007.phpt @@ -248,54 +248,54 @@ array(9) { -=-=-=-=-=-=-=-=- New functionality from 5.0.0 -=-=-=-=-=-=-=- $a=array ( '0.1' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 12, 'public_member' => 12, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 23, 'public_member' => 23, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), ); $b=array ( '0.2' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 22, 'public_member' => 22, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 3, 'public_member' => 3, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), @@ -326,54 +326,54 @@ array(3) { } $a=array ( '0.1' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 12, 'public_member' => 12, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 23, 'public_member' => 23, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), ); $b=array ( '0.2' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 22, 'public_member' => 22, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 3, 'public_member' => 3, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), @@ -404,54 +404,54 @@ array(3) { } $a=array ( '0.1' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 12, 'public_member' => 12, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 23, 'public_member' => 23, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), ); $b=array ( '0.2' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 22, 'public_member' => 22, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 3, 'public_member' => 3, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), @@ -475,54 +475,54 @@ array(2) { } $a=array ( '0.1' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 12, 'public_member' => 12, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 23, 'public_member' => 23, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), ); $b=array ( '0.2' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 22, 'public_member' => 22, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 3, 'public_member' => 3, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), diff --git a/ext/standard/tests/array/array_intersect_1.phpt b/ext/standard/tests/array/array_intersect_1.phpt index 518dfd392f46f..49890b7fee1f3 100644 --- a/ext/standard/tests/array/array_intersect_1.phpt +++ b/ext/standard/tests/array/array_intersect_1.phpt @@ -66,54 +66,54 @@ echo "end ------------ array_uintersect_uassoc() with method --------\n"; begin ------------ array_uintersect() --------------------------- $a=array ( '0.1' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 12, 'public_member' => 12, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 23, 'public_member' => 23, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), ); $b=array ( '0.2' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 22, 'public_member' => 22, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 3, 'public_member' => 3, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), @@ -146,54 +146,54 @@ end ------------ array_uintersect() --------------------------- begin ------------ array_uintersect_assoc() --------------------- $a=array ( '0.1' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 12, 'public_member' => 12, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 23, 'public_member' => 23, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), ); $b=array ( '0.2' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 22, 'public_member' => 22, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 3, 'public_member' => 3, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), @@ -219,54 +219,54 @@ end ------------ array_uintersect_assoc() --------------------- begin ------------ array_uintersect_uassoc() with ordinary func - $a=array ( '0.1' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 12, 'public_member' => 12, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 23, 'public_member' => 23, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), ); $b=array ( '0.2' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 22, 'public_member' => 22, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 3, 'public_member' => 3, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), @@ -292,54 +292,54 @@ end ------------ array_uintersect_uassoc() with ordinary func - begin ------------ array_uintersect_uassoc() with method -------- $a=array ( '0.1' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 12, 'public_member' => 12, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 23, 'public_member' => 23, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), ); $b=array ( '0.2' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 9, 'public_member' => 9, )), '0.5' => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 22, 'public_member' => 22, )), 0 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 3, 'public_member' => 3, )), 1 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => 4, 'public_member' => 4, )), 2 => - cr::__set_state(array( + \cr::__set_state(array( 'priv_member' => -15, 'public_member' => -15, )), diff --git a/ext/standard/tests/array/var_export3.phpt b/ext/standard/tests/array/var_export3.phpt index e7d3c851f27c2..723cc514f149e 100644 --- a/ext/standard/tests/array/var_export3.phpt +++ b/ext/standard/tests/array/var_export3.phpt @@ -18,7 +18,7 @@ $kake = new kake; var_export($kake); ?> --EXPECT-- -kake::__set_state(array( +\kake::__set_state(array( 'mann' => 42, 'kvinne' => 43, )) diff --git a/ext/standard/tests/file/stream_copy_to_stream.phpt b/ext/standard/tests/file/stream_copy_to_stream.phpt index 1f34b843347ca..c3b00b9ee0027 100644 --- a/ext/standard/tests/file/stream_copy_to_stream.phpt +++ b/ext/standard/tests/file/stream_copy_to_stream.phpt @@ -12,6 +12,8 @@ stream_filter_append($src, "string.rot13", STREAM_FILTER_READ); $dest = fopen($new_file, 'w'); var_dump(stream_copy_to_stream($src, $dest, 0)); +var_dump(ftell($src)); +var_dump(ftell($dest)); fclose($src); fclose($dest); var_dump(file_get_contents($new_file)); @@ -24,6 +26,8 @@ stream_filter_append($src, "string.rot13", STREAM_FILTER_READ); $dest = fopen($new_file, 'w'); var_dump(stream_copy_to_stream($src, $dest, -1)); +var_dump(ftell($src)); +var_dump(ftell($dest)); fclose($src); fclose($dest); if (WIN) { var_dump(str_replace("\r\n","\n", file_get_contents($new_file))); @@ -39,6 +43,8 @@ stream_filter_append($src, "string.rot13", STREAM_FILTER_READ); $dest = fopen($new_file, 'w'); var_dump(stream_copy_to_stream($src, $dest)); +var_dump(ftell($src)); +var_dump(ftell($dest)); fclose($src); fclose($dest); if (WIN) { @@ -54,6 +60,8 @@ $src = fopen($initial_file, 'r'); $dest = fopen($new_file, 'w'); var_dump(stream_copy_to_stream($src, $dest)); +var_dump(ftell($src)); +var_dump(ftell($dest)); fclose($src); fclose($dest); if (WIN) { @@ -69,6 +77,8 @@ $src = fopen($initial_file, 'r'); $dest = fopen($new_file, 'w'); var_dump(stream_copy_to_stream($src, $dest, 1000000)); +var_dump(ftell($src)); +var_dump(ftell($dest)); fclose($src); fclose($dest); if (WIN) { @@ -85,6 +95,8 @@ $src = fopen($initial_file, 'r'); $dest = fopen($new_file, 'w'); var_dump(stream_copy_to_stream($src, $dest, 10)); +var_dump(ftell($src)); +var_dump(ftell($dest)); fclose($src); fclose($dest); if (WIN) { @@ -100,6 +112,8 @@ $src = fopen($initial_file, 'r'); $dest = fopen($new_file, 'w'); var_dump(stream_copy_to_stream($src, $dest, -1)); +var_dump(ftell($src)); +var_dump(ftell($dest)); fclose($src); fclose($dest); if (WIN) { @@ -113,8 +127,12 @@ echo "Done\n"; ?> --EXPECTF-- int(0) +int(0) +int(0) string(0) "" int(%d) +int(134) +int(134) string(134) "Nabgure qnl Jura gur cnvaf bs yvsr jba'g one zl jnl V'yy oernx gurfr punvaf @@ -122,6 +140,8 @@ Gung ubyq zr qbja V'yy grne lbh qbja vagb zl cevingr uryy " int(%d) +int(134) +int(134) string(134) "Nabgure qnl Jura gur cnvaf bs yvsr jba'g one zl jnl V'yy oernx gurfr punvaf @@ -129,6 +149,8 @@ Gung ubyq zr qbja V'yy grne lbh qbja vagb zl cevingr uryy " int(%d) +int(134) +int(134) string(134) "Another day When the pains of life won't bar my way I'll break these chains @@ -136,6 +158,8 @@ That hold me down I'll tear you down into my private hell " int(%d) +int(134) +int(134) string(134) "Another day When the pains of life won't bar my way I'll break these chains @@ -143,8 +167,12 @@ That hold me down I'll tear you down into my private hell " int(%d) +int(10) +int(10) string(10) "Another da" int(%d) +int(134) +int(134) string(134) "Another day When the pains of life won't bar my way I'll break these chains diff --git a/ext/standard/tests/file/stream_copy_to_stream_interleaved.phpt b/ext/standard/tests/file/stream_copy_to_stream_interleaved.phpt new file mode 100644 index 0000000000000..dc0839cd5d1f0 --- /dev/null +++ b/ext/standard/tests/file/stream_copy_to_stream_interleaved.phpt @@ -0,0 +1,48 @@ +--TEST-- +stream_copy_to_stream() tests with interleaved read/write calls +--FILE-- + +--EXPECTF-- +string(10) "Another da" +int(3) +int(10) +int(20) +int(13) +string(10) " pains of " +int(3) +int(10) +int(40) +int(26) +string(26) "fooy +When thebarlife won't" +Done diff --git a/ext/standard/tests/file/windows_mb_path/bug54028.phpt b/ext/standard/tests/file/windows_mb_path/bug54028.phpt index 6f3e6dab5141e..61913a1a7218f 100644 --- a/ext/standard/tests/file/windows_mb_path/bug54028.phpt +++ b/ext/standard/tests/file/windows_mb_path/bug54028.phpt @@ -1,12 +1,14 @@ --TEST-- Bug #54028 Directory::read() cannot handle non-unicode chars properly +--EXTENSIONS-- +mbstring --SKIPIF-- --FILE-- 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 461ed5d002592..d4821b23be0e4 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 @@ -25,9 +25,9 @@ include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "���զh�r�`���|"; // BIG5 string $prefix = create_data("dir_big5", $item . "5", 950); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}5"; +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}5"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 01952217784ff..5076768c955b3 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 @@ -22,9 +22,9 @@ include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('big5', 'utf-8', "���զh�r�`���|"); // BIG5 string $prefix = create_data("dir_big5", $item . "5"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}5"; +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}5"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 c792988ba503a..ad09ff1967caf 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 @@ -21,10 +21,10 @@ dir_cp1250 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "šđčćž_ŠĐČĆŽ"; // cp1250 specific chars -$prefix = create_data("dir_cp1250", "${item}42"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp1250", "{$item}42"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 9e1279a5cdef4..61e1b4eaa598b 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 @@ -21,8 +21,8 @@ dir_cp1250 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "šđčćž_ŠĐČĆŽ"; // cp1250 specific chars -$prefix = create_data("dir_cp1250", "${item}42}"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp1250", "{$item}42}"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 0eb0f9b09768a..8992a847eb507 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 @@ -21,10 +21,10 @@ dir_cp1250 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "Árvíztűrő tükörfúrógép"; // cp1250 specific chars -$prefix = create_data("dir_cp1250", "${item}42"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp1250", "{$item}42"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 0c56ea4b48f35..392c486a767f7 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 @@ -21,8 +21,8 @@ dir_cp1250 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "Árvíztűrő tükörfúrógép"; // cp1250 specific chars -$prefix = create_data("dir_cp1250", "${item}42}"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp1250", "{$item}42}"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 a1f05c80f6d7a..0ea67f575e563 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 @@ -27,7 +27,7 @@ $item = " $prefix = create_data("dir_cp1251", $item . "3", 1251); $path = $prefix . DIRECTORY_SEPARATOR . $item . "3"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($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 742af59480610..f65b38eafdad0 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 @@ -25,7 +25,7 @@ include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "������"; // cp1251 string $prefix = create_data("file_cp1251", $item . "7", 1251); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}7"; +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}7"; $f = fopen($fn, 'w'); if ($f) { 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 e7e274c4e6d7d..6e53ff48c99d9 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 @@ -24,7 +24,7 @@ $item = iconv('cp1251', 'utf-8', " $prefix = create_data("dir_cp1251", $item . "3"); $path = $prefix . DIRECTORY_SEPARATOR . $item . "3"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 31e611303edee..95b75985c6188 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 @@ -22,7 +22,7 @@ include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('cp1251', 'utf-8', "������"); // cp1251 string $prefix = create_data("file_cp1251", $item . "7"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}7"; +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}7"; $f = fopen($fn, 'w'); if ($f) { 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 51d2b6d8c1893..8b800ed3bdeab 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 @@ -1,5 +1,7 @@ --TEST-- Test fopen() for reading CP1251 with zend.multibyte +--EXTENSIONS-- +mbstring --INI-- zend.multibyte=1 zend.script_encoding=cp1251 @@ -9,7 +11,7 @@ include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; skip_if_not_win(); if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); -skip_if_no_required_exts("mbstring"); +skip_if_no_required_exts(); ?> --CONFLICTS-- 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 ca11bfff560dc..31db615f4d2c8 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 @@ -1,5 +1,7 @@ --TEST-- Test mkdir/rmdir CP1251 with zend.multibyte +--EXTENSIONS-- +mbstring --INI-- zend.multibyte=1 zend.script_encoding=cp1251 @@ -9,7 +11,7 @@ include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; skip_if_not_win(); if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); -skip_if_no_required_exts("mbstring"); +skip_if_no_required_exts(); ?> --CONFLICTS-- @@ -25,9 +27,9 @@ include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "������"; // cp1251 string $prefix = create_data("dir_cp1251", $item . "3"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}3"; +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}3"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 eb52b78835696..d6075da559c92 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 @@ -1,5 +1,7 @@ --TEST-- Test fopen() for write CP1251 with zend.multibyte +--EXTENSIONS-- +mbstring --INI-- zend.multibyte=1 zend.script_encoding=cp1251 @@ -9,7 +11,7 @@ include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; skip_if_not_win(); if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); -skip_if_no_required_exts("mbstring"); +skip_if_no_required_exts(); ?> --CONFLICTS-- 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 2465145758110..5f5a6a78385a7 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 @@ -21,10 +21,10 @@ dir_cp1252 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('cp1252', 'utf-8', "tsch��"); // cp1252 string -$prefix = create_data("dir_cp1252", "${item}3"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}3"; +$prefix = create_data("dir_cp1252", "{$item}3"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}3"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 9185503abea45..04baef95b0252 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 @@ -21,8 +21,8 @@ dir_cp1252 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('cp1252', 'utf-8', "tsch��"); // cp1252 string -$prefix = create_data("dir_cp1252", "${item}3"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}7"; +$prefix = create_data("dir_cp1252", "{$item}3"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}7"; $f = fopen($fn, 'w'); if ($f) { 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 98a419efc576b..a3359f686c1b3 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 @@ -21,10 +21,10 @@ dir2_cp1252 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('cp1252', 'utf-8', "Vol��ao"); // cp1252 string -$prefix = create_data("dir2_cp1252", "${item}3"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}3"; +$prefix = create_data("dir2_cp1252", "{$item}3"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}3"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 fb98361c17ab9..42212d027126c 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 @@ -21,8 +21,8 @@ dir2_cp1252 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('cp1252', 'utf-8', "Vol��ao"); // cp1252 string -$prefix = create_data("dir2_cp1252", "${item}3"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}7"; +$prefix = create_data("dir2_cp1252", "{$item}3"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}7"; $f = fopen($fn, 'w'); if ($f) { 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 aa08aa24eaac4..9ffdb11b2b83e 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 @@ -24,10 +24,10 @@ default_charset=cp1253 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "�������� �������"; -$prefix = create_data("dir_cp1253", "${item}42", 1253); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp1253", "{$item}42", 1253); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($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 46ce9b5fef305..642e4aaabd194 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 @@ -24,8 +24,8 @@ internal_encoding=cp1253 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "�������� �������"; -$prefix = create_data("dir_cp1253", "${item}42}", 1253); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp1253", "{$item}42}", 1253); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 70a548f6685b6..c84e9c95b3694 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 @@ -21,10 +21,10 @@ dir_cp1253 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "διαδρομή δοκιμής"; -$prefix = create_data("dir_cp1253", "${item}42"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp1253", "{$item}42"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 ef15325feaf75..c0723d18b1228 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 @@ -21,8 +21,8 @@ dir_cp1253 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "διαδρομή δοκιμής"; -$prefix = create_data("dir_cp1253", "${item}42}"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp1253", "{$item}42}"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 54108d0e7908a..82d74c750961b 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 @@ -24,10 +24,10 @@ internal_encoding=cp1254 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "�okbaytl� i�leri"; -$prefix = create_data("dir_cp1254", "${item}42", 1254); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp1254", "{$item}42", 1254); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($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 b2ba41900d321..f14a4c3de086e 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 @@ -24,8 +24,8 @@ internal_encoding=cp1254 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "�okbaytl� i�leri"; -$prefix = create_data("dir_cp1254", "${item}42}", 1254); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp1254", "{$item}42}", 1254); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 23fd79d44e7b6..42b241176ffb6 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 @@ -21,10 +21,10 @@ dir_cp1254 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "çokbaytlı işleri"; -$prefix = create_data("dir_cp1254", "${item}42"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp1254", "{$item}42"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 4bff1e9baaf0f..b0c4f5ec83f0e 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 @@ -21,8 +21,8 @@ dir_cp1254 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "çokbaytlı işleri"; -$prefix = create_data("dir_cp1254", "${item}42}"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp1254", "{$item}42}"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 0c78b91ab09e8..2cf42239267ad 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 @@ -24,10 +24,10 @@ default_charset=cp1255 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "����� ������"; -$prefix = create_data("dir_cp1255", "${item}42", 1255); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp1255", "{$item}42", 1255); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($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 1af549f0a7a3a..e4779b721ba92 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 @@ -24,8 +24,8 @@ internal_encoding=cp1255 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "����� ������"; -$prefix = create_data("dir_cp1255", "${item}42}", 1255); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp1255", "{$item}42}", 1255); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 e53936090a295..356143ca7876a 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 @@ -21,10 +21,10 @@ dir_cp1255 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "כללים מרובים"; -$prefix = create_data("dir_cp1255", "${item}42"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp1255", "{$item}42"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 1c9396348e406..b378a7231d15e 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 @@ -21,8 +21,8 @@ dir_cp1255 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "כללים מרובים"; -$prefix = create_data("dir_cp1255", "${item}42}"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp1255", "{$item}42}"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 08e8067163412..244758fe7bd67 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 @@ -24,10 +24,10 @@ internal_encoding=cp1256 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "���� ����� ������ ������"; -$prefix = create_data("dir_cp1256", "${item}42", 1256); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp1256", "{$item}42", 1256); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($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 d68cd3113ab2a..f5b5db8935277 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 @@ -24,8 +24,8 @@ default_charset=cp1256 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "���� ����� ������ ������"; -$prefix = create_data("dir_cp1256", "${item}42}", 1256); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp1256", "{$item}42}", 1256); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 04f5854e5b34e..b630f37648bc4 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 @@ -21,10 +21,10 @@ dir_cp1256 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "مسار متعدد البايت اختبار"; -$prefix = create_data("dir_cp1256", "${item}42"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp1256", "{$item}42"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 7b01bc56e080f..6aa29f43c4268 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 @@ -21,8 +21,8 @@ dir_cp1256 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "مسار متعدد البايت اختبار"; -$prefix = create_data("dir_cp1256", "${item}42}"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp1256", "{$item}42}"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 4bc6028ce2564..744d1a592be95 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 @@ -24,10 +24,10 @@ default_charset=cp932 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "�e�X�g�}���`�o�C�g�E�p�X"; // cp932 string -$prefix = create_data("dir_cp932", "${item}42", 932); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp932", "{$item}42", 932); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 2860eb9fb37b3..737a4d3eb869b 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 @@ -24,8 +24,8 @@ internal_encoding=cp932 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "�e�X�g�}���`�o�C�g�E�p�X"; // cp932 string -$prefix = create_data("dir_cp932", "${item}42}", 932); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp932", "{$item}42}", 932); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 0c487a33d3845..b9575302c8abc 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 @@ -21,10 +21,10 @@ dir_cp932 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('cp932', 'utf-8', "�e�X�g�}���`�o�C�g�E�p�X"); // cp932 string -$prefix = create_data("dir_cp932", "${item}42"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_cp932", "{$item}42"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 064625d1c88c9..7c3870593692e 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 @@ -21,8 +21,8 @@ dir_cp932 include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('cp932', 'utf-8', "�e�X�g�}���`�o�C�g�E�p�X"); // cp932 string -$prefix = create_data("dir_cp932", "${item}42}"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_cp932", "{$item}42}"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 b965a6855247d..529808aad5fb2 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 @@ -25,9 +25,9 @@ include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "�yԇ���ֹ�·��"; // cp936 string $prefix = create_data("dir_cp936", $item . "5", 936); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}5"; +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}5"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 c00e5f6b1f5f3..f9730b6fe9a08 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 @@ -22,9 +22,9 @@ include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('cp936', 'utf-8', "�yԇ���ֹ�·��"); // cp936 string $prefix = create_data("dir_cp936", $item . "5"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}5"; +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}5"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 313d0db9b7ae7..e3111ba33af7e 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 @@ -21,10 +21,10 @@ dir_eucjp include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('eucjp', 'utf-8', "�ƥ��ȥޥ���Х��ȡ��ѥ�"); // EUCJP string -$prefix = create_data("dir_eucjp", "${item}42"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_eucjp", "{$item}42"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 6707146c67d76..9425a1cc1cea8 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 @@ -21,8 +21,8 @@ dir_eucjp include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = iconv('eucjp', 'utf-8', "�ƥ��ȥޥ���Х��ȡ��ѥ�"); // EUCJP string -$prefix = create_data("dir_eucjp", "${item}42}"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_eucjp", "{$item}42}"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 baa6e96606b31..d348ccfd3c8fd 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 @@ -21,10 +21,10 @@ dir_kartuli include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "ქართველები"; -$prefix = create_data("dir_kartuli", "${item}42"); -$path = $prefix . DIRECTORY_SEPARATOR . "${item}42"; +$prefix = create_data("dir_kartuli", "{$item}42"); +$path = $prefix . DIRECTORY_SEPARATOR . "{$item}42"; -$subpath = $path . DIRECTORY_SEPARATOR . "${item}4"; +$subpath = $path . DIRECTORY_SEPARATOR . "{$item}4"; /* The mb dirname exists*/ var_dump(file_exists($path)); 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 4944aade2df3d..2e57dc0c91fa0 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 @@ -21,8 +21,8 @@ dir_kartuli include __DIR__ . DIRECTORY_SEPARATOR . "util.inc"; $item = "ქართველები"; -$prefix = create_data("dir_kartuli", "${item}42}"); -$fn = $prefix . DIRECTORY_SEPARATOR . "${item}33"; +$prefix = create_data("dir_kartuli", "{$item}42}"); +$fn = $prefix . DIRECTORY_SEPARATOR . "{$item}33"; $f = fopen($fn, 'w'); if ($f) { 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 3705582484cf1..6a5b60f08bbeb 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 @@ -1,12 +1,14 @@ --TEST-- Basic long path test +--EXTENSIONS-- +mbstring --SKIPIF-- --FILE-- diff --git a/ext/standard/tests/file/windows_mb_path/test_long_path_2.phpt b/ext/standard/tests/file/windows_mb_path/test_long_path_2.phpt index 05982133c1672..09ccebc0c0766 100644 --- a/ext/standard/tests/file/windows_mb_path/test_long_path_2.phpt +++ b/ext/standard/tests/file/windows_mb_path/test_long_path_2.phpt @@ -1,12 +1,14 @@ --TEST-- Basic long path test with file I/O, multibyte path and realpath() check +--EXTENSIONS-- +mbstring --SKIPIF-- --FILE-- diff --git a/ext/standard/tests/general_functions/bug47027.phpt b/ext/standard/tests/general_functions/bug47027.phpt index e4f5aae9dd744..b7d6604dbe90a 100644 --- a/ext/standard/tests/general_functions/bug47027.phpt +++ b/ext/standard/tests/general_functions/bug47027.phpt @@ -6,7 +6,7 @@ $ao = new ArrayObject(array (2 => "foo", "bar" => "baz")); var_export ($ao); ?> --EXPECT-- -ArrayObject::__set_state(array( +\ArrayObject::__set_state(array( 2 => 'foo', 'bar' => 'baz', )) diff --git a/ext/standard/tests/general_functions/bug77638_1.phpt b/ext/standard/tests/general_functions/bug77638_1.phpt index e2a99ffd19953..9d75a9a7ce498 100644 --- a/ext/standard/tests/general_functions/bug77638_1.phpt +++ b/ext/standard/tests/general_functions/bug77638_1.phpt @@ -7,5 +7,5 @@ com_dotnet var_export(new COM("Scripting.Dictionary")); ?> --EXPECT-- -com::__set_state(array( +\com::__set_state(array( )) diff --git a/ext/standard/tests/general_functions/bug77638_2.phpt b/ext/standard/tests/general_functions/bug77638_2.phpt index cec76659c608d..589697011aa60 100644 --- a/ext/standard/tests/general_functions/bug77638_2.phpt +++ b/ext/standard/tests/general_functions/bug77638_2.phpt @@ -7,5 +7,5 @@ ffi var_export(FFI::new('int')); ?> --EXPECT-- -FFI\CData::__set_state(array( +\FFI\CData::__set_state(array( )) diff --git a/ext/standard/tests/general_functions/dl-001.phpt b/ext/standard/tests/general_functions/dl-001.phpt new file mode 100644 index 0000000000000..cd4538e22d1b0 --- /dev/null +++ b/ext/standard/tests/general_functions/dl-001.phpt @@ -0,0 +1,33 @@ +--TEST-- +dl(): Loaded extensions properly unregister their ini settings +--SKIPIF-- + +--FILE-- + +--FILE-- + +--FILE-- += $sleeplow) { echo "TEST PASSED\n"; } else { - echo "TEST FAILED - time is ${time} secs and sleep was ${sleeptime} secs\n"; + echo "TEST FAILED - time is {$time} secs and sleep was {$sleeptime} secs\n"; } ?> --EXPECTF-- diff --git a/ext/standard/tests/general_functions/var_export-locale.phpt b/ext/standard/tests/general_functions/var_export-locale.phpt index 0b22a4f4678d3..18fb957871b3f 100644 --- a/ext/standard/tests/general_functions/var_export-locale.phpt +++ b/ext/standard/tests/general_functions/var_export-locale.phpt @@ -914,35 +914,35 @@ string(17) "(object) array( Iteration 2 -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" Iteration 3 -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -string(36) "concreteClass::__set_state(array( +string(37) "\concreteClass::__set_state(array( ))" Iteration 4 -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -string(57) "Value::__set_state(array( +string(58) "\Value::__set_state(array( 'vars' => array ( ), @@ -950,140 +950,140 @@ string(57) "Value::__set_state(array( Iteration 5 -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -string(266) "myClass::__set_state(array( +string(271) "\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), ))" Iteration 6 -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -string(266) "myClass::__set_state(array( +string(271) "\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), ))" Iteration 7 -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" Iteration 8 -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" Iteration 9 -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" Iteration 10 -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -string(57) "Value::__set_state(array( +string(58) "\Value::__set_state(array( 'vars' => array ( ), @@ -1091,11 +1091,11 @@ string(57) "Value::__set_state(array( Iteration 11 -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -string(36) "concreteClass::__set_state(array( +string(37) "\concreteClass::__set_state(array( ))" *** Testing var_export() with valid null values *** diff --git a/ext/standard/tests/general_functions/var_export-locale_32.phpt b/ext/standard/tests/general_functions/var_export-locale_32.phpt index 81ddacb1a358e..2cf6cf341d449 100644 --- a/ext/standard/tests/general_functions/var_export-locale_32.phpt +++ b/ext/standard/tests/general_functions/var_export-locale_32.phpt @@ -914,35 +914,35 @@ string(17) "(object) array( Iteration 2 -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" Iteration 3 -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -string(36) "concreteClass::__set_state(array( +string(37) "\concreteClass::__set_state(array( ))" Iteration 4 -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -string(57) "Value::__set_state(array( +string(58) "\Value::__set_state(array( 'vars' => array ( ), @@ -950,140 +950,140 @@ string(57) "Value::__set_state(array( Iteration 5 -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -string(266) "myClass::__set_state(array( +string(271) "\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), ))" Iteration 6 -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -string(266) "myClass::__set_state(array( +string(271) "\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), ))" Iteration 7 -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" Iteration 8 -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" Iteration 9 -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" Iteration 10 -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -string(57) "Value::__set_state(array( +string(58) "\Value::__set_state(array( 'vars' => array ( ), @@ -1091,11 +1091,11 @@ string(57) "Value::__set_state(array( Iteration 11 -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -string(36) "concreteClass::__set_state(array( +string(37) "\concreteClass::__set_state(array( ))" *** Testing var_export() with valid null values *** diff --git a/ext/standard/tests/general_functions/var_export_basic6.phpt b/ext/standard/tests/general_functions/var_export_basic6.phpt index 3f60e08e9fcc0..42d072bcb3b56 100644 --- a/ext/standard/tests/general_functions/var_export_basic6.phpt +++ b/ext/standard/tests/general_functions/var_export_basic6.phpt @@ -110,35 +110,35 @@ string(17) "(object) array( -- Iteration: new foo -- -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" -- Iteration: new concreteClass -- -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -string(36) "concreteClass::__set_state(array( +string(37) "\concreteClass::__set_state(array( ))" -- Iteration: new Value -- -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -string(57) "Value::__set_state(array( +string(58) "\Value::__set_state(array( 'vars' => array ( ), @@ -146,140 +146,140 @@ string(57) "Value::__set_state(array( -- Iteration: new myClass -- -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -string(266) "myClass::__set_state(array( +string(271) "\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), ))" -- Iteration: myClass_object -- -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -myClass::__set_state(array( +\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), )) -string(266) "myClass::__set_state(array( +string(271) "\myClass::__set_state(array( 'foo_object' => - foo::__set_state(array( + \foo::__set_state(array( )), 'public_var' => 10, 'public_var1' => - foo::__set_state(array( + \foo::__set_state(array( )), 'private_var' => - foo::__set_state(array( + \foo::__set_state(array( )), 'protected_var' => - foo::__set_state(array( + \foo::__set_state(array( )), ))" -- Iteration: myClass_object->foo_object -- -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" -- Iteration: myClass_object->public_var1 -- -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" -- Iteration: foo_object -- -foo::__set_state(array( +\foo::__set_state(array( )) -foo::__set_state(array( +\foo::__set_state(array( )) -string(26) "foo::__set_state(array( +string(27) "\foo::__set_state(array( ))" -- Iteration: Value_object -- -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -Value::__set_state(array( +\Value::__set_state(array( 'vars' => array ( ), )) -string(57) "Value::__set_state(array( +string(58) "\Value::__set_state(array( 'vars' => array ( ), @@ -287,9 +287,9 @@ string(57) "Value::__set_state(array( -- Iteration: concreteClass_object -- -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -concreteClass::__set_state(array( +\concreteClass::__set_state(array( )) -string(36) "concreteClass::__set_state(array( +string(37) "\concreteClass::__set_state(array( ))" diff --git a/ext/standard/tests/mail/bug72964.phpt b/ext/standard/tests/mail/bug72964.phpt index 44048771d6d2c..38289c2f3d454 100644 --- a/ext/standard/tests/mail/bug72964.phpt +++ b/ext/standard/tests/mail/bug72964.phpt @@ -1,5 +1,7 @@ --TEST-- Bug #72964 (White space not unfolded for CC/Bcc headers) +--EXTENSIONS-- +imap --SKIPIF-- " ') !== false); + var_dump(strpos($header, "To: \"\" <{$users[1]}@$domain>") !== false); echo "From header found: "; var_dump(strpos($header, 'From: "" ') !== false); echo "Cc header found: "; - var_dump(strpos($header, 'Cc: "Lastname, Firstname\\\\" ') !== false); + var_dump(strpos($header, "Cc: \"Lastname, Firstname\\\\\" <{$users[2]}@$domain>") !== false); imap_delete($imap_stream, $i); $found = true; break; diff --git a/ext/standard/tests/mail/mail_basic_alt1-win32.phpt b/ext/standard/tests/mail/mail_basic_alt1-win32.phpt index 0cffdfd2aa21e..3051e600ec662 100644 --- a/ext/standard/tests/mail/mail_basic_alt1-win32.phpt +++ b/ext/standard/tests/mail/mail_basic_alt1-win32.phpt @@ -1,5 +1,7 @@ --TEST-- Test mail() function : basic functionality +--EXTENSIONS-- +imap --SKIPIF-- ---EXPECT-- -*** Testing syslog() : basic functionality *** -bool(true) diff --git a/ext/standard/tests/serialize/bug69425.phpt b/ext/standard/tests/serialize/bug69425.phpt index 906c7192fb20a..1bc79c0387c8c 100644 --- a/ext/standard/tests/serialize/bug69425.phpt +++ b/ext/standard/tests/serialize/bug69425.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #69425: Use After Free in unserialize() +Bug #69425 (Use After Free in unserialize()) --FILE-- ---EXPECT-- +--EXPECTF-- int(1) array(2) { [0]=> - object(DateInterval)#1 (16) { + object(DateInterval)#1 (%d) { ["y"]=> int(-1) ["m"]=> @@ -41,24 +41,12 @@ array(2) { int(-1) ["f"]=> float(0) - ["weekday"]=> - int(-1) - ["weekday_behavior"]=> - int(-1) - ["first_last_day_of"]=> - int(-1) ["invert"]=> int(0) ["days"]=> int(-1) - ["special_type"]=> - int(0) - ["special_amount"]=> - int(-1) - ["have_weekday_relative"]=> - int(0) - ["have_special_relative"]=> - int(0) + ["from_string"]=> + bool(false) } [1]=> int(2) diff --git a/ext/standard/tests/streams/temp_stream_seek.phpt b/ext/standard/tests/streams/temp_stream_seek.phpt new file mode 100644 index 0000000000000..821c6b2784d7d --- /dev/null +++ b/ext/standard/tests/streams/temp_stream_seek.phpt @@ -0,0 +1,20 @@ +--TEST-- +BUG: php://temp does not preserve file-pointer once it switches from memory to temporary file +--FILE-- + +--EXPECT-- +string(16) "2222222222222222" +int(738) diff --git a/ext/standard/tests/strings/lcfirst.phpt b/ext/standard/tests/strings/lcfirst.phpt index d98b3a9cb0eed..1abc31d0b3b51 100644 --- a/ext/standard/tests/strings/lcfirst.phpt +++ b/ext/standard/tests/strings/lcfirst.phpt @@ -130,6 +130,7 @@ var_dump(lcfirst(lcfirst("hello"))); echo "Done\n"; ?> --EXPECTF-- +Deprecated: Using ${var} in strings is deprecated, use {$var} instead in %s on line %d #### Basic and Various operations #### string(16) "tesTing lcfirst." string(17) "1.testing lcfirst" diff --git a/ext/standard/tests/strings/str_replace_variation3.phpt b/ext/standard/tests/strings/str_replace_variation3.phpt index f08d8c7dc1bae..07c6ef7da3467 100644 --- a/ext/standard/tests/strings/str_replace_variation3.phpt +++ b/ext/standard/tests/strings/str_replace_variation3.phpt @@ -149,6 +149,8 @@ closedir($resource2); ?> --EXPECTF-- +Deprecated: Using ${var} in strings is deprecated, use {$var} instead in %s on line %d + *** Testing Miscellaneous input data *** string(3) "qqq" int(5) diff --git a/ext/standard/tests/strings/strcasecmp.phpt b/ext/standard/tests/strings/strcasecmp.phpt index 04452067d488f..e55b2a684fb21 100644 --- a/ext/standard/tests/strings/strcasecmp.phpt +++ b/ext/standard/tests/strings/strcasecmp.phpt @@ -113,6 +113,7 @@ var_dump(strcasecmp(10.55555555595555555555555555, 10.555555556)); // int(0) echo "Done\n"; ?> --EXPECTF-- +Deprecated: Using ${var} in strings is deprecated, use {$var} instead in %s on line %d #### Basic and Possible operations #### *** comparing the strings in an Array diff --git a/ext/standard/tests/strings/strcmp.phpt b/ext/standard/tests/strings/strcmp.phpt index a36873830cedd..5310566d53b60 100644 --- a/ext/standard/tests/strings/strcmp.phpt +++ b/ext/standard/tests/strings/strcmp.phpt @@ -113,6 +113,7 @@ var_dump(strcmp(10.55555555595555555555555555, 10.555555556)); // int(0) echo "Done\n"; ?> --EXPECTF-- +Deprecated: Using ${var} in strings is deprecated, use {$var} instead in %s on line %d #### Basic and Possible operations #### *** comparing the strings in an Array diff --git a/ext/standard/tests/strings/strlen.phpt b/ext/standard/tests/strings/strlen.phpt index 426154504b66b..b98111f15e672 100644 --- a/ext/standard/tests/strings/strlen.phpt +++ b/ext/standard/tests/strings/strlen.phpt @@ -122,6 +122,7 @@ var_dump(strlen(strlen("Hello"))); // len=1 echo "Done\n"; ?> --EXPECTF-- +Deprecated: Using ${var} in strings is deprecated, use {$var} instead in %s on line %d #### Basic operations and variations #### String length of 'Hello, World' is => int(12) String length of 'Hello, World' is => int(12) diff --git a/ext/standard/tests/strings/strpos.phpt b/ext/standard/tests/strings/strpos.phpt index 449601f6e5480..05913cc1f03b5 100644 --- a/ext/standard/tests/strings/strpos.phpt +++ b/ext/standard/tests/strings/strpos.phpt @@ -175,6 +175,7 @@ try { DONE --EXPECTF-- +Deprecated: Using ${var} in strings is deprecated, use {$var} instead in %s on line %d *** Testing basic functionality of strpos() *** int(0) int(5) diff --git a/ext/standard/tests/strings/strstr.phpt b/ext/standard/tests/strings/strstr.phpt index f5a2d80318b74..0d4065b54fb2b 100644 --- a/ext/standard/tests/strings/strstr.phpt +++ b/ext/standard/tests/strings/strstr.phpt @@ -136,6 +136,7 @@ var_dump( strstr("a", "b", "c") ); // args > expected DONE --EXPECTF-- +Deprecated: Using ${var} in strings is deprecated, use {$var} instead in %s on line %d *** Testing basic functionality of strstr() *** string(11) "test string" string(6) "string" diff --git a/ext/standard/tests/strings/ucfirst.phpt b/ext/standard/tests/strings/ucfirst.phpt index 1cae286d98a9a..5389579eb2f38 100644 --- a/ext/standard/tests/strings/ucfirst.phpt +++ b/ext/standard/tests/strings/ucfirst.phpt @@ -101,6 +101,7 @@ var_dump(ucfirst(ucfirst("hello"))); echo "Done\n"; ?> --EXPECTF-- +Deprecated: Using ${var} in strings is deprecated, use {$var} instead in %s on line %d #### Basic and Various operations #### string(16) "Testing ucfirst." string(17) "1.testing ucfirst" diff --git a/ext/standard/tests/time/idate.phpt b/ext/standard/tests/time/idate.phpt index 1a06070b45e3c..dc006f7acf465 100644 --- a/ext/standard/tests/time/idate.phpt +++ b/ext/standard/tests/time/idate.phpt @@ -3,7 +3,7 @@ idate() function --FILE-- +--EXPECT-- +U: 1041808859 +w: 0 +N: 7 +W: 1 +U: 1072912859 +Y: 2003 +o: 2004 +W: 1 diff --git a/ext/standard/var.c b/ext/standard/var.c index dc9f8639b146f..54f8657da80d6 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -575,6 +575,7 @@ PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf) /* {{{ */ if (ce == zend_standard_class_def) { smart_str_appendl(buf, "(object) array(\n", 16); } else { + smart_str_appendc(buf, '\\'); smart_str_append(buf, ce->name); if (is_enum) { zend_object *zobj = Z_OBJ_P(struc); diff --git a/ext/sysvshm/tests/bug72858.phpt b/ext/sysvshm/tests/bug72858.phpt index f3b269a4d671d..74eefb3b773af 100644 --- a/ext/sysvshm/tests/bug72858.phpt +++ b/ext/sysvshm/tests/bug72858.phpt @@ -12,7 +12,7 @@ if (substr(PHP_OS, 0, 3) != "WIN") { print "skip windows only"; } diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 63a141e15057a..0a0f12e79fe2d 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -291,6 +291,15 @@ static ZEND_FUNCTION(zend_weakmap_dump) RETURN_ARR(zend_array_dup(&ZT_G(global_weakmap))); } +static ZEND_FUNCTION(zend_get_current_func_name) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + zend_string *function_name = get_function_or_method_name(EG(current_execute_data)->prev_execute_data->func); + + RETURN_STR(function_name); +} + /* TESTS Z_PARAM_ITERABLE and Z_PARAM_ITERABLE_OR_NULL */ static ZEND_FUNCTION(zend_iterable) { diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 9361d81c267d8..8d5c4142130e9 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -109,6 +109,8 @@ function zend_weakmap_dump(): array {} function zend_get_unit_enum(): ZendTestUnitEnum {} function zend_test_parameter_with_attribute(string $parameter): int {} + + function zend_get_current_func_name(): string {} } namespace ZendTestNS { diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 22290c580d059..7a553e0a18457 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: bf10c37919483ac04bc1f788ac6e59b5edab295e */ + * Stub hash: 54adf746478423b7e7caa09d417fb97bb9621203 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -75,14 +75,16 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_parameter_with_attribu ZEND_ARG_TYPE_INFO(0, parameter, IS_STRING, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_get_current_func_name, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ZendTestNS2_ZendSubNS_namespaced_func, 0, 0, _IS_BOOL, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class__ZendTestClass_is_object, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class__ZendTestClass___toString, 0, 0, IS_STRING, 0) -ZEND_END_ARG_INFO() +#define arginfo_class__ZendTestClass___toString arginfo_zend_get_current_func_name ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class__ZendTestClass_returnsStatic, 0, 0, IS_STATIC, 0) ZEND_END_ARG_INFO() @@ -131,6 +133,7 @@ static ZEND_FUNCTION(zend_weakmap_remove); static ZEND_FUNCTION(zend_weakmap_dump); static ZEND_FUNCTION(zend_get_unit_enum); static ZEND_FUNCTION(zend_test_parameter_with_attribute); +static ZEND_FUNCTION(zend_get_current_func_name); static ZEND_FUNCTION(namespaced_func); static ZEND_METHOD(_ZendTestClass, is_object); static ZEND_METHOD(_ZendTestClass, __toString); @@ -167,6 +170,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(zend_weakmap_dump, arginfo_zend_weakmap_dump) ZEND_FE(zend_get_unit_enum, arginfo_zend_get_unit_enum) ZEND_FE(zend_test_parameter_with_attribute, arginfo_zend_test_parameter_with_attribute) + ZEND_FE(zend_get_current_func_name, arginfo_zend_get_current_func_name) ZEND_NS_FE("ZendTestNS2\\ZendSubNS", namespaced_func, arginfo_ZendTestNS2_ZendSubNS_namespaced_func) ZEND_FE_END }; diff --git a/ext/zend_test/tests/get_function_or_method_name_01.inc b/ext/zend_test/tests/get_function_or_method_name_01.inc new file mode 100644 index 0000000000000..b0c2ae5a20236 --- /dev/null +++ b/ext/zend_test/tests/get_function_or_method_name_01.inc @@ -0,0 +1,3 @@ + +--EXPECT-- +string(4) "main" diff --git a/ext/zend_test/tests/observer_bug81430_1.phpt b/ext/zend_test/tests/observer_bug81430_1.phpt index 1d1e3c4256e0e..cac53ef70cbbb 100644 --- a/ext/zend_test/tests/observer_bug81430_1.phpt +++ b/ext/zend_test/tests/observer_bug81430_1.phpt @@ -1,7 +1,7 @@ --TEST-- Bug #81430 (Attribute instantiation frame accessing invalid frame pointer) --EXTENSIONS-- -zend-test +zend_test --INI-- memory_limit=20M zend_test.observer.enabled=1 diff --git a/ext/zend_test/tests/observer_bug81430_2.phpt b/ext/zend_test/tests/observer_bug81430_2.phpt index a575fb9d7a038..4d56248a80f34 100644 --- a/ext/zend_test/tests/observer_bug81430_2.phpt +++ b/ext/zend_test/tests/observer_bug81430_2.phpt @@ -1,7 +1,7 @@ --TEST-- Bug #81430 (Attribute instantiation leaves dangling execute_data pointer) --EXTENSIONS-- -zend-test +zend_test --INI-- memory_limit=20M zend_test.observer.enabled=1 diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index 49c1491828f06..d3f224cb51d29 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -31,7 +31,7 @@ extern zend_module_entry zip_module_entry; #define ZIP_OVERWRITE ZIP_TRUNCATE #endif -#define PHP_ZIP_VERSION "1.20.0" +#define PHP_ZIP_VERSION "1.20.1" #define ZIP_OPENBASEDIR_CHECKPATH(filename) php_check_open_basedir(filename) diff --git a/ext/zip/php_zip.stub.php b/ext/zip/php_zip.stub.php index 26ef522470e91..47df80df0e49a 100644 --- a/ext/zip/php_zip.stub.php +++ b/ext/zip/php_zip.stub.php @@ -106,7 +106,7 @@ public function addFromString(string $name, string $content, int $flags = ZipArc public function addFile(string $filepath, string $entryname = "", int $start = 0, int $length = 0, int $flags = ZipArchive::FL_OVERWRITE): bool {} /** @tentative-return-type */ - public function replaceFile(string $filepath, string $index, int $start = 0, int $length = 0, int $flags = 0): bool {} + public function replaceFile(string $filepath, int $index, int $start = 0, int $length = 0, int $flags = 0): bool {} /** @tentative-return-type */ public function addGlob(string $pattern, int $flags = 0, array $options = []): array|false {} diff --git a/ext/zip/php_zip_arginfo.h b/ext/zip/php_zip_arginfo.h index 09e586502c780..b642f6347783e 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: 13bf4e67d7a36ba19e7222fbbcb94fea4e59c558 */ + * Stub hash: f6542fda12c523584d476d2b733b4ccc0ffffe32 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) @@ -82,7 +82,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ZipArchive_replaceFile, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, filepath, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, index, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, index, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, start, IS_LONG, 0, "0") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, length, IS_LONG, 0, "0") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 09188dc76941e..a53fb2acc4593 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -281,7 +281,7 @@ static int php_zlib_output_handler(void **handler_context, php_output_context *o return FAILURE; } - if (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN) || (output_context->op & PHP_OUTPUT_HANDLER_START)) { + if (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN) || ((output_context->op & PHP_OUTPUT_HANDLER_START) && !(output_context->op & PHP_OUTPUT_HANDLER_FINAL))) { int flags; if (SUCCESS == php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags)) { diff --git a/main/fastcgi.c b/main/fastcgi.c index 6020cf4fda9a4..a77491f1bf23d 100644 --- a/main/fastcgi.c +++ b/main/fastcgi.c @@ -1590,10 +1590,10 @@ int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int l memcpy(req->out_pos, str, len); req->out_pos += len; } else if (len - limit < (int)(sizeof(req->out_buf) - sizeof(fcgi_header))) { - if (!req->out_hdr) { - open_packet(req, type); - } if (limit > 0) { + if (!req->out_hdr) { + open_packet(req, type); + } memcpy(req->out_pos, str, limit); req->out_pos += limit; } diff --git a/main/main.c b/main/main.c index dc705fcdbdfe9..3bdd01169ee11 100644 --- a/main/main.c +++ b/main/main.c @@ -1960,24 +1960,6 @@ int php_register_extensions(zend_module_entry * const * ptr, int count) return SUCCESS; } -/* A very long time ago php_module_startup() was refactored in a way - * which broke calling it with more than one additional module. - * This alternative to php_register_extensions() works around that - * by walking the shallower structure. - * - * See algo: https://bugs.php.net/bug.php?id=63159 - */ -static int php_register_extensions_bc(zend_module_entry *ptr, int count) -{ - while (count--) { - if (zend_register_internal_module(ptr++) == NULL) { - return FAILURE; - } - } - return SUCCESS; -} -/* }}} */ - #ifdef PHP_WIN32 static _invalid_parameter_handler old_invalid_parameter_handler; @@ -2012,11 +1994,12 @@ void dummy_invalid_parameter_handler( #endif /* {{{ php_module_startup */ -int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint32_t num_additional_modules) +zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module) { zend_utility_functions zuf; zend_utility_values zuv; - int retval = SUCCESS, module_number=0; /* for REGISTER_INI_ENTRIES() */ + zend_result retval = SUCCESS; + int module_number = 0; char *php_os; zend_module_entry *module; @@ -2194,7 +2177,7 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod zend_stream_shutdown(); /* Register PHP core ini entries */ - REGISTER_INI_ENTRIES(); + zend_register_ini_entries_ex(ini_entries, module_number, MODULE_PERSISTENT); /* Register Zend ini entries */ zend_register_standard_ini_entries(); @@ -2243,7 +2226,9 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod } /* start additional PHP extensions */ - php_register_extensions_bc(additional_modules, num_additional_modules); + if (additional_module && (zend_register_internal_module(additional_module) == NULL)) { + return FAILURE; + } /* load and startup extensions compiled as shared objects (aka DLLs) as requested by php.ini entries @@ -2278,7 +2263,7 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod module->version = PHP_VERSION; module->info_func = PHP_MINFO(php_core); } - + /* freeze the list of observer fcall_init handlers */ zend_observer_post_startup(); @@ -2389,7 +2374,7 @@ int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals) /* {{{ php_module_shutdown */ void php_module_shutdown(void) { - int module_number=0; /* for UNREGISTER_INI_ENTRIES() */ + int module_number=0; module_shutdown = 1; @@ -2420,7 +2405,7 @@ void php_module_shutdown(void) /* Destroys filter & transport registries too */ php_shutdown_stream_wrappers(module_number); - UNREGISTER_INI_ENTRIES(); + zend_unregister_ini_entries_ex(module_number, MODULE_PERSISTENT); /* close down the ini config */ php_shutdown_config(); diff --git a/main/network.c b/main/network.c index 47082ba3bb125..f0559953b227f 100644 --- a/main/network.c +++ b/main/network.c @@ -884,6 +884,12 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short local_address.in6.sin6_port = htons(bindport); } } +#endif +#ifdef IP_BIND_ADDRESS_NO_PORT + { + int val = 1; + (void) setsockopt(sock, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &val, sizeof(val)); + } #endif if (local_address_len == 0) { php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto); @@ -1157,7 +1163,7 @@ PHPAPI void _php_emit_fd_setsize_warning(int max_fd) php_error_docref(NULL, E_WARNING, "PHP needs to be recompiled with a larger value of FD_SETSIZE.\n" "If this binary is from an official www.php.net package, file a bug report\n" - "at http://bugs.php.net, including the following information:\n" + "at https://github.com/php/php-src/issues, including the following information:\n" "FD_SETSIZE=%d, but you are using %d.\n" " --enable-fd-setsize=%d is recommended, but you may want to set it\n" "to match to maximum number of sockets each script will work with at\n" diff --git a/main/php_ini.c b/main/php_ini.c index d080163663851..0f3fdcd502fb4 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -566,7 +566,7 @@ int php_init_config(void) /* Check if php_ini_file_name is a file and can be opened */ if (php_ini_file_name && php_ini_file_name[0]) { - zend_stat_t statbuf; + zend_stat_t statbuf = {0}; if (!VCWD_STAT(php_ini_file_name, &statbuf)) { if (!((statbuf.st_mode & S_IFMT) == S_IFDIR)) { @@ -642,7 +642,7 @@ int php_init_config(void) if (!sapi_module.php_ini_ignore && php_ini_scanned_path_len) { struct dirent **namelist; int ndir, i; - zend_stat_t sb; + zend_stat_t sb = {0}; char ini_file[MAXPATHLEN]; char *p; zend_llist scanned_ini_list; diff --git a/main/php_ini_builder.c b/main/php_ini_builder.c new file mode 100644 index 0000000000000..d214a340343fd --- /dev/null +++ b/main/php_ini_builder.c @@ -0,0 +1,82 @@ +/* + +----------------------------------------------------------------------+ + | 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: Max Kellermann | + +----------------------------------------------------------------------+ +*/ + +#include "php_ini_builder.h" + +#include +#include + +PHPAPI void php_ini_builder_prepend(struct php_ini_builder *b, const char *src, size_t length) +{ + php_ini_builder_realloc(b, length); + if (b->length > 0) + memmove(b->value + length, b->value, b->length); + memcpy(b->value, src, length); + b->length += length; +} + +PHPAPI void php_ini_builder_unquoted(struct php_ini_builder *b, const char *name, size_t name_length, const char *value, size_t value_length) +{ + php_ini_builder_realloc(b, name_length + 1 + value_length + 1); + + memcpy(b->value + b->length, name, name_length); + b->length += name_length; + + b->value[b->length++] = '='; + + memcpy(b->value + b->length, value, value_length); + b->length += value_length; + + b->value[b->length++] = '\n'; +} + +PHPAPI void php_ini_builder_quoted(struct php_ini_builder *b, const char *name, size_t name_length, const char *value, size_t value_length) +{ + php_ini_builder_realloc(b, name_length + 2 + value_length + 2); + + memcpy(b->value + b->length, name, name_length); + b->length += name_length; + + b->value[b->length++] = '='; + b->value[b->length++] = '"'; + + memcpy(b->value + b->length, value, value_length); + b->length += value_length; + + b->value[b->length++] = '"'; + b->value[b->length++] = '\n'; +} + +PHPAPI void php_ini_builder_define(struct php_ini_builder *b, const char *arg) +{ + const size_t len = strlen(arg); + const char *val = strchr(arg, '='); + + if (val != NULL) { + val++; + if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') { + php_ini_builder_quoted(b, arg, val - arg - 1, val, arg + len - val); + } else { + php_ini_builder_realloc(b, len + strlen("\n")); + memcpy(b->value + b->length, arg, len); + b->length += len; + b->value[b->length++] = '\n'; + } + } else { + php_ini_builder_unquoted(b, arg, len, "1", 1); + } +} + diff --git a/main/php_ini_builder.h b/main/php_ini_builder.h new file mode 100644 index 0000000000000..7f5be81c10ac7 --- /dev/null +++ b/main/php_ini_builder.h @@ -0,0 +1,95 @@ +/* + +----------------------------------------------------------------------+ + | 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: Max Kellermann | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_INI_BUILDER_H +#define PHP_INI_BUILDER_H + +#include "php.h" + +/** + * A class which helps with constructing INI entries from the command + * line. + */ +struct php_ini_builder { + char *value; + size_t length; +}; + +BEGIN_EXTERN_C() + +static inline void php_ini_builder_init(struct php_ini_builder *b) +{ + b->value = NULL; + b->length = 0; +} + +static inline void php_ini_builder_deinit(struct php_ini_builder *b) +{ + free(b->value); +} + +/** + * Null-terminate the buffer and return it. + */ +static inline char *php_ini_builder_finish(struct php_ini_builder *b) +{ + if (b->value != NULL) { + /* null-terminate the string */ + b->value[b->length] = '\0'; + } + + return b->value; +} + +/** + * Make room for more data. + * + * @param delta the number of bytes to be appended + */ +static inline void php_ini_builder_realloc(struct php_ini_builder *b, size_t delta) +{ + /* reserve enough space for the null terminator */ + b->value = realloc(b->value, b->length + delta + 1); +} + +/** + * Prepend a string. + * + * @param src the source string + * @param length the size of the source string + */ +PHPAPI void php_ini_builder_prepend(struct php_ini_builder *b, const char *src, size_t length); + +#define php_ini_builder_prepend_literal(b, l) php_ini_builder_prepend(b, l, strlen(l)) + +/** + * Append an unquoted name/value pair. + */ +PHPAPI void php_ini_builder_unquoted(struct php_ini_builder *b, const char *name, size_t name_length, const char *value, size_t value_length); + +/** + * Append a quoted name/value pair. + */ +PHPAPI void php_ini_builder_quoted(struct php_ini_builder *b, const char *name, size_t name_length, const char *value, size_t value_length); + +/** + * Parse an INI entry from the command-line option "--define". + */ +PHPAPI void php_ini_builder_define(struct php_ini_builder *b, const char *arg); + +END_EXTERN_C() + +#endif diff --git a/main/php_main.h b/main/php_main.h index 661c88446524f..50351da0e6391 100644 --- a/main/php_main.h +++ b/main/php_main.h @@ -25,7 +25,7 @@ BEGIN_EXTERN_C() PHPAPI int php_request_startup(void); PHPAPI void php_request_shutdown(void *dummy); -PHPAPI int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint32_t num_additional_modules); +PHPAPI zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_module); PHPAPI void php_module_shutdown(void); PHPAPI int php_module_shutdown_wrapper(sapi_module_struct *sapi_globals); diff --git a/main/streams/memory.c b/main/streams/memory.c index 365976716d283..f53084a6c3a77 100644 --- a/main/streams/memory.c +++ b/main/streams/memory.c @@ -348,9 +348,10 @@ static ssize_t php_stream_temp_write(php_stream *stream, const char *buf, size_t return -1; } if (php_stream_is(ts->innerstream, PHP_STREAM_IS_MEMORY)) { - zend_string *membuf = php_stream_memory_get_buffer(ts->innerstream); - - if (ZSTR_LEN(membuf) + count >= ts->smax) { + zend_off_t pos = php_stream_tell(ts->innerstream); + + if (pos + count >= ts->smax) { + zend_string *membuf = php_stream_memory_get_buffer(ts->innerstream); php_stream *file = php_stream_fopen_temporary_file(ts->tmpdir, "php", NULL); if (file == NULL) { php_error_docref(NULL, E_WARNING, "Unable to create temporary file, Check permissions in temporary files directory."); @@ -360,6 +361,7 @@ static ssize_t php_stream_temp_write(php_stream *stream, const char *buf, size_t php_stream_free_enclosed(ts->innerstream, PHP_STREAM_FREE_CLOSE); ts->innerstream = file; php_stream_encloses(stream, ts->innerstream); + php_stream_seek(ts->innerstream, pos, SEEK_SET); } } return php_stream_write(ts->innerstream, buf, count); diff --git a/main/streams/streams.c b/main/streams/streams.c index 8a7e328007215..c10af433904bc 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1555,6 +1555,90 @@ PHPAPI zend_result _php_stream_copy_to_stream_ex(php_stream *src, php_stream *de return SUCCESS; } +#ifdef HAVE_COPY_FILE_RANGE + + /* TODO: on FreeBSD, copy_file_range() works only with the + undocumented flag 0x01000000; until the problem is fixed + properly, copy_file_range() is not used on FreeBSD */ +#ifndef __FreeBSD__ + if (php_stream_is(src, PHP_STREAM_IS_STDIO) && + php_stream_is(dest, PHP_STREAM_IS_STDIO) && + src->writepos == src->readpos && + php_stream_can_cast(src, PHP_STREAM_AS_FD) == SUCCESS && + php_stream_can_cast(dest, PHP_STREAM_AS_FD) == SUCCESS) { + /* both php_stream instances are backed by a file + descriptor, are not filtered and the read buffer is + empty: we can use copy_file_range() */ + + int src_fd, dest_fd; + + php_stream_cast(src, PHP_STREAM_AS_FD, (void*)&src_fd, 0); + php_stream_cast(dest, PHP_STREAM_AS_FD, (void*)&dest_fd, 0); + + /* clamp to INT_MAX to avoid EOVERFLOW */ + const size_t cfr_max = MIN(maxlen, (size_t)SSIZE_MAX); + + /* copy_file_range() is a Linux-specific system call + which allows efficient copying between two file + descriptors, eliminating the need to transfer data + from the kernel to userspace and back. For + networking file systems like NFS and Ceph, it even + eliminates copying data to the client, and local + filesystems like Btrfs and XFS can create shared + extents. */ + + ssize_t result = copy_file_range(src_fd, NULL, + dest_fd, NULL, + cfr_max, 0); + if (result > 0) { + size_t nbytes = (size_t)result; + haveread += nbytes; + + src->position += nbytes; + dest->position += nbytes; + + if ((maxlen != PHP_STREAM_COPY_ALL && nbytes == maxlen) || + php_stream_eof(src)) { + /* the whole request was satisfied or + end-of-file reached - done */ + *len = haveread; + return SUCCESS; + } + + /* there may be more data; continue copying + using the fallback code below */ + } else if (result == 0) { + /* end of file */ + *len = haveread; + return SUCCESS; + } else if (result < 0) { + switch (errno) { + case EINVAL: + /* some formal error, e.g. overlapping + file ranges */ + break; + + case EXDEV: + /* pre Linux 5.3 error */ + break; + + case ENOSYS: + /* not implemented by this Linux kernel */ + break; + + default: + /* unexpected I/O error - give up, no + fallback */ + *len = haveread; + return FAILURE; + } + + /* fall back to classic copying */ + } + } +#endif // __FreeBSD__ +#endif // HAVE_COPY_FILE_RANGE + if (maxlen == PHP_STREAM_COPY_ALL) { maxlen = 0; } diff --git a/main/strlcat.c b/main/strlcat.c index 212948ffaf3a8..b514a7e0d5d5c 100644 --- a/main/strlcat.c +++ b/main/strlcat.c @@ -61,10 +61,7 @@ static const char *rcsid = "$OpenBSD: strlcat.c,v 1.17 2016/10/14 18:19:04 dtuck * Returns strlen(src) + MIN(siz, strlen(initial dst). * If retval >= siz, truncation occurred. */ -PHPAPI size_t php_strlcat(dst, src, siz) - char *dst; - const char *src; - size_t siz; +PHPAPI size_t php_strlcat(char *dst, const char *src, size_t siz) { const char *d = dst; const char *s = src; diff --git a/main/strlcpy.c b/main/strlcpy.c index 7839856592e7b..9ca99311aa424 100644 --- a/main/strlcpy.c +++ b/main/strlcpy.c @@ -59,10 +59,7 @@ static const char *rcsid = "$OpenBSD: strlcpy.c,v 1.15 2016/10/16 17:37:39 dtuck * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ -PHPAPI size_t php_strlcpy(dst, src, siz) - char *dst; - const char *src; - size_t siz; +PHPAPI size_t php_strlcpy(char *dst, const char *src, size_t siz) { const char *s = src; size_t n = siz; @@ -83,12 +80,7 @@ PHPAPI size_t php_strlcpy(dst, src, siz) ; } - /* - * Cast pointers to unsigned type before calculation, to avoid signed - * overflow when the string ends where the MSB has changed. - * Return value does not include NUL. - */ - return((uintptr_t)src - (uintptr_t)s - 1); + return(src - s - 1); } #endif /* !HAVE_STRLCPY */ diff --git a/run-tests.php b/run-tests.php index 964b7c117592b..8b4061e1c84b8 100755 --- a/run-tests.php +++ b/run-tests.php @@ -2807,10 +2807,10 @@ function run_test(string $php, $file, array $env): string lldb -- {$orig_cmd} ;; "valgrind") - USE_ZEND_ALLOC=0 valgrind $2 ${orig_cmd} + USE_ZEND_ALLOC=0 valgrind $2 {$orig_cmd} ;; "rr") - rr record $2 ${orig_cmd} + rr record $2 {$orig_cmd} ;; *) {$orig_cmd} diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c index 7933e6accea38..5238b02bbd625 100644 --- a/sapi/apache2handler/sapi_apache2.c +++ b/sapi/apache2handler/sapi_apache2.c @@ -378,10 +378,7 @@ extern zend_module_entry php_apache_module; static int php_apache2_startup(sapi_module_struct *sapi_module) { - if (php_module_startup(sapi_module, &php_apache_module, 1)==FAILURE) { - return FAILURE; - } - return SUCCESS; + return php_module_startup(sapi_module, &php_apache_module); } static sapi_module_struct apache2_sapi_module = { diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index 7d5f444d1c54a..4f9a71bfac6c5 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -22,6 +22,7 @@ #include "php.h" #include "php_globals.h" #include "php_variables.h" +#include "php_ini_builder.h" #include "zend_modules.h" #include "SAPI.h" @@ -966,10 +967,7 @@ static int sapi_cgi_deactivate(void) static int php_cgi_startup(sapi_module_struct *sapi_module) { - if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) { - return FAILURE; - } - return SUCCESS; + return php_module_startup(sapi_module, &cgi_module_entry); } /* {{{ sapi_module_struct cgi_sapi_module */ @@ -1727,7 +1725,7 @@ int main(int argc, char *argv[]) int orig_optind = php_optind; char *orig_optarg = php_optarg; char *script_file = NULL; - size_t ini_entries_len = 0; + struct php_ini_builder ini_builder; /* end of temporary locals */ int max_requests = 500; @@ -1812,6 +1810,8 @@ int main(int argc, char *argv[]) free(decoded_query_string); } + php_ini_builder_init(&ini_builder); + while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { switch (c) { case 'c': @@ -1823,37 +1823,10 @@ int main(int argc, char *argv[]) case 'n': cgi_sapi_module.php_ini_ignore = 1; break; - case 'd': { + case 'd': /* define ini entries on command line */ - size_t len = strlen(php_optarg); - char *val; - - if ((val = strchr(php_optarg, '='))) { - val++; - if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') { - cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0")); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg)); - ini_entries_len += (val - php_optarg); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1); - ini_entries_len++; - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg)); - ini_entries_len += len - (val - php_optarg); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0")); - ini_entries_len += sizeof("\n\0\"") - 2; - } else { - cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0")); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0")); - ini_entries_len += len + sizeof("\n\0") - 2; - } - } else { - cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0")); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len); - memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0")); - ini_entries_len += len + sizeof("=1\n\0") - 2; - } + php_ini_builder_define(&ini_builder, php_optarg); break; - } /* if we're started on command line, check to see if * we are being started as an 'external' fastcgi * server by accepting a bindpath parameter. */ @@ -1870,6 +1843,8 @@ int main(int argc, char *argv[]) php_optind = orig_optind; php_optarg = orig_optarg; + cgi_sapi_module.ini_entries = php_ini_builder_finish(&ini_builder); + if (fastcgi || bindpath) { /* Override SAPI callbacks */ cgi_sapi_module.ub_write = sapi_fcgi_ub_write; @@ -2619,9 +2594,7 @@ consult the installation file that came with this distribution, or visit \n\ if (cgi_sapi_module.php_ini_path_override) { free(cgi_sapi_module.php_ini_path_override); } - if (cgi_sapi_module.ini_entries) { - free(cgi_sapi_module.ini_entries); - } + php_ini_builder_deinit(&ini_builder); } zend_catch { exit_status = 255; } zend_end_try(); diff --git a/sapi/cli/php.1.in b/sapi/cli/php.1.in index e8b84ad3d12a9..abf053769a815 100644 --- a/sapi/cli/php.1.in +++ b/sapi/cli/php.1.in @@ -436,7 +436,7 @@ You can view the list of known bugs or report any new bug you found at: .PD 0 .P -.B http://bugs.php.net +.B https://github.com/php/php-src/issues .PD 1 .SH AUTHORS The PHP Group: Thies C. Arntzen, Stig Bakken, Andi Gutmans, Rasmus Lerdorf, Sam Ruby, Sascha Schumann, Zeev Suraski, Jim Winstead, Andrei Zmievski. diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index fdd604cec53b0..66a1b9ad86b09 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -21,6 +21,7 @@ #include "php.h" #include "php_globals.h" #include "php_variables.h" +#include "php_ini_builder.h" #include "zend_hash.h" #include "zend_modules.h" #include "zend_interfaces.h" @@ -131,7 +132,7 @@ const char HARDCODED_INI[] = "implicit_flush=1\n" "output_buffering=0\n" "max_execution_time=0\n" - "max_input_time=-1\n\0"; + "max_input_time=-1\n"; const opt_struct OPTIONS[] = { @@ -233,7 +234,7 @@ static void print_extensions(void) /* {{{ */ #define STDERR_FILENO 2 #endif -static inline int sapi_cli_select(php_socket_t fd) +static inline bool sapi_cli_select(php_socket_t fd) { fd_set wfd; struct timeval tv; @@ -406,10 +407,7 @@ static void sapi_cli_send_header(sapi_header_struct *sapi_header, void *server_c static int php_cli_startup(sapi_module_struct *sapi_module) /* {{{ */ { - if (php_module_startup(sapi_module, NULL, 0)==FAILURE) { - return FAILURE; - } - return SUCCESS; + return php_module_startup(sapi_module, NULL); } /* }}} */ @@ -574,7 +572,7 @@ static void cli_register_file_handles(bool no_close) /* {{{ */ static const char *param_mode_conflict = "Either execute direct code, process stdin or use a file.\n"; /* {{{ cli_seek_file_begin */ -static int cli_seek_file_begin(zend_file_handle *file_handle, char *script_file) +static zend_result cli_seek_file_begin(zend_file_handle *file_handle, char *script_file) { FILE *fp = VCWD_FOPEN(script_file, "rb"); if (!fp) { @@ -611,9 +609,9 @@ static int do_cli(int argc, char **argv) /* {{{ */ char *exec_direct=NULL, *exec_run=NULL, *exec_begin=NULL, *exec_end=NULL; char *arg_free=NULL, **arg_excp=&arg_free; char *script_file=NULL, *translated_path = NULL; - int interactive=0; + bool interactive = false; const char *param_error=NULL; - int hide_argv = 0; + bool hide_argv = false; int num_repeats = 1; pid_t pid = getpid(); @@ -700,7 +698,7 @@ static int do_cli(int argc, char **argv) /* {{{ */ break; } - interactive=1; + interactive = true; } break; @@ -820,7 +818,7 @@ static int do_cli(int argc, char **argv) /* {{{ */ zend_load_extension(php_optarg); break; case 'H': - hide_argv = 1; + hide_argv = true; break; case 10: behavior=PHP_MODE_REFLECTION_FUNCTION; @@ -896,7 +894,7 @@ static int do_cli(int argc, char **argv) /* {{{ */ } if (script_file) { virtual_cwd_activate(); - if (cli_seek_file_begin(&file_handle, script_file) != SUCCESS) { + if (cli_seek_file_begin(&file_handle, script_file) == FAILURE) { goto err; } else { char real_path[MAXPATHLEN]; @@ -1024,7 +1022,7 @@ static int do_cli(int argc, char **argv) /* {{{ */ zend_eval_string_ex(exec_run, NULL, "Command line run code", 1); } else { if (script_file) { - if (cli_seek_file_begin(&file_handle, script_file) != SUCCESS) { + if (cli_seek_file_begin(&file_handle, script_file) == FAILURE) { EG(exit_status) = 1; } else { CG(skip_shebang) = 1; @@ -1176,8 +1174,7 @@ int main(int argc, char *argv[]) char *php_optarg = NULL; int php_optind = 1, use_extended_info = 0; char *ini_path_override = NULL; - char *ini_entries = NULL; - size_t ini_entries_len = 0; + struct php_ini_builder ini_builder; int ini_ignore = 0; sapi_module_struct *sapi_module = &cli_sapi_module; @@ -1239,6 +1236,8 @@ int main(int argc, char *argv[]) setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ #endif + php_ini_builder_init(&ini_builder); + while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 1, 2))!=-1) { switch (c) { case 'c': @@ -1250,37 +1249,10 @@ int main(int argc, char *argv[]) case 'n': ini_ignore = 1; break; - case 'd': { + case 'd': /* define ini entries on command line */ - size_t len = strlen(php_optarg); - char *val; - - if ((val = strchr(php_optarg, '='))) { - val++; - if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') { - ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\"\"\n\0")); - memcpy(ini_entries + ini_entries_len, php_optarg, (val - php_optarg)); - ini_entries_len += (val - php_optarg); - memcpy(ini_entries + ini_entries_len, "\"", 1); - ini_entries_len++; - memcpy(ini_entries + ini_entries_len, val, len - (val - php_optarg)); - ini_entries_len += len - (val - php_optarg); - memcpy(ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0")); - ini_entries_len += sizeof("\n\0\"") - 2; - } else { - ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\n\0")); - memcpy(ini_entries + ini_entries_len, php_optarg, len); - memcpy(ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0")); - ini_entries_len += len + sizeof("\n\0") - 2; - } - } else { - ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("=1\n\0")); - memcpy(ini_entries + ini_entries_len, php_optarg, len); - memcpy(ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0")); - ini_entries_len += len + sizeof("=1\n\0") - 2; - } + php_ini_builder_define(&ini_builder, php_optarg); break; - } #ifndef PHP_CLI_WIN32_NO_CONSOLE case 'S': sapi_module = &cli_server_sapi_module; @@ -1317,18 +1289,10 @@ int main(int argc, char *argv[]) sapi_module->executable_location = argv[0]; if (sapi_module == &cli_sapi_module) { - if (ini_entries) { - ini_entries = realloc(ini_entries, ini_entries_len + sizeof(HARDCODED_INI)); - memmove(ini_entries + sizeof(HARDCODED_INI) - 2, ini_entries, ini_entries_len + 1); - memcpy(ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI) - 2); - } else { - ini_entries = malloc(sizeof(HARDCODED_INI)); - memcpy(ini_entries, HARDCODED_INI, sizeof(HARDCODED_INI)); - } - ini_entries_len += sizeof(HARDCODED_INI) - 2; + php_ini_builder_prepend_literal(&ini_builder, HARDCODED_INI); } - sapi_module->ini_entries = ini_entries; + sapi_module->ini_entries = php_ini_builder_finish(&ini_builder); /* startup after we get the above ini override se we get things right */ if (sapi_module->startup(sapi_module) == FAILURE) { @@ -1375,9 +1339,7 @@ int main(int argc, char *argv[]) if (ini_path_override) { free(ini_path_override); } - if (ini_entries) { - free(ini_entries); - } + php_ini_builder_deinit(&ini_builder); if (module_started) { php_module_shutdown(); } diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 6e7a909b128d0..983d5f88bac62 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -164,19 +164,15 @@ typedef struct php_cli_server_client { php_socket_t sock; struct sockaddr *addr; socklen_t addr_len; - char *addr_str; - size_t addr_str_len; + zend_string *addr_str; php_http_parser parser; - unsigned int request_read:1; - char *current_header_name; - size_t current_header_name_len; - unsigned int current_header_name_allocated:1; - char *current_header_value; - size_t current_header_value_len; + bool request_read; + zend_string *current_header_name; + zend_string *current_header_value; enum { HEADER_NONE=0, HEADER_FIELD, HEADER_VALUE } last_header_element; size_t post_read_offset; php_cli_server_request request; - unsigned int content_sender_initialized:1; + bool content_sender_initialized; php_cli_server_content_sender content_sender; int file_fd; } php_cli_server_client; @@ -241,23 +237,23 @@ static const char php_cli_server_css[] = "