Version in base suite: 8.2.24-1~deb12u1 Base version: php8.2_8.2.24-1~deb12u1 Target version: php8.2_8.2.26-1~deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/php8.2/php8.2_8.2.24-1~deb12u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/php8.2/php8.2_8.2.26-1~deb12u1.dsc /srv/release.debian.org/tmp/1nVyDKFjuf/php8.2-8.2.26/ext/pdo_odbc/tests/test.mdb |binary php8.2-8.2.26/.cirrus.yml | 1 php8.2-8.2.26/.github/CODEOWNERS | 29 php8.2-8.2.26/.github/actions/brew/action.yml | 17 php8.2-8.2.26/.github/actions/configure-macos/action.yml | 3 php8.2-8.2.26/.github/actions/configure-x64/action.yml | 3 php8.2-8.2.26/.github/actions/setup-mssql/action.yml | 2 php8.2-8.2.26/.github/actions/setup-x64/action.yml | 9 php8.2-8.2.26/.github/actions/test-linux/action.yml | 4 php8.2-8.2.26/.github/labeler.yml | 90 + php8.2-8.2.26/.github/nightly_matrix.php | 111 - php8.2-8.2.26/.github/scripts/windows/test_task.bat | 11 php8.2-8.2.26/.github/workflows/nightly.yml | 592 +++++- php8.2-8.2.26/.github/workflows/push.yml | 19 php8.2-8.2.26/.github/workflows/root.yml | 57 php8.2-8.2.26/EXTENSIONS | 3 php8.2-8.2.26/NEWS | 291 +++ php8.2-8.2.26/TSRM/tsrm_win32.c | 1 php8.2-8.2.26/Zend/Optimizer/zend_inference.c | 3 php8.2-8.2.26/Zend/tests/generators/gh15851.phpt | 27 php8.2-8.2.26/Zend/tests/gh15712.phpt | 9 php8.2-8.2.26/Zend/tests/gh15866.phpt | 53 php8.2-8.2.26/Zend/tests/gh15907.phpt | 18 php8.2-8.2.26/Zend/tests/gh16188.phpt | 34 php8.2-8.2.26/Zend/tests/gh16293_001.phpt | 19 php8.2-8.2.26/Zend/tests/gh16293_002.phpt | 19 php8.2-8.2.26/Zend/tests/gh16371.phpt | 47 php8.2-8.2.26/Zend/tests/gh16508.phpt | 20 php8.2-8.2.26/Zend/tests/gh16509.inc | 7 php8.2-8.2.26/Zend/tests/gh16509.phpt | 11 php8.2-8.2.26/Zend/tests/gh16515.phpt | 16 php8.2-8.2.26/Zend/tests/gh16648.phpt | 49 php8.2-8.2.26/Zend/zend.c | 2 php8.2-8.2.26/Zend/zend.h | 2 php8.2-8.2.26/Zend/zend_builtin_functions.c | 10 php8.2-8.2.26/Zend/zend_closures.c | 2 php8.2-8.2.26/Zend/zend_compile.c | 3 php8.2-8.2.26/Zend/zend_exceptions.c | 12 php8.2-8.2.26/Zend/zend_generators.c | 25 php8.2-8.2.26/Zend/zend_generators.h | 1 php8.2-8.2.26/Zend/zend_hash.c | 30 php8.2-8.2.26/Zend/zend_hash.h | 8 php8.2-8.2.26/Zend/zend_inheritance.c | 2 php8.2-8.2.26/Zend/zend_interfaces.c | 4 php8.2-8.2.26/Zend/zend_object_handlers.c | 9 php8.2-8.2.26/Zend/zend_operators.h | 15 php8.2-8.2.26/Zend/zend_string.c | 40 php8.2-8.2.26/Zend/zend_strtod.c | 6 php8.2-8.2.26/Zend/zend_weakrefs.c | 4 php8.2-8.2.26/build/php.m4 | 12 php8.2-8.2.26/configure | 68 php8.2-8.2.26/configure.ac | 12 php8.2-8.2.26/debian/changelog | 25 php8.2-8.2.26/debian/patches/0001-libtool_fixes.patch | 4 php8.2-8.2.26/debian/patches/0002-debian_quirks.patch | 8 php8.2-8.2.26/debian/patches/0003-php-5.4.9-phpinfo.patch | 4 php8.2-8.2.26/debian/patches/0004-extension_api.patch | 6 php8.2-8.2.26/debian/patches/0006-php-5.4.7-libdb.patch | 2 php8.2-8.2.26/debian/patches/0010-session_save_path.patch | 4 php8.2-8.2.26/debian/patches/0017-php-5.3.3-macropen.patch | 4 php8.2-8.2.26/debian/patches/0021-Use-system-timezone.patch | 2 php8.2-8.2.26/debian/patches/0024-php-5.4.9-fixheader.patch | 4 php8.2-8.2.26/debian/patches/0030-Really-expand-libdir-datadir-into-EXPANDED_LIBDIR-DA.patch | 4 php8.2-8.2.26/debian/patches/0035-Include-all-libtool-files-from-phpize.m4.patch | 2 php8.2-8.2.26/debian/patches/0041-Lower-the-OpenSSL-requirement-to-1.0.1.patch | 4 php8.2-8.2.26/debian/patches/0042-Fail-the-build-when-the-dtrace-call-fails.patch | 2 php8.2-8.2.26/debian/patches/0043-Override-result-of-AC_PROG_LN_S-to-fix-FTBFS-on-ppc6.patch | 2 php8.2-8.2.26/debian/patches/0046-Remove-timestamps-from-phar.patch | 2 php8.2-8.2.26/debian/patches/0048-Revert-ext-gmp-gmp_pow-fix-FPE-with-large-values-pat.patch | 181 ++ php8.2-8.2.26/debian/patches/series | 1 php8.2-8.2.26/ext/calendar/cal_unix.c | 6 php8.2-8.2.26/ext/calendar/dow.c | 9 php8.2-8.2.26/ext/calendar/easter.c | 6 php8.2-8.2.26/ext/calendar/jewish.c | 19 php8.2-8.2.26/ext/calendar/tests/gh16228.phpt | 26 php8.2-8.2.26/ext/calendar/tests/gh16231.phpt | 21 php8.2-8.2.26/ext/calendar/tests/gh16234.phpt | 11 php8.2-8.2.26/ext/calendar/tests/gh16258.phpt | 12 php8.2-8.2.26/ext/com_dotnet/com_variant.c | 7 php8.2-8.2.26/ext/com_dotnet/tests/variant_variation.phpt | 30 php8.2-8.2.26/ext/curl/multi.c | 14 php8.2-8.2.26/ext/curl/tests/bug48203_multi.phpt | 7 php8.2-8.2.26/ext/curl/tests/bug71523.phpt | 7 php8.2-8.2.26/ext/curl/tests/curl_basic_018.phpt | 7 php8.2-8.2.26/ext/curl/tests/curl_multi_add_handle_lifecycle.phpt | 49 php8.2-8.2.26/ext/curl/tests/curl_multi_getcontent_basic3.phpt | 7 php8.2-8.2.26/ext/date/lib/parse_date.c | 228 +- php8.2-8.2.26/ext/date/lib/parse_date.re | 20 php8.2-8.2.26/ext/date/lib/parse_iso_intervals.c | 791 ++++----- php8.2-8.2.26/ext/date/lib/timelib.h | 8 php8.2-8.2.26/ext/date/lib/timelib_private.h | 9 php8.2-8.2.26/ext/date/php_date.c | 35 php8.2-8.2.26/ext/date/tests/bug-gh15582.phpt | 21 php8.2-8.2.26/ext/date/tests/bug-gh16037.phpt | 9 php8.2-8.2.26/ext/date/tests/bug40861.phpt | 2 php8.2-8.2.26/ext/date/tests/gh14732.phpt | 38 php8.2-8.2.26/ext/date/tests/gh16454.phpt | 21 php8.2-8.2.26/ext/dba/dba.c | 17 php8.2-8.2.26/ext/dba/tests/gh16390.phpt | 11 php8.2-8.2.26/ext/dom/node.c | 104 - php8.2-8.2.26/ext/dom/parentnode.c | 5 php8.2-8.2.26/ext/dom/php_dom.stub.php | 2 php8.2-8.2.26/ext/dom/php_dom_arginfo.h | 4 php8.2-8.2.26/ext/dom/tests/gh16039.phpt | 31 php8.2-8.2.26/ext/dom/tests/gh16151.phpt | 35 php8.2-8.2.26/ext/dom/tests/gh16316.phpt | 32 php8.2-8.2.26/ext/dom/tests/gh16473.phpt | 13 php8.2-8.2.26/ext/dom/tests/gh16533.phpt | 20 php8.2-8.2.26/ext/dom/tests/gh16535.phpt | 25 php8.2-8.2.26/ext/dom/tests/gh16593.phpt | 22 php8.2-8.2.26/ext/dom/xml_common.h | 18 php8.2-8.2.26/ext/dom/xpath.c | 5 php8.2-8.2.26/ext/exif/exif.c | 2 php8.2-8.2.26/ext/exif/tests/gh16409.phpt | 12 php8.2-8.2.26/ext/ffi/ffi.c | 8 php8.2-8.2.26/ext/ffi/tests/gh16397.phpt | 15 php8.2-8.2.26/ext/filter/logical_filters.c | 2 php8.2-8.2.26/ext/filter/tests/gh16523.phpt | 20 php8.2-8.2.26/ext/gd/gd.c | 19 php8.2-8.2.26/ext/gd/libgd/gd_avif.c | 25 php8.2-8.2.26/ext/gd/libgd/gd_interpolation.c | 64 php8.2-8.2.26/ext/gd/libgd/wbmp.c | 3 php8.2-8.2.26/ext/gd/tests/gh16232.phpt | 27 php8.2-8.2.26/ext/gd/tests/gh16257.phpt | 12 php8.2-8.2.26/ext/gd/tests/gh16260.phpt | 22 php8.2-8.2.26/ext/gd/tests/gh16322.phpt | 27 php8.2-8.2.26/ext/gd/tests/gh16559.phpt | 15 php8.2-8.2.26/ext/gmp/gmp.c | 123 + php8.2-8.2.26/ext/gmp/tests/gh16411.phpt | 11 php8.2-8.2.26/ext/gmp/tests/gh16501.phpt | 14 php8.2-8.2.26/ext/gmp/tests/gmp_pow.phpt | 2 php8.2-8.2.26/ext/gmp/tests/gmp_pow_32bits.phpt | 77 php8.2-8.2.26/ext/gmp/tests/gmp_pow_fpe.phpt | 35 php8.2-8.2.26/ext/gmp/tests/gmp_random_bits.phpt | 6 php8.2-8.2.26/ext/gmp/tests/overloading_cmp_op_with_null.phpt | 53 php8.2-8.2.26/ext/gmp/tests/overloading_with_array.phpt | 84 php8.2-8.2.26/ext/gmp/tests/overloading_with_float.phpt | 117 + php8.2-8.2.26/ext/gmp/tests/overloading_with_float_fractional.phpt | 132 + php8.2-8.2.26/ext/gmp/tests/overloading_with_float_string.phpt | 84 php8.2-8.2.26/ext/gmp/tests/overloading_with_int_string.phpt | 117 + php8.2-8.2.26/ext/gmp/tests/overloading_with_non_numeric_string.phpt | 84 php8.2-8.2.26/ext/gmp/tests/overloading_with_null.phpt | 84 php8.2-8.2.26/ext/gmp/tests/overloading_with_object_not_stringable.phpt | 85 php8.2-8.2.26/ext/gmp/tests/overloading_with_object_stringable.phpt | 91 + php8.2-8.2.26/ext/gmp/tests/overloading_with_resource.phpt | 84 php8.2-8.2.26/ext/intl/tests/bug62070_3.phpt | 1 php8.2-8.2.26/ext/intl/tests/bug62070_icu76_1.phpt | 17 php8.2-8.2.26/ext/intl/tests/collator_get_sort_key_variant7.phpt | 1 php8.2-8.2.26/ext/intl/tests/collator_get_sort_key_variant_icu76_1.phpt | 97 + php8.2-8.2.26/ext/intl/tests/locale_get_display_name8.phpt | 18 php8.2-8.2.26/ext/intl/tests/locale_get_display_variant2.phpt | 18 php8.2-8.2.26/ext/intl/tests/timezone_IDforWindowsID_basic2.phpt | 1 php8.2-8.2.26/ext/intl/tests/timezone_IDforWindowsID_basic_icu76_1.phpt | 44 php8.2-8.2.26/ext/ldap/ldap.c | 59 php8.2-8.2.26/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt | 28 php8.2-8.2.26/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt | 29 php8.2-8.2.26/ext/ldap/tests/gh16032-1.phpt | 26 php8.2-8.2.26/ext/ldap/tests/gh16032-2.phpt | 26 php8.2-8.2.26/ext/ldap/tests/gh16101.phpt | 25 php8.2-8.2.26/ext/ldap/tests/gh16132-1.phpt | 28 php8.2-8.2.26/ext/ldap/tests/gh16132-2.phpt | 28 php8.2-8.2.26/ext/ldap/tests/gh16136.phpt | 30 php8.2-8.2.26/ext/libxml/tests/bug61367-read_2.phpt | 2 php8.2-8.2.26/ext/libxml/tests/libxml_disable_entity_loader_2.phpt | 2 php8.2-8.2.26/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt | 2 php8.2-8.2.26/ext/mbstring/mbstring.c | 32 php8.2-8.2.26/ext/mbstring/tests/gh16229.phpt | 26 php8.2-8.2.26/ext/mbstring/tests/gh16261.phpt | 44 php8.2-8.2.26/ext/mbstring/tests/gh16360.phpt | 23 php8.2-8.2.26/ext/mysqli/tests/fake_server.inc | 856 ++++++++++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt | 38 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt | 47 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt | 43 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-query-len-overflow.phpt | 48 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-bit.phpt | 53 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-date.phpt | 53 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-datetime.phpt | 53 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-double.phpt | 53 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-float.phpt | 53 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-int.phpt | 53 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-no-space.phpt | 53 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-string.phpt | 53 php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-time.phpt | 53 php8.2-8.2.26/ext/mysqli/tests/protocol_query_row_fetch_data.phpt | 74 php8.2-8.2.26/ext/mysqli/tests/protocol_stmt_row_fetch_data.phpt | 91 + php8.2-8.2.26/ext/mysqlnd/mysqlnd_ps_codec.c | 68 php8.2-8.2.26/ext/mysqlnd/mysqlnd_wireprotocol.c | 98 - php8.2-8.2.26/ext/opcache/jit/zend_jit.c | 15 php8.2-8.2.26/ext/opcache/jit/zend_jit_arm64.dasc | 4 php8.2-8.2.26/ext/opcache/jit/zend_jit_helpers.c | 6 php8.2-8.2.26/ext/opcache/jit/zend_jit_trace.c | 5 php8.2-8.2.26/ext/opcache/jit/zend_jit_x86.dasc | 4 php8.2-8.2.26/ext/opcache/tests/jit/gh15973.phpt | 24 php8.2-8.2.26/ext/opcache/tests/jit/gh16393.phpt | 18 php8.2-8.2.26/ext/opcache/tests/jit/gh16499.phpt | 28 php8.2-8.2.26/ext/opcache/zend_accelerator_util_funcs.c | 4 php8.2-8.2.26/ext/openssl/openssl.c | 37 php8.2-8.2.26/ext/openssl/openssl.stub.php | 4 php8.2-8.2.26/ext/openssl/openssl_arginfo.h | 4 php8.2-8.2.26/ext/openssl/tests/gh16357.phpt | 22 php8.2-8.2.26/ext/openssl/tests/gh16433.phpt | 17 php8.2-8.2.26/ext/pcre/php_pcre.c | 13 php8.2-8.2.26/ext/pcre/tests/gh16184.phpt | 13 php8.2-8.2.26/ext/pcre/tests/gh16189.phpt | 19 php8.2-8.2.26/ext/pdo_dblib/dblib_driver.c | 10 php8.2-8.2.26/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt | 24 php8.2-8.2.26/ext/pdo_firebird/firebird_driver.c | 6 php8.2-8.2.26/ext/pdo_odbc/odbc_stmt.c | 7 php8.2-8.2.26/ext/pdo_odbc/tests/gh16450.phpt | 35 php8.2-8.2.26/ext/phar/phar.c | 12 php8.2-8.2.26/ext/phar/phar_object.c | 3 php8.2-8.2.26/ext/phar/tests/033a.phpt | 6 php8.2-8.2.26/ext/phar/tests/gh16406.phpt | 35 php8.2-8.2.26/ext/phar/tests/phar_oo_002.phpt | 6 php8.2-8.2.26/ext/phar/tests/phar_oo_iswriteable.phpt | 6 php8.2-8.2.26/ext/phar/tests/stat.phpt | 6 php8.2-8.2.26/ext/phar/tests/tar/033a.phpt | 6 php8.2-8.2.26/ext/phar/tests/zip/033a.phpt | 6 php8.2-8.2.26/ext/posix/tests/posix_getgrnam_basic.phpt | 5 php8.2-8.2.26/ext/posix/tests/posix_getgroups_basic.phpt | 6 php8.2-8.2.26/ext/reflection/php_reflection.c | 47 php8.2-8.2.26/ext/reflection/tests/ReflectionExtension_double_construct.phpt | 20 php8.2-8.2.26/ext/reflection/tests/ReflectionObject_double_construct.phpt | 21 php8.2-8.2.26/ext/reflection/tests/ReflectionParameter_double_construct.phpt | 27 php8.2-8.2.26/ext/reflection/tests/ReflectionProperty_double_construct.phpt | 24 php8.2-8.2.26/ext/reflection/tests/gh16187.phpt | 14 php8.2-8.2.26/ext/session/session.c | 20 php8.2-8.2.26/ext/session/tests/gh16290.phpt | 13 php8.2-8.2.26/ext/session/tests/gh16385.phpt | 13 php8.2-8.2.26/ext/session/tests/session_get_cookie_params_basic.phpt | 4 php8.2-8.2.26/ext/simplexml/simplexml.c | 5 php8.2-8.2.26/ext/simplexml/tests/gh15837.phpt | 30 php8.2-8.2.26/ext/soap/php_encoding.c | 25 php8.2-8.2.26/ext/soap/php_http.c | 10 php8.2-8.2.26/ext/soap/php_schema.c | 27 php8.2-8.2.26/ext/soap/soap.c | 7 php8.2-8.2.26/ext/soap/tests/bug71610.phpt | 13 php8.2-8.2.26/ext/soap/tests/bugs/bug27722.phpt | 2 php8.2-8.2.26/ext/soap/tests/bugs/bug27742.phpt | 2 php8.2-8.2.26/ext/soap/tests/bugs/bug62900.phpt | 95 + php8.2-8.2.26/ext/soap/tests/bugs/bug62900_run | 2 php8.2-8.2.26/ext/soap/tests/bugs/gh16237.phpt | 17 php8.2-8.2.26/ext/soap/tests/bugs/gh16256.phpt | 25 php8.2-8.2.26/ext/soap/tests/bugs/gh16259.phpt | 23 php8.2-8.2.26/ext/soap/tests/bugs/gh16429.phpt | 22 php8.2-8.2.26/ext/soap/tests/server011.phpt | 6 php8.2-8.2.26/ext/soap/tests/server012.phpt | 6 php8.2-8.2.26/ext/sockets/sockets.c | 8 php8.2-8.2.26/ext/sockets/tests/gh16267.phpt | 22 php8.2-8.2.26/ext/sockets/tests/socket_recv_overflow.phpt | 19 php8.2-8.2.26/ext/spl/spl_array.c | 15 php8.2-8.2.26/ext/spl/spl_directory.c | 25 php8.2-8.2.26/ext/spl/spl_dllist.c | 13 php8.2-8.2.26/ext/spl/spl_fixedarray.c | 4 php8.2-8.2.26/ext/spl/spl_heap.c | 55 php8.2-8.2.26/ext/spl/spl_iterators.c | 27 php8.2-8.2.26/ext/spl/spl_observer.c | 13 php8.2-8.2.26/ext/spl/tests/gh14687.phpt | 49 php8.2-8.2.26/ext/spl/tests/gh16337.phpt | 49 php8.2-8.2.26/ext/spl/tests/gh16464.phpt | 29 php8.2-8.2.26/ext/spl/tests/gh16477-2.phpt | 19 php8.2-8.2.26/ext/spl/tests/gh16477.phpt | 19 php8.2-8.2.26/ext/spl/tests/gh16478.phpt | 21 php8.2-8.2.26/ext/spl/tests/gh16479.phpt | 25 php8.2-8.2.26/ext/spl/tests/gh16588.phpt | 22 php8.2-8.2.26/ext/spl/tests/gh16589.phpt | 23 php8.2-8.2.26/ext/spl/tests/gh16604_1.phpt | 15 php8.2-8.2.26/ext/spl/tests/gh16604_2.phpt | 21 php8.2-8.2.26/ext/spl/tests/gh16646.phpt | 32 php8.2-8.2.26/ext/spl/tests/gh16646_2.phpt | 25 php8.2-8.2.26/ext/standard/array.c | 17 php8.2-8.2.26/ext/standard/assert.c | 5 php8.2-8.2.26/ext/standard/filters.c | 7 php8.2-8.2.26/ext/standard/http_fopen_wrapper.c | 18 php8.2-8.2.26/ext/standard/pack.c | 7 php8.2-8.2.26/ext/standard/tests/array/gh16053.phpt | 28 php8.2-8.2.26/ext/standard/tests/file/file_get_contents_basic.phpt | 12 php8.2-8.2.26/ext/standard/tests/file/file_get_contents_error.phpt | 6 php8.2-8.2.26/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt | 12 php8.2-8.2.26/ext/standard/tests/general_functions/phpinfo.phpt | 26 php8.2-8.2.26/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt | 28 php8.2-8.2.26/ext/standard/tests/streams/gh15908.phpt | 38 php8.2-8.2.26/ext/standard/tests/streams/gh15937.phpt | 16 php8.2-8.2.26/ext/standard/tests/streams/gh15980.phpt | 12 php8.2-8.2.26/ext/standard/tests/strings/gh15613.phpt | 25 php8.2-8.2.26/ext/sysvmsg/sysvmsg.c | 14 php8.2-8.2.26/ext/sysvmsg/tests/gh16592.phpt | 19 php8.2-8.2.26/ext/sysvshm/sysvshm.c | 6 php8.2-8.2.26/ext/sysvshm/tests/gh16591.phpt | 25 php8.2-8.2.26/ext/xml/tests/gh15868.phpt | 46 php8.2-8.2.26/ext/xml/xml.c | 6 php8.2-8.2.26/ext/xmlreader/php_xmlreader.c | 8 php8.2-8.2.26/ext/xmlreader/tests/gh16292.phpt | 26 php8.2-8.2.26/ext/zend_test/fiber.c | 2 php8.2-8.2.26/ext/zend_test/observer.c | 8 php8.2-8.2.26/ext/zend_test/test.c | 34 php8.2-8.2.26/ext/zend_test/test.stub.php | 7 php8.2-8.2.26/ext/zend_test/test_arginfo.h | 27 php8.2-8.2.26/ext/zend_test/tests/gh16230.phpt | 22 php8.2-8.2.26/ext/zend_test/tests/gh16233.phpt | 32 php8.2-8.2.26/ext/zend_test/tests/gh16266.phpt | 21 php8.2-8.2.26/ext/zend_test/tests/gh16294.phpt | 16 php8.2-8.2.26/ext/zend_test/tests/gh16388.phpt | 12 php8.2-8.2.26/ext/zend_test/tests/gh16514.phpt | 58 php8.2-8.2.26/ext/zend_test/tests/observer_error_04.phpt | 4 php8.2-8.2.26/ext/zend_test/tests/observer_fiber_functions_03.phpt | 4 php8.2-8.2.26/ext/zlib/tests/gh16326.phpt | 26 php8.2-8.2.26/ext/zlib/zlib.c | 32 php8.2-8.2.26/main/SAPI.c | 3 php8.2-8.2.26/main/main.c | 4 php8.2-8.2.26/main/php_network.h | 2 php8.2-8.2.26/main/php_variables.c | 1 php8.2-8.2.26/main/php_version.h | 6 php8.2-8.2.26/main/streams/streams.c | 12 php8.2-8.2.26/run-tests.php | 7 php8.2-8.2.26/sapi/cli/php_cli.c | 1 php8.2-8.2.26/sapi/cli/php_cli_server.c | 30 php8.2-8.2.26/sapi/cli/tests/gh16137.phpt | 20 php8.2-8.2.26/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt | 41 php8.2-8.2.26/sapi/fpm/fpm/zlog.c | 19 php8.2-8.2.26/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt | 61 php8.2-8.2.26/sapi/fpm/tests/gh16628.phpt | 53 php8.2-8.2.26/sapi/fpm/tests/tester.inc | 3 php8.2-8.2.26/sapi/phpdbg/phpdbg_info.c | 58 php8.2-8.2.26/sapi/phpdbg/phpdbg_lexer.c | 607 ++----- php8.2-8.2.26/sapi/phpdbg/phpdbg_lexer.l | 2 php8.2-8.2.26/sapi/phpdbg/phpdbg_prompt.c | 2 php8.2-8.2.26/sapi/phpdbg/tests/gh15901.phpt | 10 php8.2-8.2.26/sapi/phpdbg/tests/gh16174.phpt | 10 php8.2-8.2.26/sapi/phpdbg/tests/gh16181.phpt | 26 php8.2-8.2.26/scripts/phpize.m4 | 5 php8.2-8.2.26/tests/basic/gh15905.phpt | 12 332 files changed, 9350 insertions(+), 1713 deletions(-) diff -Nru php8.2-8.2.24/.cirrus.yml php8.2-8.2.26/.cirrus.yml --- php8.2-8.2.24/.cirrus.yml 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.cirrus.yml 2024-11-19 17:11:09.000000000 +0000 @@ -3,6 +3,7 @@ freebsd_task: name: FREEBSD_DEBUG_NTS + skip: "changesIncludeOnly('NEWS', 'EXTENSIONS', 'UPGRADING', 'UPGRADING.INTERNALS', '**.md', 'docs/*', 'docs-old/*', '**/README.*', 'CONTRIBUTING.md', 'CODING_STANDARDS.md')" freebsd_instance: image_family: freebsd-13-3 env: diff -Nru php8.2-8.2.24/.github/CODEOWNERS php8.2-8.2.26/.github/CODEOWNERS --- php8.2-8.2.24/.github/CODEOWNERS 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/CODEOWNERS 2024-11-19 17:11:09.000000000 +0000 @@ -14,7 +14,7 @@ # For more information, see the GitHub CODEOWNERS documentation: # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners -/.github @iluuu1994 @TimWolla +/.github @TimWolla /build/gen_stub.php @kocsismate /ext/bcmath @Girgias @nielsdos @SakiTakamachi /ext/curl @adoy @@ -32,7 +32,7 @@ /ext/mbstring @alexdowad @youkidearitai /ext/mysqlnd @SakiTakamachi /ext/odbc @NattyNarwhal -/ext/opcache @dstogov @iluuu1994 +/ext/opcache @dstogov /ext/openssl @bukka /ext/pcntl @devnexen /ext/pdo @SakiTakamachi @@ -46,6 +46,7 @@ /ext/random @TimWolla @zeriyoshi /ext/session @Girgias /ext/simplexml @nielsdos +/ext/soap @nielsdos /ext/sockets @devnexen /ext/spl @Girgias /ext/standard @bukka @@ -55,26 +56,24 @@ /ext/xsl @nielsdos /main @bukka /sapi/fpm @bukka -/Zend/Optimizer @dstogov @iluuu1994 +/Zend/Optimizer @dstogov /Zend/zend.* @dstogov /Zend/zend_alloc.* @dstogov -/Zend/zend_API.* @dstogov @iluuu1994 +/Zend/zend_API.* @dstogov /Zend/zend_call_stack.* @arnaud-lb /Zend/zend_closures.* @dstogov -/Zend/zend_compile.* @iluuu1994 -/Zend/zend_enum.* @iluuu1994 -/Zend/zend_execute.* @dstogov @iluuu1994 -/Zend/zend_execute_API.c @dstogov @iluuu1994 +/Zend/zend_execute.* @dstogov +/Zend/zend_execute_API.c @dstogov /Zend/zend_gc.* @dstogov @arnaud-lb /Zend/zend_hash.* @dstogov -/Zend/zend_inheritance.* @dstogov @iluuu1994 +/Zend/zend_inheritance.* @dstogov /Zend/zend_max_execution_timer.* @arnaud-lb -/Zend/zend_object_handlers.* @dstogov @iluuu1994 -/Zend/zend_objects.* @dstogov @iluuu1994 -/Zend/zend_objects_API.* @dstogov @iluuu1994 -/Zend/zend_opcode.* @dstogov @iluuu1994 +/Zend/zend_object_handlers.* @dstogov +/Zend/zend_objects.* @dstogov +/Zend/zend_objects_API.* @dstogov +/Zend/zend_opcode.* @dstogov /Zend/zend_string.* @dstogov -/Zend/zend_type*.h @dstogov @iluuu1994 +/Zend/zend_type*.h @dstogov /Zend/zend_variables.* @dstogov -/Zend/zend_vm* @dstogov @iluuu1994 +/Zend/zend_vm* @dstogov *.stub.php @kocsismate diff -Nru php8.2-8.2.24/.github/actions/brew/action.yml php8.2-8.2.26/.github/actions/brew/action.yml --- php8.2-8.2.24/.github/actions/brew/action.yml 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/actions/brew/action.yml 2024-11-19 17:11:09.000000000 +0000 @@ -12,31 +12,16 @@ sudo sed -Ei '' "s/$code.*/$code, overwrite: true\)/" "$formula_installer" brew install \ - pkg-config \ - autoconf \ bison \ re2c brew install \ - openssl@1.1 \ - curl \ - krb5 \ bzip2 \ enchant \ libffi \ - libpng \ - webp \ - freetype \ intltool \ icu4c \ libiconv \ - zlib \ t1lib \ - gd \ - libzip \ - gmp \ - tidy-html5 \ libxml2 \ libjpeg \ - libxslt \ - postgresql - brew link icu4c gettext --force + libxslt diff -Nru php8.2-8.2.24/.github/actions/configure-macos/action.yml php8.2-8.2.26/.github/actions/configure-macos/action.yml --- php8.2-8.2.24/.github/actions/configure-macos/action.yml 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/actions/configure-macos/action.yml 2024-11-19 17:11:09.000000000 +0000 @@ -9,6 +9,7 @@ - shell: bash run: | set -x + BREW_OPT="$(brew --prefix)"/opt export PATH="/usr/local/opt/bison/bin:$PATH" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/openssl@1.1/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/curl/lib/pkgconfig" @@ -18,8 +19,10 @@ export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/libxslt/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/zlib/lib/pkgconfig" export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/icu4c/lib/pkgconfig" + sed -i -e 's/Requires.private:.*//g' "$BREW_OPT/curl/lib/pkgconfig/libcurl.pc" ./buildconf --force ./configure \ + CFLAGS="-Wno-strict-prototypes -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion" \ --enable-option-checking=fatal \ --prefix=/usr/local \ --enable-fpm \ diff -Nru php8.2-8.2.24/.github/actions/configure-x64/action.yml php8.2-8.2.26/.github/actions/configure-x64/action.yml --- php8.2-8.2.24/.github/actions/configure-x64/action.yml 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/actions/configure-x64/action.yml 2024-11-19 17:11:09.000000000 +0000 @@ -3,6 +3,9 @@ configurationParameters: default: '' required: false + asan: + default: false + required: false runs: using: composite steps: diff -Nru php8.2-8.2.24/.github/actions/setup-mssql/action.yml php8.2-8.2.26/.github/actions/setup-mssql/action.yml --- php8.2-8.2.24/.github/actions/setup-mssql/action.yml 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/actions/setup-mssql/action.yml 2024-11-19 17:11:09.000000000 +0000 @@ -11,4 +11,4 @@ -p 1433:1433 \ --name sql1 \ -h sql1 \ - -d mcr.microsoft.com/mssql/server:2019-CU8-ubuntu-16.04 + -d mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04 diff -Nru php8.2-8.2.24/.github/actions/setup-x64/action.yml php8.2-8.2.26/.github/actions/setup-x64/action.yml --- php8.2-8.2.24/.github/actions/setup-x64/action.yml 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/actions/setup-x64/action.yml 2024-11-19 17:11:09.000000000 +0000 @@ -6,15 +6,8 @@ run: | set -x - sudo service mysql start - sudo service postgresql start sudo service slapd start - mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test" - # Ensure local_infile tests can run. - mysql -uroot -proot -e "SET GLOBAL local_infile = true" - sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" - sudo -u postgres psql -c "CREATE DATABASE test;" - docker exec sql1 /opt/mssql-tools/bin/sqlcmd -S 127.0.0.1 -U SA -P "" -Q "create login pdo_test with password='password', check_policy=off; create user pdo_test for login pdo_test; grant alter, control to pdo_test;" + docker exec sql1 /opt/mssql-tools18/bin/sqlcmd -S 127.0.0.1 -U SA -C -P "" -Q "create login pdo_test with password='password', check_policy=off; create user pdo_test for login pdo_test; grant alter, control to pdo_test;" sudo locale-gen de_DE ./.github/scripts/setup-slapd.sh diff -Nru php8.2-8.2.24/.github/actions/test-linux/action.yml php8.2-8.2.26/.github/actions/test-linux/action.yml --- php8.2-8.2.24/.github/actions/test-linux/action.yml 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/actions/test-linux/action.yml 2024-11-19 17:11:09.000000000 +0000 @@ -31,6 +31,10 @@ export PDO_OCI_TEST_USER="system" export PDO_OCI_TEST_PASS="pass" export PDO_OCI_TEST_DSN="oci:dbname=localhost/XEPDB1;charset=AL32UTF8" + export PGSQL_TEST_CONNSTR="host=localhost dbname=test port=5432 user=postgres password=postgres" + if [[ -z "$PDO_PGSQL_TEST_DSN" ]]; then + export PDO_PGSQL_TEST_DSN="pgsql:host=localhost port=5432 dbname=test user=postgres password=postgres" + fi export SKIP_IO_CAPTURE_TESTS=1 sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ -d opcache.jit=${{ inputs.jitType }} \ diff -Nru php8.2-8.2.24/.github/labeler.yml php8.2-8.2.26/.github/labeler.yml --- php8.2-8.2.24/.github/labeler.yml 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/labeler.yml 2024-11-19 17:11:09.000000000 +0000 @@ -241,3 +241,93 @@ "SAPI: phpdbg": - sapi/phpdbg/**/* + +"ABI break": +- 'TSRM/*.h' +- 'Zend/*.h' +- 'Zend/Optimizer/zend_call_graph.h' +- 'Zend/Optimizer/zend_cfg.h' +- 'Zend/Optimizer/zend_dump.h' +- 'Zend/Optimizer/zend_func_info.h' +- 'Zend/Optimizer/zend_inference.h' +- 'Zend/Optimizer/zend_optimizer.h' +- 'Zend/Optimizer/zend_ssa.h' +- 'ext/curl/php_curl.h' +- 'ext/date/lib/timelib.h' +- 'ext/date/lib/timelib_config.h' +- 'ext/date/php_date.h' +- 'ext/dom/xml_common.h' +- 'ext/filter/php_filter.h' +- 'ext/gd/*.h' +- 'ext/gd/libgd/*.h' +- 'ext/gmp/php_gmp_int.h' +- 'ext/hash/php_hash.h' +- 'ext/hash/php_hash_adler32.h' +- 'ext/hash/php_hash_crc32.h' +- 'ext/hash/php_hash_gost.h' +- 'ext/hash/php_hash_haval.h' +- 'ext/hash/php_hash_md.h' +- 'ext/hash/php_hash_murmur.h' +- 'ext/hash/php_hash_ripemd.h' +- 'ext/hash/php_hash_sha.h' +- 'ext/hash/php_hash_sha3.h' +- 'ext/hash/php_hash_snefru.h' +- 'ext/hash/php_hash_tiger.h' +- 'ext/hash/php_hash_whirlpool.h' +- 'ext/hash/php_hash_xxhash.h' +- 'ext/iconv/*.h' +- 'ext/json/php_json.h' +- 'ext/json/php_json_parser.h' +- 'ext/json/php_json_scanner.h' +- 'ext/libxml/php_libxml.h' +- 'ext/mbstring/libmbfl/config.h' +- 'ext/mbstring/libmbfl/mbfl/eaw_table.h' +- 'ext/mbstring/libmbfl/mbfl/mbfilter.h' +- 'ext/mbstring/libmbfl/mbfl/mbfilter_8bit.h' +- 'ext/mbstring/libmbfl/mbfl/mbfilter_pass.h' +- 'ext/mbstring/libmbfl/mbfl/mbfilter_wchar.h' +- 'ext/mbstring/libmbfl/mbfl/mbfl_consts.h' +- 'ext/mbstring/libmbfl/mbfl/mbfl_convert.h' +- 'ext/mbstring/libmbfl/mbfl/mbfl_defs.h' +- 'ext/mbstring/libmbfl/mbfl/mbfl_encoding.h' +- 'ext/mbstring/libmbfl/mbfl/mbfl_filter_output.h' +- 'ext/mbstring/libmbfl/mbfl/mbfl_language.h' +- 'ext/mbstring/libmbfl/mbfl/mbfl_memory_device.h' +- 'ext/mbstring/libmbfl/mbfl/mbfl_string.h' +- 'ext/mbstring/mbstring.h' +- 'ext/mbstring/php_mbregex.h' +- 'ext/mbstring/php_onig_compat.h' +- 'ext/mysqli/php_mysqli_structs.h' +- 'ext/mysqlnd/*.h' +- 'ext/pcre/pcre2lib/*.h' +- 'ext/pcre/php_pcre.h' +- 'ext/pdo/php_pdo.h' +- 'ext/pdo/php_pdo_driver.h' +- 'ext/pdo/php_pdo_error.h' +- 'ext/random/php_random.h' +- 'ext/session/mod_files.h' +- 'ext/session/mod_mm.h' +- 'ext/session/mod_user.h' +- 'ext/session/php_session.h' +- 'ext/simplexml/php_simplexml.h' +- 'ext/simplexml/php_simplexml_exports.h' +- 'ext/sockets/php_sockets.h' +- 'ext/sockets/windows_common.h' +- 'ext/sodium/php_libsodium.h' +- 'ext/spl/php_spl.h' +- 'ext/spl/spl_array.h' +- 'ext/spl/spl_directory.h' +- 'ext/spl/spl_dllist.h' +- 'ext/spl/spl_engine.h' +- 'ext/spl/spl_exceptions.h' +- 'ext/spl/spl_fixedarray.h' +- 'ext/spl/spl_functions.h' +- 'ext/spl/spl_heap.h' +- 'ext/spl/spl_iterators.h' +- 'ext/spl/spl_observer.h' +- 'ext/standard/*.h' +- 'ext/xml/*.h' +- 'main/*.h' +- 'main/streams/*.h' +- 'sapi/embed/php_embed.h' +- 'win32/*.h' diff -Nru php8.2-8.2.24/.github/nightly_matrix.php php8.2-8.2.26/.github/nightly_matrix.php --- php8.2-8.2.24/.github/nightly_matrix.php 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/nightly_matrix.php 2024-11-19 17:11:09.000000000 +0000 @@ -1,23 +1,17 @@ 'master', 'version' => [8, 5]], + ['ref' => 'PHP-8.4', 'version' => [8, 4]], + ['ref' => 'PHP-8.3', 'version' => [8, 3]], + ['ref' => 'PHP-8.2', 'version' => [8, 2]], + ['ref' => 'PHP-8.1', 'version' => [8, 1]], +]; function get_branch_commit_cache_file_path(): string { return dirname(__DIR__) . '/branch-commit-cache.json'; } -function get_branch_matrix(array $branches) { - $result = array_map(function ($branch) { - $branch_key = strtoupper(str_replace('.', '', $branch)); - return [ - 'name' => $branch_key, - 'ref' => $branch, - ]; - }, $branches); - - return $result; -} - function get_branches() { $branch_commit_cache_file = get_branch_commit_cache_file_path(); $branch_commit_map = []; @@ -27,88 +21,45 @@ $changed_branches = []; foreach (BRANCHES as $branch) { - $previous_commit_hash = $branch_commit_map[$branch] ?? null; - $current_commit_hash = trim(shell_exec('git rev-parse origin/' . $branch)); + $previous_commit_hash = $branch_commit_map[$branch['ref']] ?? null; + $current_commit_hash = trim(shell_exec('git rev-parse origin/' . $branch['ref'])); if ($previous_commit_hash !== $current_commit_hash) { $changed_branches[] = $branch; } - $branch_commit_map[$branch] = $current_commit_hash; + $branch_commit_map[$branch['ref']] = $current_commit_hash; } file_put_contents($branch_commit_cache_file, json_encode($branch_commit_map)); - return get_branch_matrix($changed_branches); + return $changed_branches; } -function get_matrix_include(array $branches) { - $jobs = []; - foreach ($branches as $branch) { - $jobs[] = [ - 'name' => '_ASAN_UBSAN', - 'branch' => $branch, - 'debug' => true, - 'zts' => true, - 'configuration_parameters' => "CFLAGS='-fsanitize=undefined,address -DZEND_TRACK_ARENA_ALLOC' LDFLAGS='-fsanitize=undefined,address'", - 'run_tests_parameters' => '--asan', - 'test_function_jit' => false, - ]; - if ($branch['ref'] !== 'PHP-8.0') { - $jobs[] = [ - 'name' => '_REPEAT', - 'branch' => $branch, - 'debug' => true, - 'zts' => false, - 'run_tests_parameters' => '--repeat 2', - 'timeout_minutes' => 360, - 'test_function_jit' => true, - ]; - $jobs[] = [ - 'name' => '_VARIATION', - 'branch' => $branch, - 'debug' => true, - 'zts' => true, - 'configuration_parameters' => "CFLAGS='-DZEND_RC_DEBUG=1 -DPROFITABILITY_CHECKS=0 -DZEND_VERIFY_FUNC_INFO=1'", - 'run_tests_parameters' => '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0', - 'timeout_minutes' => 360, - 'test_function_jit' => true, - ]; - } - } - return $jobs; -} - -function get_windows_matrix_include(array $branches) { - $jobs = []; - foreach ($branches as $branch) { - $jobs[] = [ - 'branch' => $branch, - 'x64' => true, - 'zts' => true, - 'opcache' => true, - ]; - $jobs[] = [ - 'branch' => $branch, - 'x64' => false, - 'zts' => false, - 'opcache' => false, - ]; - } - return $jobs; +function get_current_version(): array { + $file = dirname(__DIR__) . '/main/php_version.h'; + $content = file_get_contents($file); + preg_match('(^#define PHP_MAJOR_VERSION (?\d+)$)m', $content, $matches); + $major = (int) $matches['num']; + preg_match('(^#define PHP_MINOR_VERSION (?\d+)$)m', $content, $matches); + $minor = (int) $matches['num']; + return [$major, $minor]; } $trigger = $argv[1] ?? 'schedule'; $attempt = (int) ($argv[2] ?? 1); -$discard_cache = ($trigger === 'schedule' && $attempt !== 1) || $trigger === 'workflow_dispatch'; +$monday = date('w', time()) === '1'; +$discard_cache = $monday + || ($trigger === 'schedule' && $attempt !== 1) + || $trigger === 'workflow_dispatch'; if ($discard_cache) { @unlink(get_branch_commit_cache_file_path()); } - -$branches = get_branches(); -$matrix_include = get_matrix_include($branches); -$windows_matrix_include = get_windows_matrix_include($branches); - -echo '::set-output name=branches::' . json_encode($branches, JSON_UNESCAPED_SLASHES) . "\n"; -echo '::set-output name=matrix-include::' . json_encode($matrix_include, JSON_UNESCAPED_SLASHES) . "\n"; -echo '::set-output name=windows-matrix-include::' . json_encode($windows_matrix_include, JSON_UNESCAPED_SLASHES) . "\n"; +$branch = $argv[3] ?? 'master'; +$branches = $branch === 'master' + ? get_branches() + : [['ref' => $branch, 'version' => get_current_version()]]; + +$f = fopen(getenv('GITHUB_OUTPUT'), 'a'); +fwrite($f, 'branches=' . json_encode($branches, JSON_UNESCAPED_SLASHES) . "\n"); +fclose($f); diff -Nru php8.2-8.2.24/.github/scripts/windows/test_task.bat php8.2-8.2.26/.github/scripts/windows/test_task.bat --- php8.2-8.2.24/.github/scripts/windows/test_task.bat 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/scripts/windows/test_task.bat 2024-11-19 17:11:09.000000000 +0000 @@ -52,7 +52,12 @@ set PDOTEST_DSN=odbc:%ODBC_TEST_DSN% rem setup Firebird related exts -curl -sLo Firebird.zip https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0_x64.zip +if "%PLATFORM%" == "x64" ( + set PHP_FIREBIRD_DOWNLOAD_URL=https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0_x64.zip +) else ( + set PHP_FIREBIRD_DOWNLOAD_URL=https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0_Win32.zip +) +curl -sLo Firebird.zip %PHP_FIREBIRD_DOWNLOAD_URL% 7z x -oC:\Firebird Firebird.zip set PDO_FIREBIRD_TEST_DATABASE=C:\test.fdb set PDO_FIREBIRD_TEST_DSN=firebird:dbname=%PDO_FIREBIRD_TEST_DATABASE% @@ -98,14 +103,14 @@ if %errorlevel% neq 0 exit /b 3 echo Fetching enchant dicts pushd %~d0\usr\local\share\enchant\hunspell -powershell -Command wget http://windows.php.net/downloads/qa/appveyor/ext/enchant/dict.zip -OutFile dict.zip +powershell -Command wget https://downloads.php.net/~windows/qa/appveyor/ext/enchant/dict.zip -OutFile dict.zip unzip dict.zip del /q dict.zip popd 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 +start %DEPS_DIR%\bin\snmpd.exe -C -c %GITHUB_WORKSPACE%\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 diff -Nru php8.2-8.2.24/.github/workflows/nightly.yml php8.2-8.2.26/.github/workflows/nightly.yml --- php8.2-8.2.24/.github/workflows/nightly.yml 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/workflows/nightly.yml 2024-11-19 17:11:09.000000000 +0000 @@ -1,68 +1,169 @@ -name: Nightly +name: Test suite on: - schedule: - - cron: "0 1 * * *" - workflow_dispatch: ~ + workflow_call: + inputs: + asan_ubuntu_version: + required: true + type: string + branch: + required: true + type: string + community_verify_type_inference: + required: true + type: boolean + libmysqlclient_with_mysqli: + required: true + type: boolean + run_alpine: + required: true + type: boolean + run_macos_arm64: + required: true + type: boolean + ubuntu_version: + required: true + type: string + windows_version: + required: true + type: string +permissions: + contents: read 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 }} - matrix-include: ${{ steps.set-matrix.outputs.matrix-include }} - windows-matrix-include: ${{ steps.set-matrix.outputs.windows-matrix-include }} - steps: - - uses: actions/checkout@v4 - with: - # Set fetch-depth to 0 to clone the full repository - # including all branches. This is required to find - # the correct commit hashes. - fetch-depth: 0 - - name: Grab the commit mapping - uses: actions/cache@v3 - with: - path: branch-commit-cache.json - # The cache key needs to change every time for the - # cache to be updated after this job finishes. - key: nightly-${{ github.run_id }}-${{ github.run_attempt }} - restore-keys: | - nightly- - - name: Generate Matrix - id: set-matrix - run: php .github/nightly_matrix.php "${{ github.event_name }}" "${{ github.run_attempt }}" + ALPINE: + if: inputs.run_alpine + name: ALPINE_X64_ASAN_UBSAN_DEBUG_ZTS + runs-on: ubuntu-22.04 + container: + image: 'alpine:3.20.1' + steps: + - name: git checkout + uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} + - name: apk + uses: ./.github/actions/apk + - name: LLVM 17 (ASAN-only) + # libclang_rt.asan-x86_64.a is provided by compiler-rt, and only for clang17: + # https://pkgs.alpinelinux.org/contents?file=libclang_rt.asan-x86_64.a&path=&name=&branch=v3.20 + run: | + apk add clang17 compiler-rt + - name: System info + run: | + echo "::group::Show host CPU info" + lscpu + echo "::endgroup::" + echo "::group::Show installed package versions" + apk list + echo "::endgroup::" + - name: ./configure + uses: ./.github/actions/configure-alpine + with: + configurationParameters: >- + CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" + LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" + CC=clang-17 + CXX=clang++-17 + --enable-debug + --enable-zts + skipSlow: true # FIXME: This should likely include slow extensions + - name: make + run: make -j$(/usr/bin/nproc) >/dev/null + - name: make install + uses: ./.github/actions/install-alpine + - name: Test Tracing JIT + uses: ./.github/actions/test-alpine + with: + jitType: tracing + runTestsParameters: >- + --asan -x + -d zend_extension=opcache.so + -d opcache.enable_cli=1 - name: Notify Slack if: failure() uses: ./.github/actions/notify-slack with: token: ${{ secrets.ACTION_MONITORING_SLACK }} + LINUX_X64: - needs: GENERATE_MATRIX - if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} + services: + mysql: + image: mysql:8.3 + ports: + - 3306:3306 + env: + MYSQL_DATABASE: test + MYSQL_ROOT_PASSWORD: root + postgres: + image: postgres + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: test + firebird: + image: jacobalberty/firebird + ports: + - 3050:3050 + env: + ISC_PASSWORD: test + FIREBIRD_DATABASE: test.fdb + FIREBIRD_USER: test + FIREBIRD_PASSWORD: test strategy: fail-fast: false matrix: - branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }} configuration_parameters: [''] debug: [true, false] name: [''] run_tests_parameters: [''] test_function_jit: [true] zts: [true, false] - include: ${{ fromJson(needs.GENERATE_MATRIX.outputs.matrix-include) }} - name: "${{ matrix.branch.name }}_LINUX_X64${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" - runs-on: ubuntu-20.04 + include: + - name: _ASAN_UBSAN + debug: true + zts: true + configuration_parameters: >- + CFLAGS="-fsanitize=undefined,address -DZEND_TRACK_ARENA_ALLOC" + LDFLAGS="-fsanitize=undefined,address" + run_tests_parameters: '--asan' + test_function_jit: false + asan: true + - name: _REPEAT + debug: true + zts: false + run_tests_parameters: --repeat 2 + timeout_minutes: 360 + test_function_jit: true + asan: false + - name: _VARIATION + debug: true + zts: true + configuration_parameters: >- + CFLAGS="-DZEND_RC_DEBUG=1 -DPROFITABILITY_CHECKS=0 -DZEND_VERIFY_FUNC_INFO=1 -DZEND_VERIFY_TYPE_INFERENCE" + run_tests_parameters: -d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0 + timeout_minutes: 360 + test_function_jit: true + asan: false + name: "LINUX_X64${{ matrix.name }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" + runs-on: ubuntu-${{ matrix.asan && inputs.asan_ubuntu_version || inputs.ubuntu_version }} steps: - name: git checkout uses: actions/checkout@v4 with: - ref: ${{ matrix.branch.ref }} + ref: ${{ inputs.branch }} - name: Create MSSQL container uses: ./.github/actions/setup-mssql - - name: Create Oracle container - uses: ./.github/actions/setup-oracle - name: apt uses: ./.github/actions/apt-x64 + with: + asan: ${{ matrix.asan && 'true' || 'false' }} + - name: System info + run: | + echo "::group::Show host CPU info" + lscpu + echo "::endgroup::" + echo "::group::Show installed package versions" + dpkg -l + echo "::endgroup::" - name: ./configure uses: ./.github/actions/configure-x64 with: @@ -70,6 +171,7 @@ ${{ matrix.configuration_parameters }} --${{ matrix.debug && 'enable' || 'disable' }}-debug --${{ matrix.zts && 'enable' || 'disable' }}-zts + asan: ${{ matrix.asan && 'true' || 'false' }} - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install @@ -116,25 +218,18 @@ with: token: ${{ secrets.ACTION_MONITORING_SLACK }} LINUX_X32: - needs: GENERATE_MATRIX - if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} strategy: fail-fast: false matrix: - branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }} debug: [true, false] zts: [true, false] - name: "${{ matrix.branch.name }}_LINUX_X32_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" + name: "LINUX_X32_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" runs-on: ubuntu-latest container: - image: ubuntu:20.04 - env: - MYSQL_TEST_HOST: mysql - PDO_MYSQL_TEST_DSN: mysql:host=mysql;dbname=test - PDO_MYSQL_TEST_HOST: mysql + image: ubuntu:${{ inputs.ubuntu_version }} services: mysql: - image: mysql:8 + image: mysql:8.3 ports: - 3306:3306 env: @@ -144,9 +239,17 @@ - name: git checkout uses: actions/checkout@v4 with: - ref: ${{ matrix.branch.ref }} + ref: ${{ inputs.branch }} - name: apt uses: ./.github/actions/apt-x32 + - name: System info + run: | + echo "::group::Show host CPU info" + lscpu + echo "::endgroup::" + echo "::group::Show installed package versions" + dpkg -l + echo "::endgroup::" - name: ./configure uses: ./.github/actions/configure-x32 with: @@ -191,21 +294,21 @@ with: token: ${{ secrets.ACTION_MONITORING_SLACK }} MACOS: - needs: GENERATE_MATRIX - if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} strategy: fail-fast: false matrix: - branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }} debug: [true, false] zts: [true, false] - name: "${{ matrix.branch.name }}_MACOS_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" - runs-on: macos-12 + os: ['13', '14'] + exclude: + - os: ${{ !inputs.run_macos_arm64 && '14' || '*never*' }} + name: "MACOS_${{ matrix.os == '13' && 'X64' || 'ARM64' }}_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" + runs-on: macos-${{ matrix.os }} steps: - name: git checkout uses: actions/checkout@v4 with: - ref: ${{ matrix.branch.ref }} + ref: ${{ inputs.branch }} - name: brew uses: ./.github/actions/brew - name: ./configure @@ -216,35 +319,34 @@ --${{ matrix.zts && 'enable' || 'disable' }}-zts - name: make run: |- - export PATH="/usr/local/opt/bison/bin:$PATH" + export PATH="$(brew --prefix)/opt/bison/bin:$PATH" make -j$(sysctl -n hw.logicalcpu) >/dev/null - name: make install run: sudo make install - name: Test uses: ./.github/actions/test-macos - name: Test Tracing JIT + if: matrix.os != '14' || !matrix.zts uses: ./.github/actions/test-macos with: jitType: tracing runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 - -d opcache.protect_memory=1 - name: Test OpCache uses: ./.github/actions/test-macos with: runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 - -d opcache.protect_memory=1 - name: Test Function JIT + if: matrix.os != '14' || !matrix.zts uses: ./.github/actions/test-macos with: jitType: function runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 - -d opcache.protect_memory=1 - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - name: Notify Slack @@ -253,15 +355,38 @@ with: token: ${{ secrets.ACTION_MONITORING_SLACK }} COVERAGE_DEBUG_NTS: - if: github.repository_owner == 'php' || github.event_name == 'workflow_dispatch' - runs-on: ubuntu-20.04 + if: inputs.branch == 'master' + services: + mysql: + image: mysql:8.3 + ports: + - 3306:3306 + env: + MYSQL_DATABASE: test + MYSQL_ROOT_PASSWORD: root + postgres: + image: postgres + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: test + firebird: + image: jacobalberty/firebird + ports: + - 3050:3050 + env: + ISC_PASSWORD: test + FIREBIRD_DATABASE: test.fdb + FIREBIRD_USER: test + FIREBIRD_PASSWORD: test + runs-on: ubuntu-22.04 steps: - name: git checkout uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} - name: Create MSSQL container uses: ./.github/actions/setup-mssql - - name: Create Oracle container - uses: ./.github/actions/setup-oracle - name: apt uses: ./.github/actions/apt-x64 - name: Install gcovr @@ -280,27 +405,32 @@ - name: Test OpCache uses: ./.github/actions/test-linux with: + jitType: tracing runTestsParameters: >- -d zend_extension=opcache.so -d opcache.enable_cli=1 - - name: Upload Test Coverage to Codecov.io + - uses: codecov/codecov-action@v4 if: always() - run: bash <(curl -s https://codecov.io/bash) + with: + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true - name: Notify Slack if: failure() uses: ./.github/actions/notify-slack with: token: ${{ secrets.ACTION_MONITORING_SLACK }} COMMUNITY: - needs: GENERATE_MATRIX - if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} strategy: fail-fast: false matrix: - branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }} - name: "${{ matrix.branch.name }}_COMMUNITY" - runs-on: ubuntu-20.04 + type: ['asan', 'verify_type_inference'] + exclude: + - type: ${{ !inputs.community_verify_type_inference && 'verify_type_inference' || '*never*' }} + name: "COMMUNITY_${{ matrix.type }}" + runs-on: ubuntu-${{ inputs.ubuntu_version }} env: + ASAN_OPTIONS: exitcode=139 UBSAN_OPTIONS: print_stacktrace=1 USE_ZEND_ALLOC: 0 USE_TRACKED_ALLOC: 1 @@ -308,17 +438,17 @@ - name: git checkout uses: actions/checkout@v4 with: - ref: ${{ matrix.branch.ref }} + ref: ${{ inputs.branch }} - name: apt uses: ./.github/actions/apt-x64 - name: ./configure uses: ./.github/actions/configure-x64 with: + # CFLAGS removes O2, so we have to add it again... configurationParameters: >- - --enable-debug --enable-zts - CFLAGS='-fsanitize=undefined,address -fno-sanitize-recover -DZEND_TRACK_ARENA_ALLOC' - LDFLAGS='-fsanitize=undefined,address' + ${{ matrix.type == 'asan' && '--enable-debug CFLAGS="-fsanitize=undefined,address -fno-sanitize-recover -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address"' || '' }} + ${{ matrix.type == 'verify_type_inference' && 'CFLAGS="-DZEND_VERIFY_TYPE_INFERENCE -O2"' || '' }} - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install @@ -328,14 +458,50 @@ sudo service mysql start mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test" mysql -uroot -proot -e "SET GLOBAL local_infile = true" - - name: Enable Opcache and JIT + - name: Enable Opcache run: | + echo memory_limit=-1 >> /etc/php.d/opcache.ini echo zend_extension=opcache.so > /etc/php.d/opcache.ini echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini + echo opcache.enable=1 >> /etc/php.d/opcache.ini echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini + echo opcache.memory_consumption=256M >> /etc/php.d/opcache.ini + echo opcache.file_update_protection=0 >> /etc/php.d/opcache.ini + echo opcache.interned_strings_buffer=64 >> /etc/php.d/opcache.ini + echo opcache.max_accelerated_files=100000 >> /etc/php.d/opcache.ini + - name: Enable JIT + if: matrix.type != 'verify_type_inference' + run: | + echo opcache.jit=tracing >> /etc/php.d/opcache.ini echo opcache.jit_buffer_size=1G >> /etc/php.d/opcache.ini + echo opcache.jit_max_root_traces=100000 >> /etc/php.d/opcache.ini + echo opcache.jit_max_side_traces=100000 >> /etc/php.d/opcache.ini + echo opcache.jit_max_exit_counters=100000 >> /etc/php.d/opcache.ini + echo opcache.jit_hot_loop=1 >> /etc/php.d/opcache.ini + echo opcache.jit_hot_func=1 >> /etc/php.d/opcache.ini + echo opcache.jit_hot_return=1 >> /etc/php.d/opcache.ini + echo opcache.jit_hot_side_exit=1 >> /etc/php.d/opcache.ini + php -v + - name: Test AMPHP + if: always() + run: | + repositories="amp cache dns file http parallel parser pipeline process serialization socket sync websocket-client websocket-server" + X=0 + for repository in $repositories; do + printf "Testing amp/%s\n" "$repository" + git clone "https://github.com/amphp/$repository.git" "amphp-$repository" --depth 1 + cd "amphp-$repository" + git rev-parse HEAD + php /usr/bin/composer install --no-progress --ignore-platform-reqs + vendor/bin/phpunit || EXIT_CODE=$? + if [ ${EXIT_CODE:-0} -gt 128 ]; then + X=1; + fi + cd .. + done + exit $X - name: Test Laravel - if: matrix.branch.ref != 'PHP-8.0' + if: always() run: | git clone https://github.com/laravel/framework.git --branch=master --depth=1 cd framework @@ -343,13 +509,41 @@ php /usr/bin/composer install --no-progress --ignore-platform-reqs # Hack to disable a test that hangs php -r '$c = file_get_contents("tests/Filesystem/FilesystemTest.php"); $c = str_replace("public function testSharedGet()", "#[\\PHPUnit\\Framework\\Attributes\\Group('"'"'skip'"'"')]\n public function testSharedGet()", $c); file_put_contents("tests/Filesystem/FilesystemTest.php", $c);' - export ASAN_OPTIONS=exitcode=139 php vendor/bin/phpunit --exclude-group skip || EXIT_CODE=$? - if [ $EXIT_CODE -gt 128 ]; then + if [ ${EXIT_CODE:-0} -gt 128 ]; then + exit 1 + fi + - name: Test ReactPHP + if: always() + run: | + repositories="async cache child-process datagram dns event-loop promise promise-stream promise-timer stream" + X=0 + for repository in $repositories; do + printf "Testing reactphp/%s\n" "$repository" + git clone "https://github.com/reactphp/$repository.git" "reactphp-$repository" --depth 1 + cd "reactphp-$repository" + git rev-parse HEAD + php /usr/bin/composer install --no-progress --ignore-platform-reqs + vendor/bin/phpunit || EXIT_CODE=$? + if [ $[EXIT_CODE:-0} -gt 128 ]; then + X=1; + fi + cd .. + done + exit $X + - name: Test Revolt PHP + if: always() + run: | + git clone https://github.com/revoltphp/event-loop.git --depth=1 + cd event-loop + git rev-parse HEAD + php /usr/bin/composer install --no-progress --ignore-platform-reqs + vendor/bin/phpunit || EXIT_CODE=$? + if [ ${EXIT_CODE:-0} -gt 128 ]; then exit 1 fi - name: Test Symfony - if: matrix.branch.ref != 'PHP-8.0' + if: always() run: | git clone https://github.com/symfony/symfony.git --depth=1 cd symfony @@ -360,12 +554,11 @@ php -r '$c = file_get_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php"); $c = str_replace("public function testSanitizeDeepNestedString()", "/** @group skip */\n public function testSanitizeDeepNestedString()", $c); file_put_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php", $c);' # Buggy FFI test in Symfony, see https://github.com/symfony/symfony/issues/47668 php -r '$c = file_get_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php"); $c = str_replace("public function testCastNonTrailingCharPointer()", "/** @group skip */\n public function testCastNonTrailingCharPointer()", $c); file_put_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php", $c);' - export ASAN_OPTIONS=exitcode=139 export SYMFONY_DEPRECATIONS_HELPER=max[total]=999 X=0 for component in $(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -printf '%h\n'); do php ./phpunit $component --exclude-group tty,benchmark,intl-data,transient --exclude-group skip || EXIT_CODE=$? - if [ $EXIT_CODE -gt 128 ]; then + if [ ${EXIT_CODE:-0} -gt 128 ]; then X=1; fi done @@ -376,14 +569,13 @@ git clone https://github.com/sebastianbergmann/phpunit.git --branch=main --depth=1 cd phpunit git rev-parse HEAD - export ASAN_OPTIONS=exitcode=139 php /usr/bin/composer install --no-progress --ignore-platform-reqs php ./phpunit || EXIT_CODE=$? - if [ $EXIT_CODE -gt 128 ]; then + if [ ${EXIT_CODE:-0} -gt 128 ]; then exit 1 fi - name: 'Symfony Preloading' - if: matrix.branch.ref != 'PHP-8.0' + if: always() run: | php /usr/bin/composer create-project symfony/symfony-demo symfony_demo --no-progress --ignore-platform-reqs cd symfony_demo @@ -396,7 +588,6 @@ git clone https://github.com/WordPress/wordpress-develop.git wordpress --depth=1 cd wordpress git rev-parse HEAD - export ASAN_OPTIONS=exitcode=139 php /usr/bin/composer install --no-progress --ignore-platform-reqs cp wp-tests-config-sample.php wp-tests-config.php sed -i 's/youremptytestdbnamehere/test/g' wp-tests-config.php @@ -412,23 +603,38 @@ with: token: ${{ secrets.ACTION_MONITORING_SLACK }} OPCACHE_VARIATION: - needs: GENERATE_MATRIX - if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} - strategy: - fail-fast: false - matrix: - branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }} - name: "${{ matrix.branch.name }}_OPCACHE_VARIATION" - runs-on: ubuntu-20.04 + services: + mysql: + image: mysql:8.3 + ports: + - 3306:3306 + env: + MYSQL_DATABASE: test + MYSQL_ROOT_PASSWORD: root + postgres: + image: postgres + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: test + firebird: + image: jacobalberty/firebird + ports: + - 3050:3050 + env: + ISC_PASSWORD: test + FIREBIRD_DATABASE: test.fdb + FIREBIRD_USER: test + FIREBIRD_PASSWORD: test + name: OPCACHE_VARIATION + runs-on: ubuntu-${{ inputs.ubuntu_version }} steps: - name: git checkout uses: actions/checkout@v4 with: - ref: ${{ matrix.branch.ref }} + ref: ${{ inputs.branch }} - name: Create MSSQL container uses: ./.github/actions/setup-mssql - - name: Create Oracle container - uses: ./.github/actions/setup-oracle - name: apt uses: ./.github/actions/apt-x64 - name: ./configure @@ -488,19 +694,13 @@ with: token: ${{ secrets.ACTION_MONITORING_SLACK }} MSAN: - needs: GENERATE_MATRIX - if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} - strategy: - fail-fast: false - matrix: - branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }} - name: "${{ matrix.branch.name }}_MSAN" - runs-on: ubuntu-22.04 + name: MSAN + runs-on: ubuntu-${{ inputs.ubuntu_version }} steps: - name: git checkout uses: actions/checkout@v4 with: - ref: ${{ matrix.branch.ref }} + ref: ${{ inputs.branch }} - name: apt uses: ./.github/actions/apt-x64 - name: ./configure @@ -547,7 +747,8 @@ --enable-werror \ --enable-memory-sanitizer \ --with-config-file-path=/etc \ - --with-config-file-scan-dir=/etc/php.d + --with-config-file-scan-dir=/etc/php.d \ + --enable-dl-test=shared - name: make run: make -j$(/usr/bin/nproc) >/dev/null - name: make install @@ -585,21 +786,13 @@ with: token: ${{ secrets.ACTION_MONITORING_SLACK }} LIBMYSQLCLIENT: - needs: GENERATE_MATRIX - if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} - strategy: - fail-fast: false - matrix: - branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }} - exclude: - - branch: { name: 'PHP-80', ref: 'PHP-8.0' } - name: "${{ matrix.branch.name }}_LIBMYSQLCLIENT" - runs-on: ubuntu-20.04 + name: LIBMYSQLCLIENT + runs-on: ubuntu-${{ inputs.ubuntu_version }} steps: - name: git checkout uses: actions/checkout@v4 with: - ref: ${{ matrix.branch.ref }} + ref: ${{ inputs.branch }} - name: apt run: | sudo apt-get update -y | true @@ -610,33 +803,26 @@ mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test" # Ensure local_infile tests can run. mysql -uroot -proot -e "SET GLOBAL local_infile = true" - # Does not support caching_sha2_auth :( - # - name: Build mysql-5.6 - # uses: ./.github/actions/build-libmysqlclient - # with: - # libmysql: mysql-5.6.49-linux-glibc2.12-x86_64.tar.gz - # - name: Test mysql-5.6 - # uses: ./.github/actions/test-libmysqlclient - - name: Build mysql-5.7 + - name: Build mysql-8.0 uses: ./.github/actions/build-libmysqlclient with: - libmysql: mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz - withMysqli: ${{ matrix.branch.ref == 'PHP-8.1' }} - - name: Test mysql-5.7 + configurationParameters: ${{ !inputs.libmysqlclient_with_mysqli && '--enable-werror' || '' }} + libmysql: mysql-8.0.37-linux-glibc2.28-x86_64.tar.xz + withMysqli: ${{ inputs.libmysqlclient_with_mysqli }} + - name: Test mysql-8.0 uses: ./.github/actions/test-libmysqlclient with: - withMysqli: ${{ matrix.branch.ref == 'PHP-8.1' }} - - name: Build mysql-8.0 + withMysqli: ${{ inputs.libmysqlclient_with_mysqli }} + - name: Build mysql-8.4 uses: ./.github/actions/build-libmysqlclient with: - # FIXME: There are new warnings - # configurationParameters: --enable-werror - libmysql: mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz - withMysqli: ${{ matrix.branch.ref == 'PHP-8.1' }} - - name: Test mysql-8.0 + configurationParameters: ${{ !inputs.libmysqlclient_with_mysqli && '--enable-werror' || '' }} + libmysql: mysql-8.4.0-linux-glibc2.28-x86_64.tar.xz + withMysqli: ${{ inputs.libmysqlclient_with_mysqli }} + - name: Test mysql-8.4 uses: ./.github/actions/test-libmysqlclient with: - withMysqli: ${{ matrix.branch.ref == 'PHP-8.1' }} + withMysqli: ${{ inputs.libmysqlclient_with_mysqli }} - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files - name: Notify Slack @@ -644,21 +830,137 @@ uses: ./.github/actions/notify-slack with: token: ${{ secrets.ACTION_MONITORING_SLACK }} + PECL: + if: inputs.branch == 'master' + runs-on: ubuntu-22.04 + env: + CC: ccache gcc + CXX: ccache g++ + steps: + - name: git checkout PHP + uses: actions/checkout@v4 + with: + path: php + ref: ${{ inputs.branch }} + - name: git checkout apcu + uses: actions/checkout@v4 + with: + repository: krakjoe/apcu + path: apcu + - name: git checkout imagick + uses: actions/checkout@v4 + with: + repository: Imagick/imagick + path: imagick + - name: git checkout memcached + uses: actions/checkout@v4 + with: + repository: php-memcached-dev/php-memcached + path: memcached + - name: git checkout redis + uses: actions/checkout@v4 + with: + repository: phpredis/phpredis + path: redis + - name: git checkout xdebug + if: false + uses: actions/checkout@v4 + with: + repository: xdebug/xdebug + path: xdebug + - name: git checkout yaml + uses: actions/checkout@v4 + with: + repository: php/pecl-file_formats-yaml + path: yaml + - name: apt + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + ccache \ + libmemcached-dev \ + bison \ + re2c + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: "${{github.job}}-${{hashFiles('php/main/php_version.h')}}" + append-timestamp: false + save: ${{ github.event_name != 'pull_request' }} + - name: build PHP + run: | + cd php + ./buildconf --force + ./configure \ + --enable-option-checking=fatal \ + --prefix=/opt/php \ + --enable-cli \ + --disable-all \ + --enable-session \ + --enable-werror + make -j$(/usr/bin/nproc) + sudo make install + - name: build apcu + run: | + cd apcu + /opt/php/bin/phpize + ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config + make -j$(/usr/bin/nproc) + - name: build imagick + run: | + cd imagick + /opt/php/bin/phpize + ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config + make -j$(/usr/bin/nproc) + - name: build memcached + run: | + cd memcached + /opt/php/bin/phpize + ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config + make -j$(/usr/bin/nproc) + - name: build redis + run: | + cd redis + /opt/php/bin/phpize + ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config + make -j$(/usr/bin/nproc) + - name: build xdebug + if: false + run: | + cd xdebug + /opt/php/bin/phpize + ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config + make -j$(/usr/bin/nproc) + - name: build yaml + run: | + cd yaml + /opt/php/bin/phpize + ./configure --prefix=/opt/php --with-php-config=/opt/php/bin/php-config + make -j$(/usr/bin/nproc) + - name: Notify Slack + if: failure() + uses: ./.github/actions/notify-slack + with: + token: ${{ secrets.ACTION_MONITORING_SLACK }} WINDOWS: - needs: GENERATE_MATRIX - if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} strategy: fail-fast: false matrix: - include: ${{ fromJson(needs.GENERATE_MATRIX.outputs.windows-matrix-include) }} - name: "${{ matrix.branch.name }}_WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" - runs-on: windows-2019 + include: + - x64: true + zts: true + opcache: true + - x64: false + zts: false + opcache: false + name: "WINDOWS_${{ matrix.x64 && 'X64' || 'X86' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" + runs-on: windows-${{ inputs.windows_version }} env: PHP_BUILD_CACHE_BASE_DIR: C:\build-cache PHP_BUILD_OBJ_DIR: C:\obj PHP_BUILD_CACHE_SDK_DIR: C:\build-cache\sdk PHP_BUILD_SDK_BRANCH: php-sdk-2.3.0 - PHP_BUILD_CRT: vs16 + PHP_BUILD_CRT: ${{ inputs.windows_version == '2022' && 'vs17' || 'vs16' }} PLATFORM: ${{ matrix.x64 && 'x64' || 'x86' }} THREAD_SAFE: "${{ matrix.zts && '1' || '0' }}" INTRINSICS: "${{ matrix.zts && 'AVX2' || '' }}" @@ -670,7 +972,7 @@ - name: git checkout uses: actions/checkout@v4 with: - ref: ${{ matrix.branch.ref }} + ref: ${{ inputs.branch }} - name: Setup uses: ./.github/actions/setup-windows - name: Build diff -Nru php8.2-8.2.24/.github/workflows/push.yml php8.2-8.2.26/.github/workflows/push.yml --- php8.2-8.2.24/.github/workflows/push.yml 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/.github/workflows/push.yml 2024-11-19 17:11:09.000000000 +0000 @@ -34,6 +34,7 @@ - .circleci/** branches: - '**' + workflow_dispatch: ~ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.url || github.run_id }} cancel-in-progress: true @@ -43,6 +44,22 @@ jobs: LINUX_X64: if: github.repository == 'php/php-src' || github.event_name == 'pull_request' + services: + mysql: + image: mysql:8.3 + ports: + - 3306:3306 + env: + MYSQL_DATABASE: test + MYSQL_ROOT_PASSWORD: root + postgres: + image: postgres + ports: + - 5432:5432 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: test strategy: fail-fast: false matrix: @@ -142,7 +159,7 @@ -d opcache.enable_cli=1 MACOS_DEBUG_NTS: if: github.repository == 'php/php-src' || github.event_name == 'pull_request' - runs-on: macos-12 + runs-on: macos-13 steps: - name: git checkout uses: actions/checkout@v4 diff -Nru php8.2-8.2.24/.github/workflows/root.yml php8.2-8.2.26/.github/workflows/root.yml --- php8.2-8.2.24/.github/workflows/root.yml 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/.github/workflows/root.yml 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,57 @@ +name: Nightly +on: + schedule: + - cron: "0 1 * * *" + workflow_dispatch: ~ +permissions: + contents: read +jobs: + GENERATE_MATRIX: + name: Generate Matrix + if: github.repository == 'php/php-src' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + outputs: + branches: ${{ steps.set-matrix.outputs.branches }} + steps: + - uses: actions/checkout@v4 + with: + # Set fetch-depth to 0 to clone the full repository + # including all branches. This is required to find + # the correct commit hashes. + fetch-depth: 0 + - name: Grab the commit mapping + uses: actions/cache@v4 + with: + path: branch-commit-cache.json + # The cache key needs to change every time for the + # cache to be updated after this job finishes. + key: nightly-${{ github.run_id }}-${{ github.run_attempt }} + restore-keys: | + nightly- + - name: Generate Matrix + id: set-matrix + run: php .github/nightly_matrix.php "${{ github.event_name }}" "${{ github.run_attempt }}" "${{ github.head_ref || github.ref_name }}" + - name: Notify Slack + if: failure() + uses: ./.github/actions/notify-slack + with: + token: ${{ secrets.ACTION_MONITORING_SLACK }} + NIGHTLY: + needs: GENERATE_MATRIX + name: ${{ matrix.branch.ref }} + if: ${{ needs.GENERATE_MATRIX.outputs.branches != '[]' }} + uses: ./.github/workflows/nightly.yml + strategy: + fail-fast: false + matrix: + branch: ${{ fromJson(needs.GENERATE_MATRIX.outputs.branches) }} + with: + asan_ubuntu_version: '20.04' + branch: ${{ matrix.branch.ref }} + community_verify_type_inference: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} + libmysqlclient_with_mysqli: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1) }} + run_alpine: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} + run_macos_arm64: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9 }} + ubuntu_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 3) || matrix.branch.version[0] >= 9) && '22.04' || '20.04' }} + windows_version: ${{ ((matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 4) || matrix.branch.version[0] >= 9) && '2022' || '2019' }} + secrets: inherit diff -Nru php8.2-8.2.24/EXTENSIONS php8.2-8.2.26/EXTENSIONS --- php8.2-8.2.24/EXTENSIONS 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/EXTENSIONS 2024-11-19 17:11:09.000000000 +0000 @@ -193,7 +193,8 @@ ------------------------------------------------------------------------------- EXTENSION: soap PRIMARY MAINTAINER: Dmitry Stogov (2004 - 2018) -MAINTENANCE: Maintained + Niels Dossche (2024 - 2024) +MAINTENANCE: Odd fixes STATUS: Working ------------------------------------------------------------------------------- EXTENSION: xml diff -Nru php8.2-8.2.24/NEWS php8.2-8.2.26/NEWS --- php8.2-8.2.24/NEWS 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/NEWS 2024-11-19 17:11:09.000000000 +0000 @@ -1,5 +1,296 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +21 Nov 2024, PHP 8.2.26 + +- CLI: + . Fixed bug GH-16373 (Shebang is not skipped for router script in cli-server + started through shebang). (ilutov) + . Fixed bug GHSA-4w77-75f9-2c8w (Heap-Use-After-Free in sapi_read_post_data + Processing in CLI SAPI Interface). (nielsdos) + +- COM: + . Fixed out of bound writes to SafeArray data. (cmb) + +- Core: + . Fixed bug GH-16168 (php 8.1 and earlier crash immediately when compiled + with Xcode 16 clang on macOS 15). (nielsdos) + . Fixed bug GH-16371 (Assertion failure in Zend/zend_weakrefs.c:646). (Arnaud) + . Fixed bug GH-16515 (Incorrect propagation of ZEND_ACC_RETURN_REFERENCE for + call trampoline). (ilutov) + . Fixed bug GH-16509 (Incorrect line number in function redeclaration error). + (ilutov) + . Fixed bug GH-16508 (Incorrect line number in inheritance errors of delayed + early bound classes). (ilutov) + . Fixed bug GH-16648 (Use-after-free during array sorting). (ilutov) + +- Curl: + . Fixed bug GH-16302 (CurlMultiHandle holds a reference to CurlHandle if + curl_multi_add_handle fails). (timwolla) + +- Date: + . Fixed bug GH-16454 (Unhandled INF in date_sunset() with tiny $utcOffset). + (cmb) + . Fixed bug GH-16037 (Assertion failure in ext/date/php_date.c). (Derick) + . Fixed bug GH-14732 (date_sun_info() fails for non-finite values). (cmb) + +- DBA: + . Fixed bug GH-16390 (dba_open() can segfault for "pathless" streams). (cmb) + +- DOM: + . Fixed bug GH-16316 (DOMXPath breaks when not initialized properly). + (nielsdos) + . Fixed bug GH-16473 (dom_import_simplexml stub is wrong). (nielsdos) + . Fixed bug GH-16533 (Segfault when adding attribute to parent that is not + an element). (nielsdos) + . Fixed bug GH-16535 (UAF when using document as a child). (nielsdos) + . Fixed bug GH-16593 (Assertion failure in DOM->replaceChild). (nielsdos) + . Fixed bug GH-16595 (Another UAF in DOM -> cloneNode). (nielsdos) + +- EXIF: + . Fixed bug GH-16409 (Segfault in exif_thumbnail when not dealing with a + real file). (nielsdos, cmb) + +- FFI: + . Fixed bug GH-16397 (Segmentation fault when comparing FFI object). + (nielsdos) + +- Filter: + . Fixed bug GH-16523 (FILTER_FLAG_HOSTNAME accepts ending hyphen). (cmb) + +- FPM: + . Fixed bug GH-16628 (FPM logs are getting corrupted with this log + statement). (nielsdos) + +- GD: + . Fixed bug GH-16334 (imageaffine overflow on matrix elements). + (David Carlier) + . Fixed bug GH-16427 (Unchecked libavif return values). (cmb) + . Fixed bug GH-16559 (UBSan abort in ext/gd/libgd/gd_interpolation.c:1007). + (nielsdos) + +- GMP: + . Fixed floating point exception bug with gmp_pow when using + large exposant values. (David Carlier). + . Fixed bug GH-16411 (gmp_export() can cause overflow). (cmb) + . Fixed bug GH-16501 (gmp_random_bits() can cause overflow). + (David Carlier) + . Fixed gmp_pow() overflow bug with large base/exponents. + (David Carlier) + . Fixed segfaults and other issues related to operator overloading with + GMP objects. (Girgias) + +- LDAP: + . Fixed bug GHSA-g665-fm4p-vhff (OOB access in ldap_escape). (CVE-2024-8932) + (nielsdos) + +- MBstring: + . Fixed bug GH-16361 (mb_substr overflow on start/length arguments). + (David Carlier) + +- MySQLnd: + . Fixed bug GHSA-h35g-vwh6-m678 (Leak partial content of the heap through + heap buffer over-read). (CVE-2024-8929) (Jakub Zelenka) + +- OpenSSL: + . Fixed bug GH-16357 (openssl may modify member types of certificate arrays). + (cmb) + . Fixed bug GH-16433 (Large values for openssl_csr_sign() $days overflow). + (cmb) + . Fix various memory leaks on error conditions in openssl_x509_parse(). + (nielsdos) + +- PDO DBLIB: + . Fixed bug GHSA-5hqh-c84r-qjcv (Integer overflow in the dblib quoter causing + OOB writes). (CVE-2024-11236) (nielsdos) + +- PDO Firebird: + . Fixed bug GHSA-5hqh-c84r-qjcv (Integer overflow in the firebird quoter + causing OOB writes). (CVE-2024-11236) (nielsdos) + +- PDO ODBC: + . Fixed bug GH-16450 (PDO_ODBC can inject garbage into field values). (cmb) + +- Phar: + . Fixed bug GH-16406 (Assertion failure in ext/phar/phar.c:2808). (nielsdos) + +- PHPDBG: + . Fixed bug GH-16174 (Empty string is an invalid expression for ev). (cmb) + +- Reflection: + . Fixed bug GH-16601 (Memory leak in Reflection constructors). (nielsdos) + +- Session: + . Fixed bug GH-16385 (Unexpected null returned by session_set_cookie_params). + (nielsdos) + . Fixed bug GH-16290 (overflow on cookie_lifetime ini value). + (David Carlier) + +- SOAP: + . Fixed bug GH-16429 (Segmentation fault access null pointer in SoapClient). + (nielsdos) + +- Sockets: + . Fixed bug with overflow socket_recvfrom $length argument. (David Carlier) + +- SPL: + . Fixed bug GH-16337 (Use-after-free in SplHeap). (nielsdos) + . Fixed bug GH-16464 (Use-after-free in SplDoublyLinkedList::offsetSet()). + (ilutov) + . Fixed bug GH-16479 (Use-after-free in SplObjectStorage::setInfo()). (ilutov) + . Fixed bug GH-16478 (Use-after-free in SplFixedArray::unset()). (ilutov) + . Fixed bug GH-16588 (UAF in Observer->serialize). (nielsdos) + . Fix GH-16477 (Segmentation fault when calling __debugInfo() after failed + SplFileObject::__constructor). (Girgias) + . Fixed bug GH-16589 (UAF in SplDoublyLinked->serialize()). (nielsdos) + . Fixed bug GH-14687 (segfault on SplObjectIterator instance). + (David Carlier) + . Fixed bug GH-16604 (Memory leaks in SPL constructors). (nielsdos) + . Fixed bug GH-16646 (UAF in ArrayObject::unset() and + ArrayObject::exchangeArray()). (ilutov) + +- Standard: + . Fixed bug GH-16293 (Failed assertion when throwing in assert() callback with + bail enabled). (ilutov) + +- Streams: + . Fixed bug GHSA-c5f2-jwm7-mmq2 (Configuring a proxy in a stream context + might allow for CRLF injection in URIs). (CVE-2024-11234) (Jakub Zelenka) + . Fixed bug GHSA-r977-prxv-hc43 (Single byte overread with + convert.quoted-printable-decode filter). (CVE-2024-11233) (nielsdos) + +- SysVMsg: + . Fixed bug GH-16592 (msg_send() crashes when a type does not properly + serialized). (David Carlier / cmb) + +- SysVShm: + . Fixed bug GH-16591 (Assertion error in shm_put_var). (nielsdos, cmb) + +- XMLReader: + . Fixed bug GH-16292 (Segmentation fault in ext/xmlreader/php_xmlreader.c). + (nielsdos) + +- Zlib: + . Fixed bug GH-16326 (Memory management is broken for bad dictionaries.) + (cmb) + +24 Oct 2024, PHP 8.2.25 + +- Calendar: + . Fixed GH-16240: jdtounix overflow on argument value. (David Carlier) + . Fixed GH-16241: easter_days/easter_date overflow on year argument. + (David Carlier) + . Fixed GH-16263: jddayofweek overflow. (cmb) + . Fixed GH-16234: jewishtojd overflow. (nielsdos) + +- CLI: + . Fixed bug GH-16137: duplicate http headers when set several times by + the client. (David Carlier) + +- Core: + . Fixed bug GH-15712: zend_strtod overflow with precision INI set on + large value. (David Carlier) + . Fixed bug GH-15905 (Assertion failure for TRACK_VARS_SERVER). (cmb) + . Fixed bug GH-15907 (Failed assertion when promoting Serialize deprecation to + exception). (ilutov) + . Fixed bug GH-15851 (Segfault when printing backtrace during cleanup of + nested generator frame). (ilutov) + . Fixed bug GH-15866 (Core dumped in Zend/zend_generators.c). (Arnaud) + . Fixed bug GH-16188 (Assertion failure in Zend/zend_exceptions.c). (Arnaud) + . Fixed bug GH-16233 (Observer segfault when calling user function in + internal function via trampoline). (nielsdos) + +- Date: + . Fixed bug GH-15582: Crash when not calling parent constructor of + DateTimeZone. (Derick) + . Fixed regression where signs after the first one were ignored while parsing + a signed integer, with the DateTimeInterface::modify() function. (Derick) + +- DOM: + . Fixed bug GH-16039 (Segmentation fault (access null pointer) in + ext/dom/parentnode/tree.c). (nielsdos) + . Fixed bug GH-16151 (Assertion failure in ext/dom/parentnode/tree.c). + (nielsdos) + +- GD: + . Fixed bug GH-16232 (bitshift overflow on wbmp file content reading / + fix backport from upstream). (David Carlier) + . Fixed bug GH-12264 (overflow/underflow on imagerotate degrees value) + (David Carlier) + . Fixed bug GH-16274 (imagescale underflow on RBG channels / + fix backport from upstream). (David Carlier) + +- LDAP: + . Fixed bug GH-16032 (Various NULL pointer dereferencements in + ldap_modify_batch()). (Girgias) + . Fixed bug GH-16101 (Segfault in ldap_list(), ldap_read(), and ldap_search() + when LDAPs array is not a list). (Girgias) + . Fix GH-16132 (php_ldap_do_modify() attempts to free pointer not allocated + by ZMM.). (Girgias) + . Fix GH-16136 (Memory leak in php_ldap_do_modify() when entry is not a + proper dictionary). (Girgias) + +- MBString: + . Fixed bug GH-16261 (Reference invariant broken in mb_convert_variables()). + (nielsdos) + +- OpenSSL: + . Fixed stub for openssl_csr_new. (Jakub Zelenka) + +- PCRE: + . Fixed bug GH-16189 (underflow on offset argument). (David Carlier) + . Fixed bug GH-16184 (UBSan address overflowed in ext/pcre/php_pcre.c). + (nielsdos) + +- PHPDBG: + . Fixed bug GH-15901 (phpdbg: Assertion failure on i funcs). (cmb) + . Fixed bug GH-16181 (phpdbg: exit in exception handler reports fatal error). + (cmb) + +- Reflection: + . Fixed bug GH-16187 (Assertion failure in ext/reflection/php_reflection.c). + (DanielEScherzer) + +- SAPI: + . Fixed bug GH-15395 (php-fpm: zend_mm_heap corrupted with cgi-fcgi request). + (Jakub Zelenka, David Carlier) + +- SimpleXML: + . Fixed bug GH-15837 (Segmentation fault in ext/simplexml/simplexml.c). + (nielsdos) + +- Sockets: + . Fixed bug GH-16267 (socket_strerror overflow on errno argument). + (David Carlier) + +- SOAP: + . Fixed bug #62900 (Wrong namespace on xsd import error message). (nielsdos) + . Fixed bug GH-16237 (Segmentation fault when cloning SoapServer). (nielsdos) + . Fix Soap leaking http_msg on error. (nielsdos) + . Fixed bug GH-16256 (Assertion failure in ext/soap/php_encoding.c:460). + (nielsdos) + . Fixed bug GH-16259 (Soap segfault when classmap instantiation fails). + (nielsdos) + +- Standard: + . Fixed bug GH-15613 (overflow on unpack call hex string repeater). + (David Carlier) + . Fixed bug GH-15937 (overflow on stream timeout option value). + (David Carlier) + . Fixed bug GH-16053 (Assertion failure in Zend/zend_hash.c). (Arnaud) + +- Streams: + . Fixed bugs GH-15908 and GH-15026 (leak / assertion failure in streams.c). + (nielsdos) + . Fixed bug GH-15980 (Signed integer overflow in main/streams/streams.c). + (cmb) + +- TSRM: + . Prevent closing of unrelated handles. (cmb) + +- XML: + . Fixed bug GH-15868 (Assertion failure in xml_parse_into_struct after + exception). (nielsdos) + 26 Sep 2024, PHP 8.2.24 - CGI: diff -Nru php8.2-8.2.24/TSRM/tsrm_win32.c php8.2-8.2.26/TSRM/tsrm_win32.c --- php8.2-8.2.24/TSRM/tsrm_win32.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/TSRM/tsrm_win32.c 2024-11-19 17:11:09.000000000 +0000 @@ -707,6 +707,7 @@ if (NULL != shm->descriptor && (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz)) { if (NULL != shm->segment) { CloseHandle(shm->segment); + shm->segment = INVALID_HANDLE_VALUE; } UnmapViewOfFile(shm->descriptor); shm->descriptor = NULL; diff -Nru php8.2-8.2.24/Zend/Optimizer/zend_inference.c php8.2-8.2.26/Zend/Optimizer/zend_inference.c --- php8.2-8.2.24/Zend/Optimizer/zend_inference.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/Optimizer/zend_inference.c 2024-11-19 17:11:09.000000000 +0000 @@ -3895,6 +3895,9 @@ } else { zend_arg_info *ret_info = op_array->arg_info - 1; tmp = zend_fetch_arg_info_type(script, ret_info, &ce); + if ((tmp & MAY_BE_NULL) && opline->op1_type == IS_CV) { + tmp |= MAY_BE_UNDEF; + } tmp |= (t1 & MAY_BE_INDIRECT); // TODO: We could model more precisely how illegal types are converted. diff -Nru php8.2-8.2.24/Zend/tests/generators/gh15851.phpt php8.2-8.2.26/Zend/tests/generators/gh15851.phpt --- php8.2-8.2.24/Zend/tests/generators/gh15851.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/generators/gh15851.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,27 @@ +--TEST-- +GH-15851: Access on NULL when printing backtrace with freed generator +--FILE-- + +--EXPECTF-- +#0 %s(%d): Foo->__destruct() +#1 %s(%d): bar() diff -Nru php8.2-8.2.24/Zend/tests/gh15712.phpt php8.2-8.2.26/Zend/tests/gh15712.phpt --- php8.2-8.2.24/Zend/tests/gh15712.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh15712.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,9 @@ +--TEST-- +GH-15712: overflow on real number printing +--FILE-- + +--EXPECTF-- +%s diff -Nru php8.2-8.2.24/Zend/tests/gh15866.phpt php8.2-8.2.26/Zend/tests/gh15866.phpt --- php8.2-8.2.24/Zend/tests/gh15866.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh15866.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GH-15866: Core dumped in Zend/zend_generators.c +--FILE-- +next(); + } finally { + print "Fiber finally\n"; + } +}); +$canary->value = $fiber; +$fiber->start(); + +// Reset roots +gc_collect_cycles(); + +// Add to roots, create garbage cycles +$fiber = $iterable = $canary = null; + +print "Collect cycles\n"; +gc_collect_cycles(); + +?> +==DONE== +--EXPECT-- +Collect cycles +Canary::__destruct +Generator finally +Fiber finally +==DONE== diff -Nru php8.2-8.2.24/Zend/tests/gh15907.phpt php8.2-8.2.26/Zend/tests/gh15907.phpt --- php8.2-8.2.24/Zend/tests/gh15907.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh15907.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,18 @@ +--TEST-- +GH-15907: Failed assertion when promoting inheritance error to exception +--FILE-- + +--EXPECTF-- +Fatal error: During inheritance of C, while implementing Serializable: Uncaught Exception: C implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s:%d +%a diff -Nru php8.2-8.2.24/Zend/tests/gh16188.phpt php8.2-8.2.26/Zend/tests/gh16188.phpt --- php8.2-8.2.24/Zend/tests/gh16188.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh16188.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,34 @@ +--TEST-- +GH-16188 (Assertion failure in Zend/zend_exceptions.c) +--FILE-- +getTraceAsString()); +printf("getPrevious:\n%s\n\n", get_class($re->getPrevious())); +printf("__toString:\n%s\n\n", $re); + +?> +==DONE== +--EXPECTF-- +getTraceAsString: +#0 {main} + +getPrevious: +Exception + +__toString: +Exception in %s:%d +Stack trace:%A +#%d {main} + +Next TypeError in %s:%d +Stack trace:%A +#%d {main} + +==DONE== diff -Nru php8.2-8.2.24/Zend/tests/gh16293_001.phpt php8.2-8.2.26/Zend/tests/gh16293_001.phpt --- php8.2-8.2.24/Zend/tests/gh16293_001.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh16293_001.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,19 @@ +--TEST-- +GH-16293: Exception in assert() callback with bail enabled +--FILE-- + +--EXPECTF-- +Warning: assert(): assert(false) failed in %s on line %d + +Warning: Uncaught Error: Invalid callback f1, function "f1" not found or invalid function name in %s:%d +Stack trace: +#0 %s(%d): assert(false, 'assert(false)') +#1 {main} + thrown in %s on line %d diff -Nru php8.2-8.2.24/Zend/tests/gh16293_002.phpt php8.2-8.2.26/Zend/tests/gh16293_002.phpt --- php8.2-8.2.24/Zend/tests/gh16293_002.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh16293_002.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,19 @@ +--TEST-- +GH-16293: Exception in assert() callback with bail enabled +--FILE-- + +--EXPECTF-- +Warning: assert(): assert(false) failed in %s on line %d + +Warning: Uncaught Exception: Boo in %s:%d +Stack trace: +%a diff -Nru php8.2-8.2.24/Zend/tests/gh16371.phpt php8.2-8.2.26/Zend/tests/gh16371.phpt --- php8.2-8.2.24/Zend/tests/gh16371.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh16371.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,47 @@ +--TEST-- +GH-16371: Assertion failure in zend_weakmap_iterator_get_current_key() for invalid iterator +--FILE-- +getIterator(); + +print "# Empty WeakMap\n"; + +var_dump($it->key()); +var_dump($it->current()); +var_dump($it->valid()); + +$map = new WeakMap(); +$obj = new stdClass; +$map[$obj] = 0; + +print "# Valid iterator\n"; + +$it = $map->getIterator(); +var_dump($it->key()); +var_dump($it->current()); +var_dump($it->valid()); + +print "# End of iterator\n"; + +$it->next(); +var_dump($it->key()); +var_dump($it->current()); +var_dump($it->valid()); + +?> +--EXPECTF-- +# Empty WeakMap +NULL +NULL +bool(false) +# Valid iterator +object(stdClass)#%d (0) { +} +int(0) +bool(true) +# End of iterator +NULL +NULL +bool(false) diff -Nru php8.2-8.2.24/Zend/tests/gh16508.phpt php8.2-8.2.26/Zend/tests/gh16508.phpt --- php8.2-8.2.24/Zend/tests/gh16508.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh16508.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,20 @@ +--TEST-- +GH-16508: Missing lineno in inheritance errors of delayed early bound classes +--EXTENSIONS-- +opcache +--INI-- +opcache.enable_cli=1 +--FILE-- + +--EXPECTF-- +Fatal error: Class Test2 contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Test::foo) in %s on line 5 diff -Nru php8.2-8.2.24/Zend/tests/gh16509.inc php8.2-8.2.26/Zend/tests/gh16509.inc --- php8.2-8.2.24/Zend/tests/gh16509.inc 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh16509.inc 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,7 @@ + +--EXPECTF-- +Fatal error: Cannot redeclare test() (previously declared in %sgh16509.inc:3) in %sgh16509.inc on line 3 diff -Nru php8.2-8.2.24/Zend/tests/gh16515.phpt php8.2-8.2.26/Zend/tests/gh16515.phpt --- php8.2-8.2.24/Zend/tests/gh16515.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh16515.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,16 @@ +--TEST-- +GH-16515: Incorrect propagation of ZEND_ACC_RETURN_REFERENCE for call trampoline +--FILE-- +bar(...)); + +?> +--EXPECTF-- +Notice: Only variable references should be returned by reference in %s on line %d diff -Nru php8.2-8.2.24/Zend/tests/gh16648.phpt php8.2-8.2.26/Zend/tests/gh16648.phpt --- php8.2-8.2.24/Zend/tests/gh16648.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/Zend/tests/gh16648.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,49 @@ +--TEST-- +GH-16648: Use-after-free during array sorting +--FILE-- + '1', '3' => new C, '2' => '2']; +asort($arr); +var_dump($arr); + +?> +--EXPECT-- +array(11) { + ["a"]=> + string(1) "1" + [3]=> + int(3) + [2]=> + int(2) + [0]=> + int(0) + [1]=> + int(1) + [4]=> + int(4) + [5]=> + int(5) + [6]=> + int(6) + [7]=> + int(7) + [8]=> + int(8) + [9]=> + int(9) +} diff -Nru php8.2-8.2.24/Zend/zend.c php8.2-8.2.26/Zend/zend.c --- php8.2-8.2.24/Zend/zend.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend.c 2024-11-19 17:11:09.000000000 +0000 @@ -803,6 +803,8 @@ executor_globals->record_errors = false; executor_globals->num_errors = 0; executor_globals->errors = NULL; + executor_globals->filename_override = NULL; + executor_globals->lineno_override = -1; #ifdef ZEND_MAX_EXECUTION_TIMERS executor_globals->pid = 0; executor_globals->oldact = (struct sigaction){0}; diff -Nru php8.2-8.2.24/Zend/zend.h php8.2-8.2.26/Zend/zend.h --- php8.2-8.2.24/Zend/zend.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend.h 2024-11-19 17:11:09.000000000 +0000 @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.24" +#define ZEND_VERSION "4.2.26" #define ZEND_ENGINE_3 diff -Nru php8.2-8.2.24/Zend/zend_builtin_functions.c php8.2-8.2.26/Zend/zend_builtin_functions.c --- php8.2-8.2.24/Zend/zend_builtin_functions.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_builtin_functions.c 2024-11-19 17:11:09.000000000 +0000 @@ -1725,6 +1725,16 @@ } while (call && (limit == 0 || frameno < limit)) { + if (UNEXPECTED(!call->func)) { + /* This is the fake frame inserted for nested generators. Normally, + * this frame is preceded by the actual generator frame and then + * replaced by zend_generator_check_placeholder_frame() below. + * However, the frame is popped before cleaning the stack frame, + * which is observable by destructors. */ + call = zend_generator_check_placeholder_frame(call); + ZEND_ASSERT(call->func); + } + zend_execute_data *prev = call->prev_execute_data; if (!prev) { diff -Nru php8.2-8.2.24/Zend/zend_closures.c php8.2-8.2.26/Zend/zend_closures.c --- php8.2-8.2.24/Zend/zend_closures.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_closures.c 2024-11-19 17:11:09.000000000 +0000 @@ -845,7 +845,7 @@ memset(&trampoline, 0, sizeof(zend_internal_function)); trampoline.type = ZEND_INTERNAL_FUNCTION; - trampoline.fn_flags = mptr->common.fn_flags & ZEND_ACC_STATIC; + trampoline.fn_flags = mptr->common.fn_flags & (ZEND_ACC_STATIC|ZEND_ACC_RETURN_REFERENCE); trampoline.handler = zend_closure_call_magic; trampoline.function_name = mptr->common.function_name; trampoline.scope = mptr->common.scope; diff -Nru php8.2-8.2.24/Zend/zend_compile.c php8.2-8.2.26/Zend/zend_compile.c --- php8.2-8.2.24/Zend/zend_compile.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_compile.c 2024-11-19 17:11:09.000000000 +0000 @@ -1072,7 +1072,7 @@ zend_error_noreturn(error_level, "Cannot redeclare %s() (previously declared in %s:%d)", op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name), ZSTR_VAL(old_function->op_array.filename), - old_function->op_array.opcodes[0].lineno); + old_function->op_array.line_start); } else { zend_error_noreturn(error_level, "Cannot redeclare %s()", op_array ? ZSTR_VAL(op_array->function_name) : ZSTR_VAL(old_function->common.function_name)); @@ -7516,6 +7516,7 @@ } else if (toplevel) { /* Only register the function after a successful compile */ if (UNEXPECTED(zend_hash_add_ptr(CG(function_table), lcname, op_array) == NULL)) { + CG(zend_lineno) = decl->start_lineno; do_bind_function_error(lcname, op_array, true); } } diff -Nru php8.2-8.2.24/Zend/zend_exceptions.c php8.2-8.2.26/Zend/zend_exceptions.c --- php8.2-8.2.24/Zend/zend_exceptions.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_exceptions.c 2024-11-19 17:11:09.000000000 +0000 @@ -115,15 +115,18 @@ ex = &zv; do { ancestor = zend_read_property_ex(i_get_exception_base(add_previous), add_previous, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv); + ZVAL_DEREF(ancestor); while (Z_TYPE_P(ancestor) == IS_OBJECT) { if (Z_OBJ_P(ancestor) == Z_OBJ_P(ex)) { OBJ_RELEASE(add_previous); return; } ancestor = zend_read_property_ex(i_get_exception_base(Z_OBJ_P(ancestor)), Z_OBJ_P(ancestor), ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv); + ZVAL_DEREF(ancestor); } base_ce = i_get_exception_base(Z_OBJ_P(ex)); previous = zend_read_property_ex(base_ce, Z_OBJ_P(ex), ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv); + ZVAL_DEREF(previous); if (Z_TYPE_P(previous) == IS_NULL) { zend_update_property_ex(base_ce, Z_OBJ_P(ex), ZSTR_KNOWN(ZEND_STR_PREVIOUS), &pv); GC_DELREF(add_previous); @@ -630,6 +633,7 @@ RETURN_THROWS(); } + ZVAL_DEREF(trace); /* Type should be guaranteed by property type. */ ZEND_ASSERT(Z_TYPE_P(trace) == IS_ARRAY); RETURN_NEW_STR(zend_trace_to_string(Z_ARRVAL_P(trace), /* include_main */ true)); @@ -643,7 +647,7 @@ ZEND_PARSE_PARAMETERS_NONE(); - ZVAL_COPY(return_value, GET_PROPERTY_SILENT(ZEND_THIS, ZEND_STR_PREVIOUS)); + ZVAL_COPY_DEREF(return_value, GET_PROPERTY_SILENT(ZEND_THIS, ZEND_STR_PREVIOUS)); } /* }}} */ /* {{{ Obtain the string representation of the Exception object */ @@ -723,7 +727,8 @@ Z_PROTECT_RECURSION_P(exception); exception = GET_PROPERTY(exception, ZEND_STR_PREVIOUS); - if (exception && Z_TYPE_P(exception) == IS_OBJECT && Z_IS_RECURSIVE_P(exception)) { + ZVAL_DEREF(exception); + if (Z_TYPE_P(exception) == IS_OBJECT && Z_IS_RECURSIVE_P(exception)) { break; } } @@ -731,13 +736,14 @@ exception = ZEND_THIS; /* Reset apply counts */ - while (exception && Z_TYPE_P(exception) == IS_OBJECT && (base_ce = i_get_exception_base(Z_OBJ_P(exception))) && instanceof_function(Z_OBJCE_P(exception), base_ce)) { + while (Z_TYPE_P(exception) == IS_OBJECT && (base_ce = i_get_exception_base(Z_OBJ_P(exception))) && instanceof_function(Z_OBJCE_P(exception), base_ce)) { if (Z_IS_RECURSIVE_P(exception)) { Z_UNPROTECT_RECURSION_P(exception); } else { break; } exception = GET_PROPERTY(exception, ZEND_STR_PREVIOUS); + ZVAL_DEREF(exception); } exception = ZEND_THIS; diff -Nru php8.2-8.2.24/Zend/zend_generators.c php8.2-8.2.26/Zend/zend_generators.c --- php8.2-8.2.24/Zend/zend_generators.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_generators.c 2024-11-19 17:11:09.000000000 +0000 @@ -218,43 +218,30 @@ } } -/* In the context of zend_generator_dtor_storage during shutdown, check if - * the intermediate node 'generator' is running in a fiber */ +/* Check if the node 'generator' is running in a fiber */ static inline bool check_node_running_in_fiber(zend_generator *generator) { - ZEND_ASSERT(EG(flags) & EG_FLAGS_IN_SHUTDOWN); ZEND_ASSERT(generator->execute_data); - if (generator->flags & ZEND_GENERATOR_IN_FIBER) { + if (EXPECTED(generator->flags & ZEND_GENERATOR_IN_FIBER)) { return true; } - if (generator->node.children == 0) { + if (EXPECTED(generator->node.children == 0)) { return false; } - if (generator->flags & ZEND_GENERATOR_DTOR_VISITED) { - return false; - } - generator->flags |= ZEND_GENERATOR_DTOR_VISITED; - if (generator->node.children == 1) { - if (check_node_running_in_fiber(generator->node.child.single)) { - goto in_fiber; - } - return false; + return check_node_running_in_fiber(generator->node.child.single); } zend_generator *child; ZEND_HASH_FOREACH_PTR(generator->node.child.ht, child) { if (check_node_running_in_fiber(child)) { - goto in_fiber; + return true; } } ZEND_HASH_FOREACH_END(); - return false; -in_fiber: - generator->flags |= ZEND_GENERATOR_IN_FIBER; - return true; + return false; } static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ diff -Nru php8.2-8.2.24/Zend/zend_generators.h php8.2-8.2.26/Zend/zend_generators.h --- php8.2-8.2.24/Zend/zend_generators.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_generators.h 2024-11-19 17:11:09.000000000 +0000 @@ -93,7 +93,6 @@ static const zend_uchar ZEND_GENERATOR_AT_FIRST_YIELD = 0x4; static const zend_uchar ZEND_GENERATOR_DO_INIT = 0x8; static const zend_uchar ZEND_GENERATOR_IN_FIBER = 0x10; -static const zend_uchar ZEND_GENERATOR_DTOR_VISITED = 0x20; void zend_register_generator_ce(void); ZEND_API void zend_generator_close(zend_generator *generator, bool finished_execution); diff -Nru php8.2-8.2.24/Zend/zend_hash.c php8.2-8.2.26/Zend/zend_hash.c --- php8.2-8.2.24/Zend/zend_hash.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_hash.c 2024-11-19 17:11:09.000000000 +0000 @@ -2863,13 +2863,12 @@ q->h = h; } -ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, bucket_compare_func_t compar, bool renumber) +static void zend_hash_sort_internal(HashTable *ht, sort_func_t sort, bucket_compare_func_t compar, bool renumber) { Bucket *p; uint32_t i, j; IS_CONSISTENT(ht); - HT_ASSERT_RC1(ht); if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */ @@ -2956,6 +2955,33 @@ } } +ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, bucket_compare_func_t compar, bool renumber) +{ + HT_ASSERT_RC1(ht); + zend_hash_sort_internal(ht, sort, compar, renumber); +} + +void ZEND_FASTCALL zend_array_sort_ex(HashTable *ht, sort_func_t sort, bucket_compare_func_t compar, bool renumber) +{ + HT_ASSERT_RC1(ht); + + /* Unpack the array early to avoid RCn assertion failures. */ + if (HT_IS_PACKED(ht)) { + zend_hash_packed_to_hash(ht); + } + + /* Adding a refcount prevents the array from going away. */ + GC_ADDREF(ht); + + zend_hash_sort_internal(ht, sort, compar, renumber); + + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + } else { + gc_check_possible_root((zend_refcounted *)ht); + } +} + static zend_always_inline int zend_hash_compare_impl(HashTable *ht1, HashTable *ht2, compare_func_t compar, bool ordered) { uint32_t idx1, idx2; zend_string *key1, *key2; diff -Nru php8.2-8.2.24/Zend/zend_hash.h php8.2-8.2.26/Zend/zend_hash.h --- php8.2-8.2.24/Zend/zend_hash.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_hash.h 2024-11-19 17:11:09.000000000 +0000 @@ -296,12 +296,20 @@ typedef int (*bucket_compare_func_t)(Bucket *a, Bucket *b); ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, bool ordered); ZEND_API void ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort_func, bucket_compare_func_t compare_func, bool renumber); +void ZEND_FASTCALL zend_array_sort_ex(HashTable *ht, sort_func_t sort_func, bucket_compare_func_t compare_func, bool renumber); ZEND_API zval* ZEND_FASTCALL zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag); static zend_always_inline void ZEND_FASTCALL zend_hash_sort(HashTable *ht, bucket_compare_func_t compare_func, zend_bool renumber) { zend_hash_sort_ex(ht, zend_sort, compare_func, renumber); } +/* Use this variant over zend_hash_sort() when sorting user arrays that may + * trigger user code. It will ensure the user code cannot free the array during + * sorting. */ +static zend_always_inline void zend_array_sort(HashTable *ht, bucket_compare_func_t compare_func, bool renumber) { + zend_array_sort_ex(ht, zend_sort, compare_func, renumber); +} + static zend_always_inline uint32_t zend_hash_num_elements(const HashTable *ht) { return ht->nNumOfElements; } diff -Nru php8.2-8.2.24/Zend/zend_inheritance.c php8.2-8.2.26/Zend/zend_inheritance.c --- php8.2-8.2.24/Zend/zend_inheritance.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_inheritance.c 2024-11-19 17:11:09.000000000 +0000 @@ -3222,6 +3222,8 @@ CG(current_linking_class) = is_cacheable ? ce : NULL; zend_try{ + CG(zend_lineno) = ce->info.user.line_start; + if (is_cacheable) { zend_begin_record_errors(); } diff -Nru php8.2-8.2.24/Zend/zend_interfaces.c php8.2-8.2.26/Zend/zend_interfaces.c --- php8.2-8.2.24/Zend/zend_interfaces.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_interfaces.c 2024-11-19 17:11:09.000000000 +0000 @@ -473,6 +473,10 @@ if (!(class_type->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (!class_type->__serialize || !class_type->__unserialize)) { zend_error(E_DEPRECATED, "%s implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary)", ZSTR_VAL(class_type->name)); + if (EG(exception)) { + zend_exception_uncaught_error( + "During inheritance of %s, while implementing Serializable", ZSTR_VAL(class_type->name)); + } } return SUCCESS; } diff -Nru php8.2-8.2.24/Zend/zend_object_handlers.c php8.2-8.2.26/Zend/zend_object_handlers.c --- php8.2-8.2.24/Zend/zend_object_handlers.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_object_handlers.c 2024-11-19 17:11:09.000000000 +0000 @@ -30,6 +30,7 @@ #include "zend_closures.h" #include "zend_compile.h" #include "zend_hash.h" +#include "zend_observer.h" #define DEBUG_OBJECT_HANDLERS 0 @@ -1280,7 +1281,10 @@ func->arg_flags[0] = 0; func->arg_flags[1] = 0; func->arg_flags[2] = 0; - func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_PUBLIC | ZEND_ACC_VARIADIC; + func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE + | ZEND_ACC_PUBLIC + | ZEND_ACC_VARIADIC + | (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE); if (is_static) { func->fn_flags |= ZEND_ACC_STATIC; } @@ -1294,7 +1298,8 @@ * value so that it doesn't contain garbage when the engine allocates space for the next stack * frame. This didn't cause any issues until now due to "lucky" structure layout. */ func->last_var = 0; - func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, 2) : 2; + uint32_t min_T = 2 + ZEND_OBSERVER_ENABLED; + func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, min_T) : min_T; func->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : ZSTR_EMPTY_ALLOC(); func->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0; func->line_end = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_end : 0; diff -Nru php8.2-8.2.24/Zend/zend_operators.h php8.2-8.2.26/Zend/zend_operators.h --- php8.2-8.2.24/Zend/zend_operators.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_operators.h 2024-11-19 17:11:09.000000000 +0000 @@ -27,7 +27,20 @@ #include #ifdef HAVE_IEEEFP_H -#include +/** + * On FreeBSD with ubsan/clang we get the following: + * `/usr/include/machine/ieeefp.h:161:17: runtime error: left shift of negative value -1` + * `SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/include/machine/ieeefp.h:161:17` + * ... + * `_newcw |= (~_m << FP_MSKS_OFF) & FP_MSKS_FLD;` +**/ +# if __has_feature(undefined_behavior_sanitizer) && defined(__FreeBSD__) && defined(__clang__) +# pragma clang attribute push (__attribute__((no_sanitize("undefined"))), apply_to=function) +# endif +# include +# if __has_feature(undefined_behavior_sanitizer) && defined(__FreeBSD__) && defined(__clang__) +# pragma clang attribute pop +# endif #endif #include "zend_portability.h" diff -Nru php8.2-8.2.24/Zend/zend_string.c php8.2-8.2.26/Zend/zend_string.c --- php8.2-8.2.24/Zend/zend_string.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_string.c 2024-11-19 17:11:09.000000000 +0000 @@ -392,32 +392,32 @@ ZEND_API zend_never_inline NOIPA bool ZEND_FASTCALL zend_string_equal_val(const zend_string *s1, const zend_string *s2) { const char *ptr = ZSTR_VAL(s1); - size_t delta = (const char*)s2 - (const char*)s1; + uintptr_t delta = (uintptr_t) s2 - (uintptr_t) s1; size_t len = ZSTR_LEN(s1); zend_ulong ret; __asm__ ( - ".LL0%=:\n\t" + "0:\n\t" "movl (%2,%3), %0\n\t" "xorl (%2), %0\n\t" - "jne .LL1%=\n\t" + "jne 1f\n\t" "addl $0x4, %2\n\t" "subl $0x4, %1\n\t" - "ja .LL0%=\n\t" + "ja 0b\n\t" "movl $0x1, %0\n\t" - "jmp .LL3%=\n\t" - ".LL1%=:\n\t" + "jmp 3f\n\t" + "1:\n\t" "cmpl $0x4,%1\n\t" - "jb .LL2%=\n\t" + "jb 2f\n\t" "xorl %0, %0\n\t" - "jmp .LL3%=\n\t" - ".LL2%=:\n\t" + "jmp 3f\n\t" + "2:\n\t" "negl %1\n\t" "lea 0x20(,%1,8), %1\n\t" "shll %b1, %0\n\t" "sete %b0\n\t" "movzbl %b0, %0\n\t" - ".LL3%=:\n" + "3:\n" : "=&a"(ret), "+c"(len), "+r"(ptr) @@ -430,32 +430,32 @@ ZEND_API zend_never_inline NOIPA bool ZEND_FASTCALL zend_string_equal_val(const zend_string *s1, const zend_string *s2) { const char *ptr = ZSTR_VAL(s1); - size_t delta = (const char*)s2 - (const char*)s1; + uintptr_t delta = (uintptr_t) s2 - (uintptr_t) s1; size_t len = ZSTR_LEN(s1); zend_ulong ret; __asm__ ( - ".LL0%=:\n\t" + "0:\n\t" "movq (%2,%3), %0\n\t" "xorq (%2), %0\n\t" - "jne .LL1%=\n\t" + "jne 1f\n\t" "addq $0x8, %2\n\t" "subq $0x8, %1\n\t" - "ja .LL0%=\n\t" + "ja 0b\n\t" "movq $0x1, %0\n\t" - "jmp .LL3%=\n\t" - ".LL1%=:\n\t" + "jmp 3f\n\t" + "1:\n\t" "cmpq $0x8,%1\n\t" - "jb .LL2%=\n\t" + "jb 2f\n\t" "xorq %0, %0\n\t" - "jmp .LL3%=\n\t" - ".LL2%=:\n\t" + "jmp 3f\n\t" + "2:\n\t" "negq %1\n\t" "lea 0x40(,%1,8), %1\n\t" "shlq %b1, %0\n\t" "sete %b0\n\t" "movzbq %b0, %0\n\t" - ".LL3%=:\n" + "3:\n" : "=&a"(ret), "+c"(len), "+r"(ptr) diff -Nru php8.2-8.2.24/Zend/zend_strtod.c php8.2-8.2.26/Zend/zend_strtod.c --- php8.2-8.2.24/Zend/zend_strtod.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_strtod.c 2024-11-19 17:11:09.000000000 +0000 @@ -3613,11 +3613,11 @@ rv_alloc(int i) #endif { - int j, k, *r; + int k, *r; - j = sizeof(ULong); + size_t j = sizeof(ULong); for(k = 0; - sizeof(Bigint) - sizeof(ULong) - sizeof(int) + (size_t)j <= (size_t)i; + sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (size_t)i; j <<= 1) k++; r = (int*)Balloc(k); diff -Nru php8.2-8.2.24/Zend/zend_weakrefs.c php8.2-8.2.26/Zend/zend_weakrefs.c --- php8.2-8.2.24/Zend/zend_weakrefs.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/Zend/zend_weakrefs.c 2024-11-19 17:11:09.000000000 +0000 @@ -530,6 +530,10 @@ zend_string *string_key; zend_ulong num_key; int key_type = zend_hash_get_current_key_ex(&wm->ht, &string_key, &num_key, pos); + if (key_type == HASH_KEY_NON_EXISTENT) { + ZVAL_NULL(key); + return; + } if (key_type != HASH_KEY_IS_LONG) { ZEND_ASSERT(0 && "Must have integer key"); } diff -Nru php8.2-8.2.24/build/php.m4 php8.2-8.2.26/build/php.m4 --- php8.2-8.2.24/build/php.m4 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/build/php.m4 2024-11-19 17:11:09.000000000 +0000 @@ -2735,3 +2735,15 @@ $SED -e 's/^#undef PACKAGE_[^ ]*/\/\* & \*\//g' < $srcdir/$1 \ > $srcdir/$1.tmp && mv $srcdir/$1.tmp $srcdir/$1 ]) + +dnl +dnl PHP_REMOVE_OPTIMIZATION_FLAGS +dnl +dnl Removes known compiler optimization flags like -O, -O0, -O1, ..., -Ofast +dnl from CFLAGS and CXXFLAGS. +dnl +AC_DEFUN([PHP_REMOVE_OPTIMIZATION_FLAGS], [ + sed_script='s/\([[\t ]]\|^\)-O\([[0-9gsz]]\|fast\|\)\([[\t ]]\|$\)/\1/g' + CFLAGS=$(echo "$CFLAGS" | $SED -e "$sed_script") + CXXFLAGS=$(echo "$CXXFLAGS" | $SED -e "$sed_script") +]) diff -Nru php8.2-8.2.24/configure php8.2-8.2.26/configure --- php8.2-8.2.24/configure 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/configure 2024-11-19 17:11:09.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for PHP 8.2.24. +# Generated by GNU Autoconf 2.69 for PHP 8.2.26. # # Report bugs to . # @@ -732,8 +732,8 @@ # Identity of this package. PACKAGE_NAME='PHP' PACKAGE_TARNAME='php' -PACKAGE_VERSION='8.2.24' -PACKAGE_STRING='PHP 8.2.24' +PACKAGE_VERSION='8.2.26' +PACKAGE_STRING='PHP 8.2.26' PACKAGE_BUGREPORT='https://github.com/php/php-src/issues' PACKAGE_URL='https://www.php.net' @@ -1779,7 +1779,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures PHP 8.2.24 to adapt to many kinds of systems. +\`configure' configures PHP 8.2.26 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1851,7 +1851,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of PHP 8.2.24:";; + short | recursive ) echo "Configuration of PHP 8.2.26:";; esac cat <<\_ACEOF @@ -2314,7 +2314,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -PHP configure 8.2.24 +PHP configure 8.2.26 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -3098,7 +3098,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by PHP $as_me 8.2.24, which was +It was created by PHP $as_me 8.2.26, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3879,7 +3879,7 @@ ac_IFS=$IFS; IFS="." -set $(echo 8.2.24 | "${SED}" 's/\([0-9\.]*\)\(.*\)/\1\.\2/') +set $(echo 8.2.26 | "${SED}" 's/\([0-9\.]*\)\(.*\)/\1\.\2/') IFS=$ac_IFS PHP_MAJOR_VERSION=$1 PHP_MINOR_VERSION=$2 @@ -18507,8 +18507,9 @@ - CFLAGS=`echo "$CFLAGS" | "$SED" -e 's/-O[0-9s]*//g'` - CXXFLAGS=`echo "$CXXFLAGS" | "$SED" -e 's/-O[0-9s]*//g'` + sed_script='s/\([\t ]\|^\)-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)/\1/g' + CFLAGS=$(echo "$CFLAGS" | $SED -e "$sed_script") + CXXFLAGS=$(echo "$CXXFLAGS" | $SED -e "$sed_script") CFLAGS="$CFLAGS -O0 -fprofile-arcs -ftest-coverage" @@ -18542,8 +18543,9 @@ PHP_DEBUG=1 ZEND_DEBUG=yes - CFLAGS=`echo "$CFLAGS" | "$SED" -e 's/-O[0-9s]*//g'` - CXXFLAGS=`echo "$CXXFLAGS" | "$SED" -e 's/-O[0-9s]*//g'` + sed_script='s/\([\t ]\|^\)-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)/\1/g' + CFLAGS=$(echo "$CFLAGS" | $SED -e "$sed_script") + CXXFLAGS=$(echo "$CXXFLAGS" | $SED -e "$sed_script") if test "$GCC" = "yes" || test "$ICC" = "yes"; then CFLAGS="$CFLAGS -O0" @@ -86701,7 +86703,7 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext + echo '#line 88872 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -90264,7 +90266,7 @@ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat > conftest.$ac_ext <&5) + (eval echo "\"configure:90426: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "configure:90428: \$? = $ac_status" >&5 + echo "configure:90430: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -90719,11 +90721,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"configure:90722: $lt_compile\"" >&5) + (eval echo "\"configure:90724: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "configure:90726: \$? = $ac_status" >&5 + echo "configure:90728: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -90823,11 +90825,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"configure:90826: $lt_compile\"" >&5) + (eval echo "\"configure:90828: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "configure:90830: \$? = $ac_status" >&5 + echo "configure:90832: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -91287,7 +91289,7 @@ # Determine the default libpath from the value encoded in an empty executable. cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <&5) + (eval echo "\"configure:95315: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "configure:95317: \$? = $ac_status" >&5 + echo "configure:95319: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -95414,11 +95416,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"configure:95417: $lt_compile\"" >&5) + (eval echo "\"configure:95419: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "configure:95421: \$? = $ac_status" >&5 + echo "configure:95423: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -97704,7 +97706,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by PHP $as_me 8.2.24, which was +This file was extended by PHP $as_me 8.2.26, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -97771,7 +97773,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -PHP config.status 8.2.24 +PHP config.status 8.2.26 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru php8.2-8.2.24/configure.ac php8.2-8.2.26/configure.ac --- php8.2-8.2.24/configure.ac 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/configure.ac 2024-11-19 17:11:09.000000000 +0000 @@ -17,7 +17,7 @@ dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.2.24],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.26],[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 @@ -845,10 +845,7 @@ PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/build/Makefile.gcov, $abs_srcdir) dnl Remove all optimization flags from CFLAGS. - changequote({,}) - CFLAGS=`echo "$CFLAGS" | "${SED}" -e 's/-O[0-9s]*//g'` - CXXFLAGS=`echo "$CXXFLAGS" | "${SED}" -e 's/-O[0-9s]*//g'` - changequote([,]) + PHP_REMOVE_OPTIMIZATION_FLAGS dnl Add the special gcc flags. CFLAGS="$CFLAGS -O0 -fprofile-arcs -ftest-coverage" @@ -865,10 +862,7 @@ if test "$PHP_DEBUG" = "yes"; then PHP_DEBUG=1 ZEND_DEBUG=yes - changequote({,}) - CFLAGS=`echo "$CFLAGS" | "${SED}" -e 's/-O[0-9s]*//g'` - CXXFLAGS=`echo "$CXXFLAGS" | "${SED}" -e 's/-O[0-9s]*//g'` - changequote([,]) + PHP_REMOVE_OPTIMIZATION_FLAGS dnl Add -O0 only if GCC or ICC is used. if test "$GCC" = "yes" || test "$ICC" = "yes"; then CFLAGS="$CFLAGS -O0" diff -Nru php8.2-8.2.24/debian/changelog php8.2-8.2.26/debian/changelog --- php8.2-8.2.24/debian/changelog 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/changelog 2024-11-25 17:21:51.000000000 +0000 @@ -1,3 +1,28 @@ +php8.2 (8.2.26-1~deb12u1) bookworm-security; urgency=high + + * New upstream version 8.2.26 + + Heap-Use-After-Free in sapi_read_post_data Processing in CLI SAPI Interface. + + [CVE-2024-8929]: Leak partial content of the heap through heap buffer + over-read. + + [CVE-2024-8932]: OOB access in ldap_escape. + + [CVE-2024-11233]: Single byte overread with + convert.quoted-printable-decode filter. + + [CVE-2024-11234]: Configuring a proxy in a stream context might allow + for CRLF injection in URIs. + + [CVE-2024-11236]: Integer overflow in the dblib quoter causing OOB + writes. + + [CVE-2024-11236]: Integer overflow in the firebird quoter causing OOB + writes. + * Revert "ext/gmp: gmp_pow fix FPE with large values" upstream patch + + -- Ondřej Surý Mon, 25 Nov 2024 18:21:51 +0100 + +php8.2 (8.2.25-1~deb12u1) bookworm-security; urgency=medium + + * New upstream version 8.2.25 + + -- Ondřej Surý Wed, 30 Oct 2024 11:38:36 +0100 + php8.2 (8.2.24-1~deb12u1) bookworm-security; urgency=high * New upstream version 8.2.24 diff -Nru php8.2-8.2.24/debian/patches/0001-libtool_fixes.patch php8.2-8.2.26/debian/patches/0001-libtool_fixes.patch --- php8.2-8.2.24/debian/patches/0001-libtool_fixes.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0001-libtool_fixes.patch 2024-11-25 17:21:51.000000000 +0000 @@ -7,10 +7,10 @@ 1 file changed, 2 deletions(-) diff --git a/configure.ac b/configure.ac -index bfaa275..58ec3c7 100644 +index 00f1b7f..4c93593 100644 --- a/configure.ac +++ b/configure.ac -@@ -1648,8 +1648,6 @@ AC_PROVIDE_IFELSE([PHP_REQUIRE_CXX], [], [ +@@ -1642,8 +1642,6 @@ AC_PROVIDE_IFELSE([PHP_REQUIRE_CXX], [], [ ]) AC_PROG_LIBTOOL diff -Nru php8.2-8.2.24/debian/patches/0002-debian_quirks.patch php8.2-8.2.26/debian/patches/0002-debian_quirks.patch --- php8.2-8.2.24/debian/patches/0002-debian_quirks.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0002-debian_quirks.patch 2024-11-25 17:21:51.000000000 +0000 @@ -13,10 +13,10 @@ 7 files changed, 21 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac -index 58ec3c7..4ab09eb 100644 +index 4c93593..ad3be5f 100644 --- a/configure.ac +++ b/configure.ac -@@ -1221,7 +1221,7 @@ fi +@@ -1215,7 +1215,7 @@ fi PHP_ARG_WITH([pear], [whether to install PEAR], [AS_HELP_STRING([[--with-pear[=DIR]]], @@ -25,7 +25,7 @@ [no], [yes]) -@@ -1252,6 +1252,8 @@ if test "$PHP_PEAR" != "no"; then +@@ -1246,6 +1246,8 @@ if test "$PHP_PEAR" != "no"; then PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/pear/Makefile.frag,$abs_srcdir/pear,pear) fi @@ -34,7 +34,7 @@ dnl Configuring Zend and TSRM. dnl ---------------------------------------------------------------------------- -@@ -1393,6 +1395,8 @@ datadir=`eval eval echo $datadir` +@@ -1387,6 +1389,8 @@ datadir=`eval eval echo $datadir` dnl Build extension directory path. ZEND_MODULE_API_NO=`$EGREP '#define ZEND_MODULE_API_NO ' $srcdir/Zend/zend_modules.h|"${SED}" 's/#define ZEND_MODULE_API_NO //'` diff -Nru php8.2-8.2.24/debian/patches/0003-php-5.4.9-phpinfo.patch php8.2-8.2.26/debian/patches/0003-php-5.4.9-phpinfo.patch --- php8.2-8.2.24/debian/patches/0003-php-5.4.9-phpinfo.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0003-php-5.4.9-phpinfo.patch 2024-11-25 17:21:51.000000000 +0000 @@ -25,13 +25,13 @@ if (sapi_module.pretty_name) { php_info_print_table_row(2, "Server API", sapi_module.pretty_name ); diff --git a/ext/standard/tests/general_functions/phpinfo.phpt b/ext/standard/tests/general_functions/phpinfo.phpt -index 57ba13b..2e2fae8 100644 +index a8c4f39..0229816 100644 --- a/ext/standard/tests/general_functions/phpinfo.phpt +++ b/ext/standard/tests/general_functions/phpinfo.phpt @@ -17,7 +17,6 @@ System => %s - Build Date => %s%a + Build Date => %r(.+?)%r -Configure Command => %s Server API => Command Line Interface Virtual Directory Support => %s diff -Nru php8.2-8.2.24/debian/patches/0004-extension_api.patch php8.2-8.2.26/debian/patches/0004-extension_api.patch --- php8.2-8.2.24/debian/patches/0004-extension_api.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0004-extension_api.patch 2024-11-25 17:21:51.000000000 +0000 @@ -8,10 +8,10 @@ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac -index 4ab09eb..73bef98 100644 +index ad3be5f..a0258f9 100644 --- a/configure.ac +++ b/configure.ac -@@ -1397,8 +1397,10 @@ ZEND_MODULE_API_NO=`$EGREP '#define ZEND_MODULE_API_NO ' $srcdir/Zend/zend_modul +@@ -1391,8 +1391,10 @@ ZEND_MODULE_API_NO=`$EGREP '#define ZEND_MODULE_API_NO ' $srcdir/Zend/zend_modul AC_SUBST(ZEND_MODULE_API_NO) @@ -23,7 +23,7 @@ if test "$oldstyleextdir" = "yes"; then if test "$PHP_DEBUG" = "1"; then part1=debug -@@ -1532,6 +1534,7 @@ PHP_SUBST(CXX) +@@ -1526,6 +1528,7 @@ PHP_SUBST(CXX) PHP_SUBST(CXXFLAGS) PHP_SUBST(CXXFLAGS_CLEAN) PHP_SUBST_OLD(DEBUG_CFLAGS) diff -Nru php8.2-8.2.24/debian/patches/0006-php-5.4.7-libdb.patch php8.2-8.2.26/debian/patches/0006-php-5.4.7-libdb.patch --- php8.2-8.2.24/debian/patches/0006-php-5.4.7-libdb.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0006-php-5.4.7-libdb.patch 2024-11-25 17:21:51.000000000 +0000 @@ -76,7 +76,7 @@ PHP_DBA_STD_RESULT(db4,Berkeley DB4) diff --git a/ext/dba/dba.c b/ext/dba/dba.c -index 7e0f56b..9e9d700 100644 +index e25a801..64f8b5b 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -50,6 +50,10 @@ diff -Nru php8.2-8.2.24/debian/patches/0010-session_save_path.patch php8.2-8.2.26/debian/patches/0010-session_save_path.patch --- php8.2-8.2.24/debian/patches/0010-session_save_path.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0010-session_save_path.patch 2024-11-25 17:21:51.000000000 +0000 @@ -8,10 +8,10 @@ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/session/session.c b/ext/session/session.c -index 8b95b31..bd09f26 100644 +index dd780f4..687c38d 100644 --- a/ext/session/session.c +++ b/ext/session/session.c -@@ -790,7 +790,7 @@ static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */ +@@ -799,7 +799,7 @@ static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */ /* {{{ PHP_INI */ PHP_INI_BEGIN() diff -Nru php8.2-8.2.24/debian/patches/0017-php-5.3.3-macropen.patch php8.2-8.2.26/debian/patches/0017-php-5.3.3-macropen.patch --- php8.2-8.2.24/debian/patches/0017-php-5.3.3-macropen.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0017-php-5.3.3-macropen.patch 2024-11-25 17:21:51.000000000 +0000 @@ -9,10 +9,10 @@ 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/dba/dba.c b/ext/dba/dba.c -index 9e9d700..a9f99c9 100644 +index 64f8b5b..d28b8f5 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c -@@ -851,7 +851,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) +@@ -858,7 +858,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, bool persistent) } } diff -Nru php8.2-8.2.24/debian/patches/0021-Use-system-timezone.patch php8.2-8.2.26/debian/patches/0021-Use-system-timezone.patch --- php8.2-8.2.24/debian/patches/0021-Use-system-timezone.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0021-Use-system-timezone.patch 2024-11-25 17:21:51.000000000 +0000 @@ -14,7 +14,7 @@ 1 file changed, 17 insertions(+) diff --git a/ext/date/php_date.c b/ext/date/php_date.c -index 87dd917..3d0135a 100644 +index 9108a7c..f9bc024 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -549,6 +549,23 @@ static char* guess_timezone(const timelib_tzdb *tzdb) diff -Nru php8.2-8.2.24/debian/patches/0024-php-5.4.9-fixheader.patch php8.2-8.2.26/debian/patches/0024-php-5.4.9-fixheader.patch --- php8.2-8.2.24/debian/patches/0024-php-5.4.9-fixheader.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0024-php-5.4.9-fixheader.patch 2024-11-25 17:21:51.000000000 +0000 @@ -8,10 +8,10 @@ 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac -index 73bef98..de78ca6 100644 +index a0258f9..23c6f0d 100644 --- a/configure.ac +++ b/configure.ac -@@ -1474,7 +1474,7 @@ PHP_REMOVE_USR_LIB(LDFLAGS) +@@ -1468,7 +1468,7 @@ PHP_REMOVE_USR_LIB(LDFLAGS) EXTRA_LDFLAGS="$EXTRA_LDFLAGS $PHP_LDFLAGS" EXTRA_LDFLAGS_PROGRAM="$EXTRA_LDFLAGS_PROGRAM $PHP_LDFLAGS" diff -Nru php8.2-8.2.24/debian/patches/0030-Really-expand-libdir-datadir-into-EXPANDED_LIBDIR-DA.patch php8.2-8.2.26/debian/patches/0030-Really-expand-libdir-datadir-into-EXPANDED_LIBDIR-DA.patch --- php8.2-8.2.24/debian/patches/0030-Really-expand-libdir-datadir-into-EXPANDED_LIBDIR-DA.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0030-Really-expand-libdir-datadir-into-EXPANDED_LIBDIR-DA.patch 2024-11-25 17:21:51.000000000 +0000 @@ -7,10 +7,10 @@ 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac -index de78ca6..1db407b 100644 +index 23c6f0d..de7dcb8 100644 --- a/configure.ac +++ b/configure.ac -@@ -1442,9 +1442,9 @@ EXPANDED_LOCALSTATEDIR=`eval echo $localstatedir` +@@ -1436,9 +1436,9 @@ EXPANDED_LOCALSTATEDIR=`eval echo $localstatedir` EXPANDED_BINDIR=`eval echo $bindir` EXPANDED_SBINDIR=`eval echo $sbindir` EXPANDED_MANDIR=`eval echo $mandir` diff -Nru php8.2-8.2.24/debian/patches/0035-Include-all-libtool-files-from-phpize.m4.patch php8.2-8.2.26/debian/patches/0035-Include-all-libtool-files-from-phpize.m4.patch --- php8.2-8.2.24/debian/patches/0035-Include-all-libtool-files-from-phpize.m4.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0035-Include-all-libtool-files-from-phpize.m4.patch 2024-11-25 17:21:51.000000000 +0000 @@ -7,7 +7,7 @@ 1 file changed, 4 insertions(+) diff --git a/scripts/phpize.m4 b/scripts/phpize.m4 -index 616d164..f73a0de 100644 +index b713dcc..99d3843 100644 --- a/scripts/phpize.m4 +++ b/scripts/phpize.m4 @@ -5,6 +5,10 @@ dnl comments starting with # and empty newlines from the included files. diff -Nru php8.2-8.2.24/debian/patches/0041-Lower-the-OpenSSL-requirement-to-1.0.1.patch php8.2-8.2.26/debian/patches/0041-Lower-the-OpenSSL-requirement-to-1.0.1.patch --- php8.2-8.2.24/debian/patches/0041-Lower-the-OpenSSL-requirement-to-1.0.1.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0041-Lower-the-OpenSSL-requirement-to-1.0.1.patch 2024-11-25 17:21:51.000000000 +0000 @@ -11,7 +11,7 @@ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/build/php.m4 b/build/php.m4 -index 32487e4..a7d8fb9 100644 +index e13fc33..0648237 100644 --- a/build/php.m4 +++ b/build/php.m4 @@ -1929,7 +1929,7 @@ dnl @@ -37,7 +37,7 @@ PHP_ARG_WITH([kerberos], [for Kerberos support], diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c -index f6ed67b..56d6510 100644 +index a50a307..0fd0573 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -95,7 +95,7 @@ diff -Nru php8.2-8.2.24/debian/patches/0042-Fail-the-build-when-the-dtrace-call-fails.patch php8.2-8.2.26/debian/patches/0042-Fail-the-build-when-the-dtrace-call-fails.patch --- php8.2-8.2.24/debian/patches/0042-Fail-the-build-when-the-dtrace-call-fails.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0042-Fail-the-build-when-the-dtrace-call-fails.patch 2024-11-25 17:21:51.000000000 +0000 @@ -7,7 +7,7 @@ 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/php.m4 b/build/php.m4 -index a7d8fb9..ccc9b92 100644 +index 0648237..2d1ac5c 100644 --- a/build/php.m4 +++ b/build/php.m4 @@ -2376,7 +2376,8 @@ dnl overwritten (Bug 61268). diff -Nru php8.2-8.2.24/debian/patches/0043-Override-result-of-AC_PROG_LN_S-to-fix-FTBFS-on-ppc6.patch php8.2-8.2.26/debian/patches/0043-Override-result-of-AC_PROG_LN_S-to-fix-FTBFS-on-ppc6.patch --- php8.2-8.2.24/debian/patches/0043-Override-result-of-AC_PROG_LN_S-to-fix-FTBFS-on-ppc6.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0043-Override-result-of-AC_PROG_LN_S-to-fix-FTBFS-on-ppc6.patch 2024-11-25 17:21:51.000000000 +0000 @@ -7,7 +7,7 @@ 1 file changed, 5 insertions(+) diff --git a/configure.ac b/configure.ac -index 1db407b..23eb445 100644 +index de7dcb8..72c2e4f 100644 --- a/configure.ac +++ b/configure.ac @@ -135,6 +135,11 @@ AC_PROG_CPP diff -Nru php8.2-8.2.24/debian/patches/0046-Remove-timestamps-from-phar.patch php8.2-8.2.26/debian/patches/0046-Remove-timestamps-from-phar.patch --- php8.2-8.2.24/debian/patches/0046-Remove-timestamps-from-phar.patch 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0046-Remove-timestamps-from-phar.patch 2024-11-25 17:21:51.000000000 +0000 @@ -11,7 +11,7 @@ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c -index b774f22..441a422 100644 +index e3d6ea7..51eae5d 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -3002,7 +3002,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv diff -Nru php8.2-8.2.24/debian/patches/0048-Revert-ext-gmp-gmp_pow-fix-FPE-with-large-values-pat.patch php8.2-8.2.26/debian/patches/0048-Revert-ext-gmp-gmp_pow-fix-FPE-with-large-values-pat.patch --- php8.2-8.2.24/debian/patches/0048-Revert-ext-gmp-gmp_pow-fix-FPE-with-large-values-pat.patch 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/debian/patches/0048-Revert-ext-gmp-gmp_pow-fix-FPE-with-large-values-pat.patch 2024-11-25 17:21:51.000000000 +0000 @@ -0,0 +1,181 @@ +From: =?utf-8?b?T25kxZllaiBTdXLDvQ==?= +Date: Mon, 25 Nov 2024 18:21:34 +0100 +Subject: Revert "ext/gmp: gmp_pow fix FPE with large values" patch + +--- + ext/gmp/gmp.c | 13 ------- + ext/gmp/tests/gmp_pow.phpt | 2 - + ext/gmp/tests/gmp_pow_32bits.phpt | 77 --------------------------------------- + ext/gmp/tests/gmp_pow_fpe.phpt | 35 ------------------ + 4 files changed, 127 deletions(-) + delete mode 100644 ext/gmp/tests/gmp_pow_32bits.phpt + delete mode 100644 ext/gmp/tests/gmp_pow_fpe.phpt + +diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c +index c9603c8..f31d6ab 100644 +--- a/ext/gmp/gmp.c ++++ b/ext/gmp/gmp.c +@@ -1350,26 +1350,13 @@ ZEND_FUNCTION(gmp_pow) + RETURN_THROWS(); + } + +- double powmax = log((double)ZEND_LONG_MAX); +- + if (Z_TYPE_P(base_arg) == IS_LONG && Z_LVAL_P(base_arg) >= 0) { + INIT_GMP_RETVAL(gmpnum_result); +- if ((log(Z_LVAL_P(base_arg)) * exp) > powmax) { +- zend_value_error("base and exponent overflow"); +- RETURN_THROWS(); +- } + mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp); + } else { + mpz_ptr gmpnum_base; +- zend_ulong gmpnum; + FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base, 1); + INIT_GMP_RETVAL(gmpnum_result); +- gmpnum = mpz_get_ui(gmpnum_base); +- if ((log(gmpnum) * exp) > powmax) { +- FREE_GMP_TEMP(temp_base); +- zend_value_error("base and exponent overflow"); +- RETURN_THROWS(); +- } + mpz_pow_ui(gmpnum_result, gmpnum_base, exp); + FREE_GMP_TEMP(temp_base); + } +diff --git a/ext/gmp/tests/gmp_pow.phpt b/ext/gmp/tests/gmp_pow.phpt +index 1d77bd5..f42e44e 100644 +--- a/ext/gmp/tests/gmp_pow.phpt ++++ b/ext/gmp/tests/gmp_pow.phpt +@@ -2,8 +2,6 @@ + gmp_pow() basic tests + --EXTENSIONS-- + gmp +---SKIPIF-- +- + --FILE-- + +---FILE-- +-getMessage() . "\n"; +-} +-var_dump(gmp_strval(gmp_pow("-2",10))); +-try { +- gmp_pow(20,10); +-} catch (ValueError $exception) { +- echo $exception->getMessage() . "\n"; +-} +-try { +- gmp_pow(50,10); +-} catch (ValueError $exception) { +- echo $exception->getMessage() . "\n"; +-} +-try { +- gmp_pow(50,-5); +-} catch (ValueError $exception) { +- echo $exception->getMessage() . "\n"; +-} +-try { +- $n = gmp_init("20"); +- gmp_pow($n,10); +-} catch (ValueError $exception) { +- echo $exception->getMessage() . "\n"; +-} +-try { +- $n = gmp_init("-20"); +- gmp_pow($n,10); +-} catch (ValueError $exception) { +- echo $exception->getMessage() . "\n"; +-} +-try { +- var_dump(gmp_pow(2,array())); +-} catch (TypeError $e) { +- echo $e->getMessage(), "\n"; +-} +- +-try { +- var_dump(gmp_pow(array(),10)); +-} catch (\TypeError $e) { +- echo $e->getMessage() . \PHP_EOL; +-} +- +-echo "Done\n"; +-?> +---EXPECT-- +-string(4) "1024" +-string(4) "1024" +-string(5) "-2048" +-string(4) "1024" +-string(1) "1" +-gmp_pow(): Argument #2 ($exponent) must be greater than or equal to 0 +-string(4) "1024" +-base and exponent overflow +-base and exponent overflow +-gmp_pow(): Argument #2 ($exponent) must be greater than or equal to 0 +-base and exponent overflow +-base and exponent overflow +-gmp_pow(): Argument #2 ($exponent) must be of type int, array given +-gmp_pow(): Argument #1 ($num) must be of type GMP|string|int, array given +-Done +diff --git a/ext/gmp/tests/gmp_pow_fpe.phpt b/ext/gmp/tests/gmp_pow_fpe.phpt +deleted file mode 100644 +index 248922e..0000000 +--- a/ext/gmp/tests/gmp_pow_fpe.phpt ++++ /dev/null +@@ -1,35 +0,0 @@ +---TEST-- +-gmp_pow() floating point exception +---EXTENSIONS-- +-gmp +---FILE-- +-getMessage() . PHP_EOL; +-} +-try { +- gmp_pow(256, PHP_INT_MAX); +-} catch (\ValueError $e) { +- echo $e->getMessage() . PHP_EOL; +-} +- +-try { +- gmp_pow(gmp_add(gmp_mul(gmp_init(PHP_INT_MAX), gmp_init(PHP_INT_MAX)), 3), 256); +-} catch (\ValueError $e) { +- echo $e->getMessage() . PHP_EOL; +-} +-try { +- gmp_pow(gmp_init(PHP_INT_MAX), 256); +-} catch (\ValueError $e) { +- echo $e->getMessage(); +-} +-?> +---EXPECTF-- +-base and exponent overflow +-base and exponent overflow +-base and exponent overflow +-base and exponent overflow diff -Nru php8.2-8.2.24/debian/patches/series php8.2-8.2.26/debian/patches/series --- php8.2-8.2.24/debian/patches/series 2024-09-27 04:16:10.000000000 +0000 +++ php8.2-8.2.26/debian/patches/series 2024-11-25 17:21:51.000000000 +0000 @@ -45,3 +45,4 @@ 0045-scripts-php-.in-Explicitly-define-the-path-to-sed.patch 0046-Remove-timestamps-from-phar.patch 0047-fix-implicit-function-declaration.patch +0048-Revert-ext-gmp-gmp_pow-fix-FPE-with-large-values-pat.patch diff -Nru php8.2-8.2.24/ext/calendar/cal_unix.c php8.2-8.2.26/ext/calendar/cal_unix.c --- php8.2-8.2.24/ext/calendar/cal_unix.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/calendar/cal_unix.c 2024-11-19 17:11:09.000000000 +0000 @@ -60,13 +60,13 @@ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &uday) == FAILURE) { RETURN_THROWS(); } - uday -= 2440588 /* J.D. of 1.1.1970 */; - - if (uday < 0 || uday > ZEND_LONG_MAX / SECS_PER_DAY) { /* before beginning of unix epoch or greater than representable */ + if (uday < 2440588 || (uday - 2440588) > (ZEND_LONG_MAX / SECS_PER_DAY)) { /* before beginning of unix epoch or greater than representable */ zend_value_error("jday must be between 2440588 and " ZEND_LONG_FMT, ZEND_LONG_MAX / SECS_PER_DAY + 2440588); RETURN_THROWS(); } + uday -= 2440588 /* J.D. of 1.1.1970 */; + RETURN_LONG(uday * SECS_PER_DAY); } /* }}} */ diff -Nru php8.2-8.2.24/ext/calendar/dow.c php8.2-8.2.26/ext/calendar/dow.c --- php8.2-8.2.24/ext/calendar/dow.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/calendar/dow.c 2024-11-19 17:11:09.000000000 +0000 @@ -33,14 +33,7 @@ int DayOfWeek( zend_long sdn) { - int dow; - - dow = (sdn + 1) % 7; - if (dow >= 0) { - return (dow); - } else { - return (dow + 7); - } + return (int)(sdn % 7 + 8) % 7; } const char * const DayNameShort[7] = diff -Nru php8.2-8.2.24/ext/calendar/easter.c php8.2-8.2.26/ext/calendar/easter.c --- php8.2-8.2.24/ext/calendar/easter.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/calendar/easter.c 2024-11-19 17:11:09.000000000 +0000 @@ -28,6 +28,7 @@ struct tm te; zend_long year, golden, solar, lunar, pfm, dom, tmp, easter, result; zend_long method = CAL_EASTER_DEFAULT; + const zend_long max_year = (zend_long)(ZEND_LONG_MAX / 5) * 4; bool year_is_null = 1; if (zend_parse_parameters(ZEND_NUM_ARGS(), @@ -48,6 +49,11 @@ } } + if (year <= 0 || year > max_year) { + zend_argument_value_error(1, "must be between 1 and " ZEND_LONG_FMT, max_year); + RETURN_THROWS(); + } + if (gm && (year<1970 || year>2037)) { /* out of range for timestamps */ zend_argument_value_error(1, "must be between 1970 and 2037 (inclusive)"); RETURN_THROWS(); diff -Nru php8.2-8.2.24/ext/calendar/jewish.c php8.2-8.2.26/ext/calendar/jewish.c --- php8.2-8.2.24/ext/calendar/jewish.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/calendar/jewish.c 2024-11-19 17:11:09.000000000 +0000 @@ -433,16 +433,31 @@ zend_long *pMoladHalakim) { register zend_ulong r1, r2, d1, d2; + zend_long chk; /* Start with the time of the first molad after creation. */ r1 = NEW_MOON_OF_CREATION; + chk = (zend_long)metonicCycle; + + if (chk > (ZEND_LONG_MAX - NEW_MOON_OF_CREATION) / (HALAKIM_PER_METONIC_CYCLE & 0xFFFF)) { + *pMoladDay = 0; + *pMoladHalakim = 0; + return; + } /* Calculate metonicCycle * HALAKIM_PER_METONIC_CYCLE. The upper 32 * bits of the result will be in r2 and the lower 16 bits will be * in r1. */ - r1 += metonicCycle * (HALAKIM_PER_METONIC_CYCLE & 0xFFFF); + r1 += chk * (HALAKIM_PER_METONIC_CYCLE & 0xFFFF); + + if (chk > (ZEND_LONG_MAX - (r1 >> 16)) / ((HALAKIM_PER_METONIC_CYCLE >> 16) & 0xFFFF)) { + *pMoladDay = 0; + *pMoladHalakim = 0; + return; + } + r2 = r1 >> 16; - r2 += metonicCycle * ((HALAKIM_PER_METONIC_CYCLE >> 16) & 0xFFFF); + r2 += chk * ((HALAKIM_PER_METONIC_CYCLE >> 16) & 0xFFFF); /* Calculate r2r1 / HALAKIM_PER_DAY. The remainder will be in r1, the * upper 16 bits of the quotient will be in d2 and the lower 16 bits diff -Nru php8.2-8.2.24/ext/calendar/tests/gh16228.phpt php8.2-8.2.26/ext/calendar/tests/gh16228.phpt --- php8.2-8.2.24/ext/calendar/tests/gh16228.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/calendar/tests/gh16228.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,26 @@ +--TEST-- +GH-16228 (easter_days, Overflow on year argument) +--EXTENSIONS-- +calendar +--FILE-- +getMessage() . PHP_EOL; +} +try { + easter_days(-1, 0); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} +try { + easter_date(PHP_INT_MAX, 0); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} +?> +--EXPECTF-- +easter_days(): Argument #1 ($year) must be between 1 and %d +easter_days(): Argument #1 ($year) must be between 1 and %d +easter_date(): Argument #1 ($year) must be between 1 and %d diff -Nru php8.2-8.2.24/ext/calendar/tests/gh16231.phpt php8.2-8.2.26/ext/calendar/tests/gh16231.phpt --- php8.2-8.2.24/ext/calendar/tests/gh16231.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/calendar/tests/gh16231.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,21 @@ +--TEST-- +GH-16231 (jdtounix argument overflow) +--EXTENSIONS-- +calendar +--FILE-- +getMessage() . PHP_EOL; +} + +try { + jdtounix(240587); +} catch (\ValueError $e) { + echo $e->getMessage(); +} +?> +--EXPECTF-- +jday must be between 2440588 and %d +jday must be between 2440588 and %d diff -Nru php8.2-8.2.24/ext/calendar/tests/gh16234.phpt php8.2-8.2.26/ext/calendar/tests/gh16234.phpt --- php8.2-8.2.24/ext/calendar/tests/gh16234.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/calendar/tests/gh16234.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,11 @@ +--TEST-- +GH-16234 jewishtojd overflow on year argument +--EXTENSIONS-- +calendar +--FILE-- + +--EXPECT-- +DONE diff -Nru php8.2-8.2.24/ext/calendar/tests/gh16258.phpt php8.2-8.2.26/ext/calendar/tests/gh16258.phpt --- php8.2-8.2.24/ext/calendar/tests/gh16258.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/calendar/tests/gh16258.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,12 @@ +--TEST-- +GH-16258 (jddayofweek overflow on argument) +--EXTENSIONS-- +calendar +--FILE-- + +--EXPECT-- +DONE diff -Nru php8.2-8.2.24/ext/com_dotnet/com_variant.c php8.2-8.2.26/ext/com_dotnet/com_variant.c --- php8.2-8.2.24/ext/com_dotnet/com_variant.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/com_dotnet/com_variant.c 2024-11-19 17:11:09.000000000 +0000 @@ -26,8 +26,7 @@ /* create an automation SafeArray from a PHP array. * Only creates a single-dimensional array of variants. - * The keys of the PHP hash MUST be numeric. If the array - * is sparse, then the gaps will be filled with NULL variants */ + * The keys of the PHP hash MUST be numeric. */ static void safe_array_from_zval(VARIANT *v, zval *z, int codepage) { SAFEARRAY *sa = NULL; @@ -71,7 +70,9 @@ break; } zend_hash_get_current_key_ex(Z_ARRVAL_P(z), &strindex, &intindex, &pos); - php_com_variant_from_zval(&va[intindex], item, codepage); + if (intindex < bound.cElements) { + php_com_variant_from_zval(&va[intindex], item, codepage); + } } /* Unlock it and stuff it into our variant */ diff -Nru php8.2-8.2.24/ext/com_dotnet/tests/variant_variation.phpt php8.2-8.2.26/ext/com_dotnet/tests/variant_variation.phpt --- php8.2-8.2.24/ext/com_dotnet/tests/variant_variation.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/com_dotnet/tests/variant_variation.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,30 @@ +--TEST-- +Testing variant arrays +--EXTENSIONS-- +com_dotnet +--FILE-- + [2 => 1, 1 => 2, 0 => 3], + "off" => [2 => 1, 1 => 2, 3], + "negative" => [-1 => 42], +]; +foreach ($arrays as $desc => $array) { + echo "-- $desc --\n"; + $v = new variant($array); + foreach ($v as $val) { + var_dump($val); + } +} +?> +--EXPECTF-- +-- order -- +int(3) +int(2) +int(1) +-- off -- +NULL +int(2) +int(1) +-- negative -- +%ANULL diff -Nru php8.2-8.2.24/ext/curl/multi.c php8.2-8.2.26/ext/curl/multi.c --- php8.2-8.2.24/ext/curl/multi.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/curl/multi.c 2024-11-19 17:11:09.000000000 +0000 @@ -97,12 +97,14 @@ _php_curl_cleanup_handle(ch); - Z_ADDREF_P(z_ch); - zend_llist_add_element(&mh->easyh, z_ch); - error = curl_multi_add_handle(mh->multi, ch->cp); SAVE_CURLM_ERROR(mh, error); + if (error == CURLM_OK) { + Z_ADDREF_P(z_ch); + zend_llist_add_element(&mh->easyh, z_ch); + } + RETURN_LONG((zend_long) error); } /* }}} */ @@ -164,9 +166,11 @@ error = curl_multi_remove_handle(mh->multi, ch->cp); SAVE_CURLM_ERROR(mh, error); - RETVAL_LONG((zend_long) error); - zend_llist_del_element(&mh->easyh, z_ch, (int (*)(void *, void *))curl_compare_objects); + if (error == CURLM_OK) { + zend_llist_del_element(&mh->easyh, z_ch, (int (*)(void *, void *))curl_compare_objects); + } + RETURN_LONG((zend_long) error); } /* }}} */ diff -Nru php8.2-8.2.24/ext/curl/tests/bug48203_multi.phpt php8.2-8.2.26/ext/curl/tests/bug48203_multi.phpt --- php8.2-8.2.24/ext/curl/tests/bug48203_multi.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/curl/tests/bug48203_multi.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -2,6 +2,13 @@ Variation of bug #48203 with curl_multi_exec (Crash when file pointers passed to curl are closed before calling curl_multi_exec) --EXTENSIONS-- curl +--SKIPIF-- + --FILE-- --FILE-- --EXTENSIONS-- curl +--SKIPIF-- + --FILE-- $ch) { + curl_multi_remove_handle($mh, $ch); + unset($ch); + unset($toRemove[$i]); +} +echo "Removed", PHP_EOL; + +?> +--EXPECTF-- +Removing +MyClass::__destruct +MyClass::__destruct +Removed diff -Nru php8.2-8.2.24/ext/curl/tests/curl_multi_getcontent_basic3.phpt php8.2-8.2.26/ext/curl/tests/curl_multi_getcontent_basic3.phpt --- php8.2-8.2.24/ext/curl/tests/curl_multi_getcontent_basic3.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/curl/tests/curl_multi_getcontent_basic3.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -5,6 +5,13 @@ #TestFest Utrecht 20090509 --EXTENSIONS-- curl +--SKIPIF-- + --FILE-- '9')) && (**ptr != '+') && (**ptr != '-')) { if (**ptr == '\0') { add_error(s, TIMELIB_ERR_UNEXPECTED_DATA, "Found unexpected data"); - timelib_free(str); return 0; } ++*ptr; } - - if ((**ptr == '+') || (**ptr == '-')) { - *str_ptr = **ptr; + + /* Allocate string to feed to strtoll(): sign + length + '\0' */ + str = timelib_calloc(1, max_length + 2); + str[0] = '+'; /* First position is the sign */ + str_ptr = str + 1; + + while ((**ptr == '+') || (**ptr == '-')) { + if (**ptr == '-') { + str[0] = str[0] == '+' ? '-' : '+'; + } ++*ptr; - ++str_ptr; } while (((**ptr < '0') || (**ptr > '9'))) { @@ -715,7 +719,7 @@ static void add_with_overflow(Scanner *s, timelib_sll *e, timelib_sll amount, int multiplier) { -#if defined(__has_builtin) && __has_builtin(__builtin_saddll_overflow) +#if TIMELIB_HAVE_BUILTIN_SADDLL_OVERFLOW if (__builtin_saddll_overflow(*e, amount * multiplier, e)) { add_error(s, TIMELIB_ERR_NUMBER_OUT_OF_RANGE, "Number out of range"); } @@ -1014,11 +1018,11 @@ std: s->tok = cursor; s->len = 0; -#line 1147 "ext/date/lib/parse_date.re" +#line 1151 "ext/date/lib/parse_date.re" -#line 1022 "" +#line 1026 "" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -1199,23 +1203,23 @@ YYDEBUG(2, *YYCURSOR); ++YYCURSOR; YYDEBUG(3, *YYCURSOR); -#line 1980 "ext/date/lib/parse_date.re" +#line 1984 "ext/date/lib/parse_date.re" { s->pos = cursor; s->line++; goto std; } -#line 1208 "" +#line 1212 "" yy4: YYDEBUG(4, *YYCURSOR); ++YYCURSOR; yy5: YYDEBUG(5, *YYCURSOR); -#line 1986 "ext/date/lib/parse_date.re" +#line 1990 "ext/date/lib/parse_date.re" { add_error(s, TIMELIB_ERR_UNEXPECTED_CHARACTER, "Unexpected character"); goto std; } -#line 1219 "" +#line 1223 "" yy6: YYDEBUG(6, *YYCURSOR); yyaccept = 0; @@ -1230,11 +1234,11 @@ if (yych <= '9') goto yy58; yy8: YYDEBUG(8, *YYCURSOR); -#line 1975 "ext/date/lib/parse_date.re" +#line 1979 "ext/date/lib/parse_date.re" { goto std; } -#line 1238 "" +#line 1242 "" yy9: YYDEBUG(9, *YYCURSOR); yych = *++YYCURSOR; @@ -1268,11 +1272,11 @@ YYDEBUG(11, *YYCURSOR); ++YYCURSOR; YYDEBUG(12, *YYCURSOR); -#line 1970 "ext/date/lib/parse_date.re" +#line 1974 "ext/date/lib/parse_date.re" { goto std; } -#line 1276 "" +#line 1280 "" yy13: YYDEBUG(13, *YYCURSOR); yyaccept = 1; @@ -1773,7 +1777,7 @@ } yy20: YYDEBUG(20, *YYCURSOR); -#line 1885 "ext/date/lib/parse_date.re" +#line 1889 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("tzcorrection | tz"); @@ -1787,7 +1791,7 @@ TIMELIB_DEINIT; return TIMELIB_TIMEZONE; } -#line 1791 "" +#line 1795 "" yy21: YYDEBUG(21, *YYCURSOR); yych = *++YYCURSOR; @@ -3592,7 +3596,7 @@ } yy81: YYDEBUG(81, *YYCURSOR); -#line 1632 "ext/date/lib/parse_date.re" +#line 1636 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("datenoyearrev"); TIMELIB_INIT; @@ -3603,7 +3607,7 @@ TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 3607 "" +#line 3611 "" yy82: YYDEBUG(82, *YYCURSOR); yych = *++YYCURSOR; @@ -4118,7 +4122,7 @@ } if (yych == '.') goto yy289; YYDEBUG(114, *YYCURSOR); -#line 1207 "ext/date/lib/parse_date.re" +#line 1211 "ext/date/lib/parse_date.re" { timelib_ull i; @@ -4143,7 +4147,7 @@ TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 4147 "" +#line 4151 "" yy115: YYDEBUG(115, *YYCURSOR); ++YYCURSOR; @@ -5869,7 +5873,7 @@ } yy177: YYDEBUG(177, *YYCURSOR); -#line 1373 "ext/date/lib/parse_date.re" +#line 1377 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("timetiny24 | timeshort24 | timelong24 | iso8601long"); @@ -5896,7 +5900,7 @@ TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 5900 "" +#line 5904 "" yy178: YYDEBUG(178, *YYCURSOR); yyaccept = 4; @@ -6925,7 +6929,7 @@ } yy224: YYDEBUG(224, *YYCURSOR); -#line 1467 "ext/date/lib/parse_date.re" +#line 1471 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("americanshort | american"); @@ -6940,7 +6944,7 @@ TIMELIB_DEINIT; return TIMELIB_AMERICAN; } -#line 6944 "" +#line 6948 "" yy225: YYDEBUG(225, *YYCURSOR); yyaccept = 5; @@ -7183,7 +7187,7 @@ if (yych <= '9') goto yy431; yy251: YYDEBUG(251, *YYCURSOR); -#line 1549 "ext/date/lib/parse_date.re" +#line 1553 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datefull"); @@ -7197,7 +7201,7 @@ TIMELIB_DEINIT; return TIMELIB_DATE_FULL; } -#line 7201 "" +#line 7205 "" yy252: YYDEBUG(252, *YYCURSOR); yyaccept = 3; @@ -7311,7 +7315,7 @@ if (yych == 'e') goto yy440; yy260: YYDEBUG(260, *YYCURSOR); -#line 1954 "ext/date/lib/parse_date.re" +#line 1958 "ext/date/lib/parse_date.re" { timelib_ull i; DEBUG_OUTPUT("relative"); @@ -7326,7 +7330,7 @@ TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 7330 "" +#line 7334 "" yy261: YYDEBUG(261, *YYCURSOR); yych = *++YYCURSOR; @@ -7772,7 +7776,7 @@ if (yych <= '9') goto yy471; yy290: YYDEBUG(290, *YYCURSOR); -#line 1233 "ext/date/lib/parse_date.re" +#line 1237 "ext/date/lib/parse_date.re" { timelib_sll i; timelib_ull us; @@ -7811,7 +7815,7 @@ TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 7815 "" +#line 7819 "" yy291: YYDEBUG(291, *YYCURSOR); yych = *++YYCURSOR; @@ -7836,7 +7840,7 @@ } yy293: YYDEBUG(293, *YYCURSOR); -#line 1795 "ext/date/lib/parse_date.re" +#line 1799 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("ago"); TIMELIB_INIT; @@ -7856,7 +7860,7 @@ TIMELIB_DEINIT; return TIMELIB_AGO; } -#line 7860 "" +#line 7864 "" yy294: YYDEBUG(294, *YYCURSOR); yyaccept = 7; @@ -7895,7 +7899,7 @@ } yy295: YYDEBUG(295, *YYCURSOR); -#line 1875 "ext/date/lib/parse_date.re" +#line 1879 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("monthtext"); TIMELIB_INIT; @@ -7904,7 +7908,7 @@ TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 7908 "" +#line 7912 "" yy296: YYDEBUG(296, *YYCURSOR); yyaccept = 7; @@ -8479,7 +8483,7 @@ } yy315: YYDEBUG(315, *YYCURSOR); -#line 1816 "ext/date/lib/parse_date.re" +#line 1820 "ext/date/lib/parse_date.re" { const timelib_relunit* relunit; DEBUG_OUTPUT("daytext"); @@ -8496,7 +8500,7 @@ TIMELIB_DEINIT; return TIMELIB_WEEKDAY; } -#line 8500 "" +#line 8504 "" yy316: YYDEBUG(316, *YYCURSOR); yych = *++YYCURSOR; @@ -8764,7 +8768,7 @@ } yy325: YYDEBUG(325, *YYCURSOR); -#line 1618 "ext/date/lib/parse_date.re" +#line 1622 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datetextual | datenoyear"); @@ -8777,7 +8781,7 @@ TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 8781 "" +#line 8785 "" yy326: YYDEBUG(326, *YYCURSOR); yyaccept = 10; @@ -9471,7 +9475,7 @@ } yy351: YYDEBUG(351, *YYCURSOR); -#line 1164 "ext/date/lib/parse_date.re" +#line 1168 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("now"); TIMELIB_INIT; @@ -9479,7 +9483,7 @@ TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 9483 "" +#line 9487 "" yy352: YYDEBUG(352, *YYCURSOR); yyaccept = 2; @@ -10982,7 +10986,7 @@ } yy420: YYDEBUG(420, *YYCURSOR); -#line 1401 "ext/date/lib/parse_date.re" +#line 1405 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("gnunocolon"); TIMELIB_INIT; @@ -11004,7 +11008,7 @@ TIMELIB_DEINIT; return TIMELIB_GNU_NOCOLON; } -#line 11008 "" +#line 11012 "" yy421: YYDEBUG(421, *YYCURSOR); yyaccept = 13; @@ -11085,7 +11089,7 @@ } yy422: YYDEBUG(422, *YYCURSOR); -#line 1786 "ext/date/lib/parse_date.re" +#line 1790 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("year4"); TIMELIB_INIT; @@ -11093,7 +11097,7 @@ TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 11097 "" +#line 11101 "" yy423: YYDEBUG(423, *YYCURSOR); yyaccept = 3; @@ -11700,7 +11704,7 @@ YYDEBUG(456, *YYCURSOR); ++YYCURSOR; YYDEBUG(457, *YYCURSOR); -#line 1335 "ext/date/lib/parse_date.re" +#line 1339 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12"); TIMELIB_INIT; @@ -11717,7 +11721,7 @@ TIMELIB_DEINIT; return TIMELIB_TIME12; } -#line 11721 "" +#line 11725 "" yy458: YYDEBUG(458, *YYCURSOR); yych = *++YYCURSOR; @@ -13044,7 +13048,7 @@ } yy526: YYDEBUG(526, *YYCURSOR); -#line 1173 "ext/date/lib/parse_date.re" +#line 1177 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("noon"); TIMELIB_INIT; @@ -13055,7 +13059,7 @@ TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 13059 "" +#line 13063 "" yy527: YYDEBUG(527, *YYCURSOR); yyaccept = 2; @@ -14101,7 +14105,7 @@ } yy567: YYDEBUG(567, *YYCURSOR); -#line 1535 "ext/date/lib/parse_date.re" +#line 1539 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("gnudateshort"); @@ -14114,7 +14118,7 @@ TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 14118 "" +#line 14122 "" yy568: YYDEBUG(568, *YYCURSOR); yyaccept = 15; @@ -14565,7 +14569,7 @@ } yy600: YYDEBUG(600, *YYCURSOR); -#line 1604 "ext/date/lib/parse_date.re" +#line 1608 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datenodayrev"); @@ -14578,7 +14582,7 @@ TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 14582 "" +#line 14586 "" yy601: YYDEBUG(601, *YYCURSOR); yych = *++YYCURSOR; @@ -15953,7 +15957,7 @@ YYDEBUG(696, *YYCURSOR); ++YYCURSOR; YYDEBUG(697, *YYCURSOR); -#line 1590 "ext/date/lib/parse_date.re" +#line 1594 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datenoday"); @@ -15966,7 +15970,7 @@ TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 15970 "" +#line 15974 "" yy698: YYDEBUG(698, *YYCURSOR); yych = *++YYCURSOR; @@ -16527,7 +16531,7 @@ } yy722: YYDEBUG(722, *YYCURSOR); -#line 1185 "ext/date/lib/parse_date.re" +#line 1189 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("midnight | today"); TIMELIB_INIT; @@ -16536,7 +16540,7 @@ TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 16540 "" +#line 16544 "" yy723: YYDEBUG(723, *YYCURSOR); yych = *++YYCURSOR; @@ -16846,7 +16850,7 @@ if (yych <= '9') goto yy897; yy739: YYDEBUG(739, *YYCURSOR); -#line 1576 "ext/date/lib/parse_date.re" +#line 1580 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pointed date YY"); @@ -16859,7 +16863,7 @@ TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 16863 "" +#line 16867 "" yy740: YYDEBUG(740, *YYCURSOR); yyaccept = 15; @@ -16971,7 +16975,7 @@ } yy752: YYDEBUG(752, *YYCURSOR); -#line 1521 "ext/date/lib/parse_date.re" +#line 1525 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("gnudateshorter"); @@ -16984,7 +16988,7 @@ TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 16988 "" +#line 16992 "" yy753: YYDEBUG(753, *YYCURSOR); yyaccept = 18; @@ -17233,7 +17237,7 @@ } yy777: YYDEBUG(777, *YYCURSOR); -#line 1447 "ext/date/lib/parse_date.re" +#line 1451 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("iso8601nocolon"); @@ -17252,7 +17256,7 @@ TIMELIB_DEINIT; return TIMELIB_ISO_NOCOLON; } -#line 17256 "" +#line 17260 "" yy778: YYDEBUG(778, *YYCURSOR); yyaccept = 19; @@ -18480,7 +18484,7 @@ } yy849: YYDEBUG(849, *YYCURSOR); -#line 1924 "ext/date/lib/parse_date.re" +#line 1928 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz"); @@ -18509,7 +18513,7 @@ TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 18513 "" +#line 18517 "" yy850: YYDEBUG(850, *YYCURSOR); yyaccept = 20; @@ -19553,7 +19557,7 @@ } yy926: YYDEBUG(926, *YYCURSOR); -#line 1682 "ext/date/lib/parse_date.re" +#line 1686 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgydotd"); @@ -19566,7 +19570,7 @@ TIMELIB_DEINIT; return TIMELIB_PG_YEARDAY; } -#line 19570 "" +#line 19574 "" yy927: YYDEBUG(927, *YYCURSOR); yyaccept = 21; @@ -19820,7 +19824,7 @@ if (yych <= '7') goto yy1059; yy942: YYDEBUG(942, *YYCURSOR); -#line 1715 "ext/date/lib/parse_date.re" +#line 1719 "ext/date/lib/parse_date.re" { timelib_sll w, d; DEBUG_OUTPUT("isoweek"); @@ -19838,7 +19842,7 @@ TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 19842 "" +#line 19846 "" yy943: YYDEBUG(943, *YYCURSOR); yych = *++YYCURSOR; @@ -20314,7 +20318,7 @@ if (yych == 'e') goto yy1094; yy982: YYDEBUG(982, *YYCURSOR); -#line 1858 "ext/date/lib/parse_date.re" +#line 1862 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -20330,7 +20334,7 @@ TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 20334 "" +#line 20338 "" yy983: YYDEBUG(983, *YYCURSOR); yych = *++YYCURSOR; @@ -20677,7 +20681,7 @@ YYDEBUG(1020, *YYCURSOR); ++YYCURSOR; YYDEBUG(1021, *YYCURSOR); -#line 1564 "ext/date/lib/parse_date.re" +#line 1568 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("pointed date YYYY"); TIMELIB_INIT; @@ -20688,7 +20692,7 @@ TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 20692 "" +#line 20696 "" yy1022: YYDEBUG(1022, *YYCURSOR); ++YYCURSOR; @@ -20717,7 +20721,7 @@ } yy1025: YYDEBUG(1025, *YYCURSOR); -#line 1495 "ext/date/lib/parse_date.re" +#line 1499 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("iso8601date2"); @@ -20730,7 +20734,7 @@ TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 20734 "" +#line 20738 "" yy1026: YYDEBUG(1026, *YYCURSOR); yyaccept = 15; @@ -20950,7 +20954,7 @@ } yy1043: YYDEBUG(1043, *YYCURSOR); -#line 1483 "ext/date/lib/parse_date.re" +#line 1487 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash"); TIMELIB_INIT; @@ -20961,7 +20965,7 @@ TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 20965 "" +#line 20969 "" yy1044: YYDEBUG(1044, *YYCURSOR); yyaccept = 26; @@ -21076,7 +21080,7 @@ } yy1048: YYDEBUG(1048, *YYCURSOR); -#line 1644 "ext/date/lib/parse_date.re" +#line 1648 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("datenocolon"); TIMELIB_INIT; @@ -21087,7 +21091,7 @@ TIMELIB_DEINIT; return TIMELIB_DATE_NOCOLON; } -#line 21091 "" +#line 21095 "" yy1049: YYDEBUG(1049, *YYCURSOR); yych = *++YYCURSOR; @@ -21157,7 +21161,7 @@ YYDEBUG(1059, *YYCURSOR); ++YYCURSOR; YYDEBUG(1060, *YYCURSOR); -#line 1696 "ext/date/lib/parse_date.re" +#line 1700 "ext/date/lib/parse_date.re" { timelib_sll w, d; DEBUG_OUTPUT("isoweekday"); @@ -21175,7 +21179,7 @@ TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 21179 "" +#line 21183 "" yy1061: YYDEBUG(1061, *YYCURSOR); yych = *++YYCURSOR; @@ -21238,7 +21242,7 @@ if (yych <= '9') goto yy1143; yy1070: YYDEBUG(1070, *YYCURSOR); -#line 1734 "ext/date/lib/parse_date.re" +#line 1738 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgtextshort"); @@ -21251,7 +21255,7 @@ TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 21255 "" +#line 21259 "" yy1071: YYDEBUG(1071, *YYCURSOR); yych = *++YYCURSOR; @@ -21724,7 +21728,7 @@ ++YYCURSOR; yy1107: YYDEBUG(1107, *YYCURSOR); -#line 1195 "ext/date/lib/parse_date.re" +#line 1199 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("tomorrow"); TIMELIB_INIT; @@ -21735,7 +21739,7 @@ TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 21739 "" +#line 21743 "" yy1108: YYDEBUG(1108, *YYCURSOR); yyaccept = 28; @@ -22072,7 +22076,7 @@ YYDEBUG(1140, *YYCURSOR); ++YYCURSOR; YYDEBUG(1141, *YYCURSOR); -#line 1748 "ext/date/lib/parse_date.re" +#line 1752 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgtextreverse"); @@ -22085,7 +22089,7 @@ TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 22089 "" +#line 22093 "" yy1142: YYDEBUG(1142, *YYCURSOR); ++YYCURSOR; @@ -22129,7 +22133,7 @@ } yy1145: YYDEBUG(1145, *YYCURSOR); -#line 1290 "ext/date/lib/parse_date.re" +#line 1294 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("backof | frontof"); TIMELIB_INIT; @@ -22151,7 +22155,7 @@ TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 22155 "" +#line 22159 "" yy1146: YYDEBUG(1146, *YYCURSOR); yyaccept = 29; @@ -22475,7 +22479,7 @@ } yy1172: YYDEBUG(1172, *YYCURSOR); -#line 1834 "ext/date/lib/parse_date.re" +#line 1838 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -22498,7 +22502,7 @@ TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22502 "" +#line 22506 "" yy1173: YYDEBUG(1173, *YYCURSOR); yych = *++YYCURSOR; @@ -22510,7 +22514,7 @@ ++YYCURSOR; yy1175: YYDEBUG(1175, *YYCURSOR); -#line 1152 "ext/date/lib/parse_date.re" +#line 1156 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("yesterday"); TIMELIB_INIT; @@ -22521,7 +22525,7 @@ TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22525 "" +#line 22529 "" yy1176: YYDEBUG(1176, *YYCURSOR); yyaccept = 31; @@ -23014,7 +23018,7 @@ YYDEBUG(1222, *YYCURSOR); ++YYCURSOR; YYDEBUG(1223, *YYCURSOR); -#line 1900 "ext/date/lib/parse_date.re" +#line 1904 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12"); TIMELIB_INIT; @@ -23037,7 +23041,7 @@ TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 23041 "" +#line 23045 "" yy1224: YYDEBUG(1224, *YYCURSOR); yych = *++YYCURSOR; @@ -23539,7 +23543,7 @@ YYDEBUG(1268, *YYCURSOR); ++YYCURSOR; YYDEBUG(1269, *YYCURSOR); -#line 1313 "ext/date/lib/parse_date.re" +#line 1317 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -23560,7 +23564,7 @@ TIMELIB_DEINIT; return TIMELIB_WEEK_DAY_OF_MONTH; } -#line 23564 "" +#line 23568 "" yy1270: YYDEBUG(1270, *YYCURSOR); yyaccept = 24; @@ -23607,7 +23611,7 @@ YYDEBUG(1273, *YYCURSOR); ++YYCURSOR; YYDEBUG(1274, *YYCURSOR); -#line 1273 "ext/date/lib/parse_date.re" +#line 1277 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("firstdayof | lastdayof"); TIMELIB_INIT; @@ -23623,12 +23627,12 @@ TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 23627 "" +#line 23631 "" yy1275: YYDEBUG(1275, *YYCURSOR); ++YYCURSOR; YYDEBUG(1276, *YYCURSOR); -#line 1509 "ext/date/lib/parse_date.re" +#line 1513 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("iso8601datex"); TIMELIB_INIT; @@ -23639,7 +23643,7 @@ TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 23643 "" +#line 23647 "" yy1277: YYDEBUG(1277, *YYCURSOR); yych = *++YYCURSOR; @@ -23742,7 +23746,7 @@ YYDEBUG(1290, *YYCURSOR); ++YYCURSOR; YYDEBUG(1291, *YYCURSOR); -#line 1353 "ext/date/lib/parse_date.re" +#line 1357 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("mssqltime"); TIMELIB_INIT; @@ -23761,7 +23765,7 @@ TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 23765 "" +#line 23769 "" yy1292: YYDEBUG(1292, *YYCURSOR); yych = *++YYCURSOR; @@ -24185,7 +24189,7 @@ if (yych <= '9') goto yy1331; yy1329: YYDEBUG(1329, *YYCURSOR); -#line 1656 "ext/date/lib/parse_date.re" +#line 1660 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif"); @@ -24210,7 +24214,7 @@ TIMELIB_DEINIT; return TIMELIB_XMLRPC_SOAP; } -#line 24214 "" +#line 24218 "" yy1330: YYDEBUG(1330, *YYCURSOR); yych = *++YYCURSOR; @@ -24580,7 +24584,7 @@ if (yych <= ':') goto yy1383; yy1375: YYDEBUG(1375, *YYCURSOR); -#line 1762 "ext/date/lib/parse_date.re" +#line 1766 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("clf"); @@ -24603,7 +24607,7 @@ TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 24607 "" +#line 24611 "" yy1376: YYDEBUG(1376, *YYCURSOR); yyaccept = 33; @@ -24835,7 +24839,7 @@ if (yych == ':') goto yy1286; goto yy1329; } -#line 1990 "ext/date/lib/parse_date.re" +#line 1994 "ext/date/lib/parse_date.re" } diff -Nru php8.2-8.2.24/ext/date/lib/parse_date.re php8.2-8.2.26/ext/date/lib/parse_date.re --- php8.2-8.2.24/ext/date/lib/parse_date.re 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/date/lib/parse_date.re 2024-11-19 17:11:09.000000000 +0000 @@ -547,22 +547,26 @@ timelib_sll tmp_nr = 0; int len = 0; - str = timelib_calloc(1, max_length + 2); // for sign and \0 - str_ptr = str; + /* Skip over non-numeric chars */ while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) { if (**ptr == '\0') { add_error(s, TIMELIB_ERR_UNEXPECTED_DATA, "Found unexpected data"); - timelib_free(str); return 0; } ++*ptr; } - - if ((**ptr == '+') || (**ptr == '-')) { - *str_ptr = **ptr; + + /* Allocate string to feed to strtoll(): sign + length + '\0' */ + str = timelib_calloc(1, max_length + 2); + str[0] = '+'; /* First position is the sign */ + str_ptr = str + 1; + + while ((**ptr == '+') || (**ptr == '-')) { + if (**ptr == '-') { + str[0] = str[0] == '+' ? '-' : '+'; + } ++*ptr; - ++str_ptr; } while (((**ptr < '0') || (**ptr > '9'))) { @@ -713,7 +717,7 @@ static void add_with_overflow(Scanner *s, timelib_sll *e, timelib_sll amount, int multiplier) { -#if defined(__has_builtin) && __has_builtin(__builtin_saddll_overflow) +#if TIMELIB_HAVE_BUILTIN_SADDLL_OVERFLOW if (__builtin_saddll_overflow(*e, amount * multiplier, e)) { add_error(s, TIMELIB_ERR_NUMBER_OUT_OF_RANGE, "Number out of range"); } diff -Nru php8.2-8.2.24/ext/date/lib/parse_iso_intervals.c php8.2-8.2.26/ext/date/lib/parse_iso_intervals.c --- php8.2-8.2.24/ext/date/lib/parse_iso_intervals.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/date/lib/parse_iso_intervals.c 2024-11-19 17:11:09.000000000 +0000 @@ -1,4 +1,4 @@ -/* Generated by re2c 0.15.3 on Wed Sep 14 16:32:05 2022 */ +/* Generated by re2c 1.0.3 on Wed Sep 11 17:29:40 2024 */ #line 1 "ext/date/lib/parse_iso_intervals.re" /* * The MIT License (MIT) @@ -223,54 +223,72 @@ yych = *YYCURSOR; if (yych <= ',') { if (yych <= '\n') { - if (yych <= 0x00) goto yy9; - if (yych <= 0x08) goto yy11; - if (yych <= '\t') goto yy7; - goto yy9; - } else { - if (yych == ' ') goto yy7; - if (yych <= '+') goto yy11; - goto yy7; + if (yych <= 0x00) goto yy2; + if (yych <= 0x08) goto yy4; + if (yych <= '\t') goto yy6; + } else { + if (yych == ' ') goto yy6; + if (yych <= '+') goto yy4; + goto yy6; } } else { if (yych <= 'O') { - if (yych <= '-') goto yy11; - if (yych <= '/') goto yy7; - if (yych <= '9') goto yy4; - goto yy11; + if (yych <= '-') goto yy4; + if (yych <= '/') goto yy6; + if (yych <= '9') goto yy8; + goto yy4; } else { - if (yych <= 'P') goto yy5; - if (yych != 'R') goto yy11; + if (yych <= 'P') goto yy9; + if (yych == 'R') goto yy11; + goto yy4; } } +yy2: YYDEBUG(2, *YYCURSOR); ++YYCURSOR; - if ((yych = *YYCURSOR) <= '/') goto yy3; - if (yych <= '9') goto yy98; -yy3: YYDEBUG(3, *YYCURSOR); -#line 317 "ext/date/lib/parse_iso_intervals.re" +#line 311 "ext/date/lib/parse_iso_intervals.re" { - add_error(s, "Unexpected character"); + s->pos = cursor; s->line++; goto std; } -#line 258 "" +#line 256 "" yy4: YYDEBUG(4, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych <= '/') goto yy3; - if (yych <= '9') goto yy59; - goto yy3; + ++YYCURSOR; yy5: YYDEBUG(5, *YYCURSOR); - yyaccept = 1; - yych = *(YYMARKER = ++YYCURSOR); - if (yych <= '/') goto yy6; - if (yych <= '9') goto yy12; - if (yych == 'T') goto yy14; +#line 317 "ext/date/lib/parse_iso_intervals.re" + { + add_error(s, "Unexpected character"); + goto std; + } +#line 267 "" yy6: YYDEBUG(6, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(7, *YYCURSOR); +#line 306 "ext/date/lib/parse_iso_intervals.re" + { + goto std; + } +#line 276 "" +yy8: + YYDEBUG(8, *YYCURSOR); + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '/') goto yy5; + if (yych <= '9') goto yy12; + goto yy5; +yy9: + YYDEBUG(9, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '/') goto yy10; + if (yych <= '9') goto yy14; + if (yych == 'T') goto yy15; +yy10: + YYDEBUG(10, *YYCURSOR); #line 244 "ext/date/lib/parse_iso_intervals.re" { timelib_sll nr; @@ -312,189 +330,197 @@ TIMELIB_DEINIT; return TIMELIB_PERIOD; } -#line 316 "" -yy7: - YYDEBUG(7, *YYCURSOR); - ++YYCURSOR; - YYDEBUG(8, *YYCURSOR); -#line 306 "ext/date/lib/parse_iso_intervals.re" - { - goto std; - } -#line 325 "" -yy9: - YYDEBUG(9, *YYCURSOR); - ++YYCURSOR; - YYDEBUG(10, *YYCURSOR); -#line 311 "ext/date/lib/parse_iso_intervals.re" - { - s->pos = cursor; s->line++; - goto std; - } -#line 335 "" +#line 334 "" yy11: YYDEBUG(11, *YYCURSOR); yych = *++YYCURSOR; - goto yy3; + if (yybm[0+yych] & 128) { + goto yy16; + } + goto yy5; yy12: YYDEBUG(12, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= 'L') { - if (yych <= '9') { - if (yych >= '0') goto yy25; - } else { - if (yych == 'D') goto yy24; - } - } else { - if (yych <= 'W') { - if (yych <= 'M') goto yy27; - if (yych >= 'W') goto yy26; - } else { - if (yych == 'Y') goto yy28; - } - } + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy19; yy13: YYDEBUG(13, *YYCURSOR); YYCURSOR = YYMARKER; if (yyaccept == 0) { - goto yy3; + goto yy5; } else { - goto yy6; + goto yy10; } yy14: YYDEBUG(14, *YYCURSOR); - yyaccept = 1; - yych = *(YYMARKER = ++YYCURSOR); - if (yybm[0+yych] & 128) { - goto yy15; + yych = *++YYCURSOR; + if (yych <= 'L') { + if (yych <= '9') { + if (yych <= '/') goto yy13; + goto yy20; + } else { + if (yych == 'D') goto yy21; + goto yy13; + } + } else { + if (yych <= 'W') { + if (yych <= 'M') goto yy22; + if (yych <= 'V') goto yy13; + goto yy23; + } else { + if (yych == 'Y') goto yy24; + goto yy13; + } } - goto yy6; yy15: YYDEBUG(15, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '/') goto yy10; + if (yych <= '9') goto yy25; + goto yy10; +yy16: + YYDEBUG(16, *YYCURSOR); ++YYCURSOR; - if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = *YYCURSOR; - YYDEBUG(16, *YYCURSOR); + YYDEBUG(17, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy15; + goto yy16; } + YYDEBUG(18, *YYCURSOR); +#line 209 "ext/date/lib/parse_iso_intervals.re" + { + DEBUG_OUTPUT("recurrences"); + TIMELIB_INIT; + ptr++; + s->recurrences = timelib_get_unsigned_nr(&ptr, 9); + TIMELIB_DEINIT; + s->have_recurrences = 1; + return TIMELIB_PERIOD; + } +#line 403 "" +yy19: + YYDEBUG(19, *YYCURSOR); + yych = *++YYCURSOR; + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy27; + goto yy13; +yy20: + YYDEBUG(20, *YYCURSOR); + yych = *++YYCURSOR; if (yych <= 'L') { - if (yych == 'H') goto yy19; - goto yy13; + if (yych <= '9') { + if (yych <= '/') goto yy13; + goto yy28; + } else { + if (yych != 'D') goto yy13; + } } else { - if (yych <= 'M') goto yy18; - if (yych != 'S') goto yy13; + if (yych <= 'W') { + if (yych <= 'M') goto yy22; + if (yych <= 'V') goto yy13; + goto yy23; + } else { + if (yych == 'Y') goto yy24; + goto yy13; + } } -yy17: - YYDEBUG(17, *YYCURSOR); +yy21: + YYDEBUG(21, *YYCURSOR); yych = *++YYCURSOR; - goto yy6; -yy18: - YYDEBUG(18, *YYCURSOR); + if (yych == 'T') goto yy15; + goto yy10; +yy22: + YYDEBUG(22, *YYCURSOR); yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych <= '/') goto yy6; - if (yych <= '9') goto yy22; - goto yy6; -yy19: - YYDEBUG(19, *YYCURSOR); + if (yych <= '/') goto yy10; + if (yych <= '9') goto yy29; + if (yych == 'T') goto yy15; + goto yy10; +yy23: + YYDEBUG(23, *YYCURSOR); yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych <= '/') goto yy6; - if (yych >= ':') goto yy6; -yy20: - YYDEBUG(20, *YYCURSOR); + if (yych <= '/') goto yy10; + if (yych <= '9') goto yy31; + if (yych == 'T') goto yy15; + goto yy10; +yy24: + YYDEBUG(24, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '/') goto yy10; + if (yych <= '9') goto yy33; + if (yych == 'T') goto yy15; + goto yy10; +yy25: + YYDEBUG(25, *YYCURSOR); ++YYCURSOR; if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); yych = *YYCURSOR; - YYDEBUG(21, *YYCURSOR); - if (yych <= 'L') { + YYDEBUG(26, *YYCURSOR); + if (yych <= 'H') { if (yych <= '/') goto yy13; - if (yych <= '9') goto yy20; + if (yych <= '9') goto yy25; + if (yych <= 'G') goto yy13; + goto yy35; + } else { + if (yych <= 'M') { + if (yych <= 'L') goto yy13; + goto yy36; + } else { + if (yych == 'S') goto yy37; + goto yy13; + } + } +yy27: + YYDEBUG(27, *YYCURSOR); + yych = *++YYCURSOR; + if (yych <= '/') { + if (yych == '-') goto yy38; goto yy13; } else { - if (yych <= 'M') goto yy18; - if (yych == 'S') goto yy17; + if (yych <= '0') goto yy39; + if (yych <= '1') goto yy40; goto yy13; } -yy22: - YYDEBUG(22, *YYCURSOR); - ++YYCURSOR; - if (YYLIMIT <= YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - YYDEBUG(23, *YYCURSOR); - if (yych <= '/') goto yy13; - if (yych <= '9') goto yy22; - if (yych == 'S') goto yy17; - goto yy13; -yy24: - YYDEBUG(24, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy14; - goto yy6; -yy25: - YYDEBUG(25, *YYCURSOR); +yy28: + YYDEBUG(28, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'L') { if (yych <= '9') { if (yych <= '/') goto yy13; - goto yy35; + goto yy41; } else { - if (yych == 'D') goto yy24; + if (yych == 'D') goto yy21; goto yy13; } } else { if (yych <= 'W') { - if (yych <= 'M') goto yy27; + if (yych <= 'M') goto yy22; if (yych <= 'V') goto yy13; + goto yy23; } else { - if (yych == 'Y') goto yy28; + if (yych == 'Y') goto yy24; goto yy13; } } -yy26: - YYDEBUG(26, *YYCURSOR); - yyaccept = 1; - yych = *(YYMARKER = ++YYCURSOR); - if (yych <= '/') goto yy6; - if (yych <= '9') goto yy33; - if (yych == 'T') goto yy14; - goto yy6; -yy27: - YYDEBUG(27, *YYCURSOR); - yyaccept = 1; - yych = *(YYMARKER = ++YYCURSOR); - if (yych <= '/') goto yy6; - if (yych <= '9') goto yy31; - if (yych == 'T') goto yy14; - goto yy6; -yy28: - YYDEBUG(28, *YYCURSOR); - yyaccept = 1; - yych = *(YYMARKER = ++YYCURSOR); - if (yych <= '/') goto yy6; - if (yych <= '9') goto yy29; - if (yych == 'T') goto yy14; - goto yy6; yy29: YYDEBUG(29, *YYCURSOR); ++YYCURSOR; if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3); yych = *YYCURSOR; YYDEBUG(30, *YYCURSOR); - if (yych <= 'D') { + if (yych <= 'C') { if (yych <= '/') goto yy13; if (yych <= '9') goto yy29; - if (yych <= 'C') goto yy13; - goto yy24; + goto yy13; } else { - if (yych <= 'M') { - if (yych <= 'L') goto yy13; - goto yy27; - } else { - if (yych == 'W') goto yy26; - goto yy13; - } + if (yych <= 'D') goto yy21; + if (yych == 'W') goto yy23; + goto yy13; } yy31: YYDEBUG(31, *YYCURSOR); @@ -502,313 +528,372 @@ if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3); yych = *YYCURSOR; YYDEBUG(32, *YYCURSOR); - if (yych <= 'C') { - if (yych <= '/') goto yy13; - if (yych <= '9') goto yy31; - goto yy13; - } else { - if (yych <= 'D') goto yy24; - if (yych == 'W') goto yy26; - goto yy13; - } + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy31; + if (yych == 'D') goto yy21; + goto yy13; yy33: YYDEBUG(33, *YYCURSOR); ++YYCURSOR; if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3); yych = *YYCURSOR; YYDEBUG(34, *YYCURSOR); - if (yych <= '/') goto yy13; - if (yych <= '9') goto yy33; - if (yych == 'D') goto yy24; - goto yy13; -yy35: - YYDEBUG(35, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= 'L') { - if (yych <= '9') { - if (yych <= '/') goto yy13; - } else { - if (yych == 'D') goto yy24; - goto yy13; - } + if (yych <= 'D') { + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy33; + if (yych <= 'C') goto yy13; + goto yy21; } else { - if (yych <= 'W') { - if (yych <= 'M') goto yy27; - if (yych <= 'V') goto yy13; - goto yy26; + if (yych <= 'M') { + if (yych <= 'L') goto yy13; + goto yy22; } else { - if (yych == 'Y') goto yy28; + if (yych == 'W') goto yy23; goto yy13; } } +yy35: + YYDEBUG(35, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '/') goto yy10; + if (yych <= '9') goto yy42; + goto yy10; +yy36: YYDEBUG(36, *YYCURSOR); - yych = *++YYCURSOR; - if (yych != '-') goto yy39; + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '/') goto yy10; + if (yych <= '9') goto yy44; + goto yy10; +yy37: YYDEBUG(37, *YYCURSOR); + ++YYCURSOR; + goto yy10; +yy38: + YYDEBUG(38, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '0') goto yy40; - if (yych <= '1') goto yy41; + if (yych <= '0') goto yy46; + if (yych <= '1') goto yy47; goto yy13; -yy38: - YYDEBUG(38, *YYCURSOR); - ++YYCURSOR; - if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3); - yych = *YYCURSOR; yy39: YYDEBUG(39, *YYCURSOR); - if (yych <= 'L') { - if (yych <= '9') { - if (yych <= '/') goto yy13; - goto yy38; - } else { - if (yych == 'D') goto yy24; - goto yy13; - } - } else { - if (yych <= 'W') { - if (yych <= 'M') goto yy27; - if (yych <= 'V') goto yy13; - goto yy26; - } else { - if (yych == 'Y') goto yy28; - goto yy13; - } - } + yych = *++YYCURSOR; + if (yych <= '0') goto yy13; + if (yych <= '9') goto yy48; + goto yy13; yy40: YYDEBUG(40, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '9') goto yy42; + if (yych <= '2') goto yy48; goto yy13; yy41: YYDEBUG(41, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= '3') goto yy13; + if (yych == '-') goto yy49; + goto yy51; yy42: YYDEBUG(42, *YYCURSOR); - yych = *++YYCURSOR; - if (yych != '-') goto yy13; + ++YYCURSOR; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; YYDEBUG(43, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych <= '0') goto yy44; - if (yych <= '2') goto yy45; - if (yych <= '3') goto yy46; - goto yy13; + if (yych <= 'L') { + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy42; + goto yy13; + } else { + if (yych <= 'M') goto yy36; + if (yych == 'S') goto yy37; + goto yy13; + } yy44: YYDEBUG(44, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych <= '9') goto yy47; - goto yy13; -yy45: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; YYDEBUG(45, *YYCURSOR); - yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '9') goto yy47; + if (yych <= '9') goto yy44; + if (yych == 'S') goto yy37; goto yy13; yy46: YYDEBUG(46, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= '2') goto yy13; + if (yych <= '0') goto yy13; + if (yych <= '9') goto yy52; + goto yy13; yy47: YYDEBUG(47, *YYCURSOR); yych = *++YYCURSOR; - if (yych != 'T') goto yy13; + if (yych <= '/') goto yy13; + if (yych <= '2') goto yy52; + goto yy13; +yy48: YYDEBUG(48, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '1') goto yy49; - if (yych <= '2') goto yy50; + if (yych <= '0') goto yy53; + if (yych <= '2') goto yy54; + if (yych <= '3') goto yy55; goto yy13; yy49: YYDEBUG(49, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '9') goto yy51; + if (yych <= '0') goto yy56; + if (yych <= '1') goto yy57; goto yy13; yy50: YYDEBUG(50, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= '5') goto yy13; + ++YYCURSOR; + if ((YYLIMIT - YYCURSOR) < 3) YYFILL(3); + yych = *YYCURSOR; yy51: YYDEBUG(51, *YYCURSOR); - yych = *++YYCURSOR; - if (yych != ':') goto yy13; + if (yych <= 'L') { + if (yych <= '9') { + if (yych <= '/') goto yy13; + goto yy50; + } else { + if (yych == 'D') goto yy21; + goto yy13; + } + } else { + if (yych <= 'W') { + if (yych <= 'M') goto yy22; + if (yych <= 'V') goto yy13; + goto yy23; + } else { + if (yych == 'Y') goto yy24; + goto yy13; + } + } +yy52: YYDEBUG(52, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= '6') goto yy13; + if (yych == '-') goto yy58; + goto yy13; +yy53: YYDEBUG(53, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= ':') goto yy13; + if (yych <= '0') goto yy13; + if (yych <= '9') goto yy59; + goto yy13; +yy54: YYDEBUG(54, *YYCURSOR); yych = *++YYCURSOR; - if (yych != ':') goto yy13; + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy59; + goto yy13; +yy55: YYDEBUG(55, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych >= '6') goto yy13; + if (yych <= '1') goto yy59; + goto yy13; +yy56: YYDEBUG(56, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych >= ':') goto yy13; + if (yych <= '9') goto yy60; + goto yy13; +yy57: YYDEBUG(57, *YYCURSOR); - ++YYCURSOR; + yych = *++YYCURSOR; + if (yych <= '/') goto yy13; + if (yych <= '2') goto yy60; + goto yy13; +yy58: YYDEBUG(58, *YYCURSOR); -#line 286 "ext/date/lib/parse_iso_intervals.re" - { - DEBUG_OUTPUT("combinedrep"); - TIMELIB_INIT; - s->period->y = timelib_get_unsigned_nr(&ptr, 4); - ptr++; - s->period->m = timelib_get_unsigned_nr(&ptr, 2); - ptr++; - s->period->d = timelib_get_unsigned_nr(&ptr, 2); - ptr++; - s->period->h = timelib_get_unsigned_nr(&ptr, 2); - ptr++; - s->period->i = timelib_get_unsigned_nr(&ptr, 2); - ptr++; - s->period->s = timelib_get_unsigned_nr(&ptr, 2); - s->have_period = 1; - TIMELIB_DEINIT; - return TIMELIB_PERIOD; - } -#line 684 "" + yych = *++YYCURSOR; + if (yych <= '/') goto yy13; + if (yych <= '0') goto yy61; + if (yych <= '2') goto yy62; + if (yych <= '3') goto yy63; + goto yy13; yy59: YYDEBUG(59, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= ':') goto yy13; + if (yych == 'T') goto yy64; + goto yy13; +yy60: YYDEBUG(60, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= ':') goto yy13; + if (yych == '-') goto yy65; + goto yy13; +yy61: YYDEBUG(61, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') { - if (yych == '-') goto yy64; - goto yy13; - } else { - if (yych <= '0') goto yy62; - if (yych <= '1') goto yy63; - goto yy13; - } + if (yych <= '0') goto yy13; + if (yych <= '9') goto yy66; + goto yy13; yy62: YYDEBUG(62, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '0') goto yy13; - if (yych <= '9') goto yy85; + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy66; goto yy13; yy63: YYDEBUG(63, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '2') goto yy85; + if (yych <= '1') goto yy66; goto yy13; yy64: YYDEBUG(64, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '0') goto yy65; - if (yych <= '1') goto yy66; + if (yych <= '1') goto yy67; + if (yych <= '2') goto yy68; goto yy13; yy65: YYDEBUG(65, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '0') goto yy13; - if (yych <= '9') goto yy67; + if (yych <= '/') goto yy13; + if (yych <= '2') goto yy69; + if (yych <= '3') goto yy70; goto yy13; yy66: YYDEBUG(66, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= '3') goto yy13; + if (yych == 'T') goto yy71; + goto yy13; yy67: YYDEBUG(67, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '-') goto yy13; + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy72; + goto yy13; +yy68: YYDEBUG(68, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '0') goto yy69; - if (yych <= '2') goto yy70; - if (yych <= '3') goto yy71; + if (yych <= '4') goto yy72; goto yy13; yy69: YYDEBUG(69, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '0') goto yy13; - if (yych <= '9') goto yy72; + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy73; goto yy13; yy70: YYDEBUG(70, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '9') goto yy72; + if (yych <= '1') goto yy73; goto yy13; yy71: YYDEBUG(71, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych >= '2') goto yy13; + if (yych <= '1') goto yy74; + if (yych <= '2') goto yy75; + goto yy13; yy72: YYDEBUG(72, *YYCURSOR); yych = *++YYCURSOR; - if (yych != 'T') goto yy13; + if (yych <= '/') goto yy13; + if (yych <= '5') goto yy76; + goto yy13; +yy73: YYDEBUG(73, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych <= '1') goto yy74; - if (yych <= '2') goto yy75; + if (yych == 'T') goto yy77; goto yy13; yy74: YYDEBUG(74, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '9') goto yy76; + if (yych <= '9') goto yy78; goto yy13; yy75: YYDEBUG(75, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych >= '5') goto yy13; + if (yych <= '4') goto yy78; + goto yy13; yy76: YYDEBUG(76, *YYCURSOR); yych = *++YYCURSOR; - if (yych != ':') goto yy13; + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy79; + goto yy13; +yy77: YYDEBUG(77, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych >= '6') goto yy13; + if (yych <= '1') goto yy80; + if (yych <= '2') goto yy81; + goto yy13; +yy78: YYDEBUG(78, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= ':') goto yy13; + if (yych == ':') goto yy82; + goto yy13; +yy79: YYDEBUG(79, *YYCURSOR); yych = *++YYCURSOR; - if (yych != ':') goto yy13; + if (yych <= '/') goto yy13; + if (yych <= '5') goto yy83; + goto yy13; +yy80: YYDEBUG(80, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych >= '6') goto yy13; + if (yych <= '9') goto yy84; + goto yy13; +yy81: YYDEBUG(81, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych >= ':') goto yy13; + if (yych <= '4') goto yy84; + goto yy13; +yy82: YYDEBUG(82, *YYCURSOR); yych = *++YYCURSOR; - if (yych != 'Z') goto yy13; + if (yych <= '/') goto yy13; + if (yych <= '5') goto yy85; + goto yy13; yy83: YYDEBUG(83, *YYCURSOR); - ++YYCURSOR; + yych = *++YYCURSOR; + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy86; + goto yy13; +yy84: YYDEBUG(84, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == ':') goto yy87; + goto yy13; +yy85: + YYDEBUG(85, *YYCURSOR); + yych = *++YYCURSOR; + if (yych <= '/') goto yy13; + if (yych <= '9') goto yy88; + goto yy13; +yy86: + YYDEBUG(86, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'Z') goto yy89; + goto yy13; +yy87: + YYDEBUG(87, *YYCURSOR); + yych = *++YYCURSOR; + if (yych <= '/') goto yy13; + if (yych <= '5') goto yy91; + goto yy13; +yy88: + YYDEBUG(88, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == ':') goto yy79; + goto yy13; +yy89: + YYDEBUG(89, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(90, *YYCURSOR); #line 220 "ext/date/lib/parse_iso_intervals.re" { timelib_time *current; @@ -832,54 +917,15 @@ TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 836 "" -yy85: - YYDEBUG(85, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych <= '0') goto yy86; - if (yych <= '2') goto yy87; - if (yych <= '3') goto yy88; - goto yy13; -yy86: - YYDEBUG(86, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '0') goto yy13; - if (yych <= '9') goto yy89; - goto yy13; -yy87: - YYDEBUG(87, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych <= '9') goto yy89; - goto yy13; -yy88: - YYDEBUG(88, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= '2') goto yy13; -yy89: - YYDEBUG(89, *YYCURSOR); - yych = *++YYCURSOR; - if (yych != 'T') goto yy13; - YYDEBUG(90, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych <= '1') goto yy91; - if (yych <= '2') goto yy92; - goto yy13; +#line 921 "" yy91: YYDEBUG(91, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; - if (yych <= '9') goto yy93; - goto yy13; -yy92: + if (yych >= ':') goto yy13; YYDEBUG(92, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= '5') goto yy13; -yy93: + if (yych != ':') goto yy13; YYDEBUG(93, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '/') goto yy13; @@ -889,38 +935,28 @@ if (yych <= '/') goto yy13; if (yych >= ':') goto yy13; YYDEBUG(95, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= '6') goto yy13; - YYDEBUG(96, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '/') goto yy13; - if (yych >= ':') goto yy13; - YYDEBUG(97, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'Z') goto yy83; - goto yy13; -yy98: - YYDEBUG(98, *YYCURSOR); ++YYCURSOR; - if (YYLIMIT <= YYCURSOR) YYFILL(1); - yych = *YYCURSOR; - YYDEBUG(99, *YYCURSOR); - if (yych <= '/') goto yy100; - if (yych <= '9') goto yy98; -yy100: - YYDEBUG(100, *YYCURSOR); -#line 209 "ext/date/lib/parse_iso_intervals.re" + YYDEBUG(96, *YYCURSOR); +#line 286 "ext/date/lib/parse_iso_intervals.re" { - DEBUG_OUTPUT("recurrences"); + DEBUG_OUTPUT("combinedrep"); TIMELIB_INIT; + s->period->y = timelib_get_unsigned_nr(&ptr, 4); ptr++; - s->recurrences = timelib_get_unsigned_nr(&ptr, 9); + s->period->m = timelib_get_unsigned_nr(&ptr, 2); + ptr++; + s->period->d = timelib_get_unsigned_nr(&ptr, 2); + ptr++; + s->period->h = timelib_get_unsigned_nr(&ptr, 2); + ptr++; + s->period->i = timelib_get_unsigned_nr(&ptr, 2); + ptr++; + s->period->s = timelib_get_unsigned_nr(&ptr, 2); + s->have_period = 1; TIMELIB_DEINIT; - s->have_recurrences = 1; return TIMELIB_PERIOD; } -#line 924 "" +#line 960 "" } #line 321 "ext/date/lib/parse_iso_intervals.re" @@ -931,6 +967,7 @@ #define YYMAXFILL 20 + void timelib_strtointerval(const char *s, size_t len, timelib_time **begin, timelib_time **end, timelib_rel_time **period, int *recurrences, diff -Nru php8.2-8.2.24/ext/date/lib/timelib.h php8.2-8.2.26/ext/date/lib/timelib.h --- php8.2-8.2.24/ext/date/lib/timelib.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/date/lib/timelib.h 2024-11-19 17:11:09.000000000 +0000 @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2023 Derick Rethans + * Copyright (c) 2015-2024 Derick Rethans * Copyright (c) 2018,2021 MongoDB, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -30,9 +30,9 @@ # include "timelib_config.h" #endif -#define TIMELIB_VERSION 202210 -#define TIMELIB_EXTENDED_VERSION 20221001 -#define TIMELIB_ASCII_VERSION "2022.10" +#define TIMELIB_VERSION 202212 +#define TIMELIB_EXTENDED_VERSION 20221201 +#define TIMELIB_ASCII_VERSION "2022.12" #include #include diff -Nru php8.2-8.2.24/ext/date/lib/timelib_private.h php8.2-8.2.26/ext/date/lib/timelib_private.h --- php8.2-8.2.24/ext/date/lib/timelib_private.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/date/lib/timelib_private.h 2024-11-19 17:11:09.000000000 +0000 @@ -126,6 +126,15 @@ # define TIMELIB_BREAK_INTENTIONALLY_MISSING #endif +#if defined(__has_builtin) +# if __has_builtin(__builtin_saddll_overflow) +# define TIMELIB_HAVE_BUILTIN_SADDLL_OVERFLOW 1 +# endif +#endif + +#ifndef TIMELIB_HAVE_BUILTIN_SADDLL_OVERFLOW +# define TIMELIB_HAVE_BUILTIN_SADDLL_OVERFLOW 0 +#endif struct _ttinfo { int32_t offset; diff -Nru php8.2-8.2.24/ext/date/php_date.c php8.2-8.2.26/ext/date/php_date.c --- php8.2-8.2.24/ext/date/php_date.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/date/php_date.c 2024-11-19 17:11:09.000000000 +0000 @@ -687,8 +687,11 @@ (offset->offset < 0) ? '-' : '+', abs(offset->offset / 3600), abs((offset->offset % 3600) / 60)); - } else { + } else if (t->zone_type == TIMELIB_ZONETYPE_ID) { offset = timelib_get_time_zone_info(t->sse, t->tz_info); + } else { + /* Shouldn't happen, but code defensively */ + offset = timelib_time_offset_ctor(); } } @@ -2304,7 +2307,7 @@ common = zend_std_get_properties(zobj); - ZEND_HASH_MAP_FOREACH_STR_KEY_VAL_IND(common, name, prop) { + ZEND_HASH_FOREACH_STR_KEY_VAL_IND(common, name, prop) { if (zend_hash_add(myht, name, prop) != NULL) { Z_TRY_ADDREF_P(prop); } @@ -2418,6 +2421,9 @@ new_dst = tzobj->tzi.z.dst; new_abbr = timelib_strdup(tzobj->tzi.z.abbr); break; + default: + zend_throw_error(NULL, "The DateTimeZone object has not been correctly initialized by its constructor"); + return 0; } type = tzobj->type; } else if (dateobj->time->tz_info) { @@ -2834,7 +2840,7 @@ zend_string *prop_name; zval *prop_val; - ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) { + ZEND_HASH_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) { if (!prop_name || (Z_TYPE_P(prop_val) == IS_REFERENCE) || date_time_is_internal_property(prop_name)) { continue; } @@ -3816,7 +3822,6 @@ tzobj = Z_PHPTIMEZONE_P(return_value); if (!php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht)) { zend_throw_error(NULL, "Timezone initialization failed"); - zval_ptr_dtor(return_value); RETURN_THROWS(); } } @@ -3878,7 +3883,7 @@ zend_string *prop_name; zval *prop_val; - ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) { + ZEND_HASH_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) { if (!prop_name || (Z_TYPE_P(prop_val) == IS_REFERENCE) || date_timezone_is_internal_property(prop_name)) { continue; } @@ -4507,7 +4512,7 @@ zend_string *prop_name; zval *prop_val; - ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) { + ZEND_HASH_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) { if (!prop_name || (Z_TYPE_P(prop_val) == IS_REFERENCE) || date_interval_is_internal_property(prop_name)) { continue; } @@ -5106,6 +5111,10 @@ } altitude = 90 - zenith; + if (!zend_finite(latitude) || !zend_finite(longitude)) { + RETURN_FALSE; + } + /* Initialize time struct */ tzi = get_timezone_info(); if (!tzi) { @@ -5135,6 +5144,9 @@ if (N > 24 || N < 0) { N -= floor(N / 24) * 24; } + if (N > 24 || N < 0) { + RETURN_FALSE; + } switch (retformat) { case SUNFUNCS_RET_STRING: @@ -5180,6 +5192,15 @@ Z_PARAM_DOUBLE(longitude) ZEND_PARSE_PARAMETERS_END(); + if (!zend_finite(latitude)) { + zend_argument_value_error(2, "must be finite"); + RETURN_THROWS(); + } + if (!zend_finite(longitude)) { + zend_argument_value_error(3, "must be finite"); + RETURN_THROWS(); + } + /* Initialize time struct */ tzi = get_timezone_info(); if (!tzi) { @@ -5496,7 +5517,7 @@ zend_string *prop_name; zval *prop_val; - ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) { + ZEND_HASH_FOREACH_STR_KEY_VAL(myht, prop_name, prop_val) { if (!prop_name || (Z_TYPE_P(prop_val) == IS_REFERENCE) || date_period_is_internal_property(prop_name)) { continue; } diff -Nru php8.2-8.2.24/ext/date/tests/bug-gh15582.phpt php8.2-8.2.26/ext/date/tests/bug-gh15582.phpt --- php8.2-8.2.24/ext/date/tests/bug-gh15582.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/date/tests/bug-gh15582.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,21 @@ +--TEST-- +Bug GH-15582: Crash when not calling parent constructor of DateTimeZone +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +Error: The DateTimeZone object has not been correctly initialized by its constructor diff -Nru php8.2-8.2.24/ext/date/tests/bug-gh16037.phpt php8.2-8.2.26/ext/date/tests/bug-gh16037.phpt --- php8.2-8.2.24/ext/date/tests/bug-gh16037.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/date/tests/bug-gh16037.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,9 @@ +--TEST-- +Test for bug GH-16037: Assertion failure in ext/date/php_date.c +--FILE-- +__unserialize([[]]); +echo gettype($di); +?> +--EXPECT-- +NULL diff -Nru php8.2-8.2.24/ext/date/tests/bug40861.phpt php8.2-8.2.26/ext/date/tests/bug40861.phpt --- php8.2-8.2.24/ext/date/tests/bug40861.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/date/tests/bug40861.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -28,6 +28,6 @@ ?> --EXPECT-- 2000-01-01 13:00:00 -2000-01-01 13:00:00 2000-01-01 11:00:00 2000-01-01 13:00:00 +2000-01-01 13:00:00 diff -Nru php8.2-8.2.24/ext/date/tests/gh14732.phpt php8.2-8.2.26/ext/date/tests/gh14732.phpt --- php8.2-8.2.24/ext/date/tests/gh14732.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/date/tests/gh14732.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,38 @@ +--TEST-- +GH-14732 (date_sun_info() fails for non-finite values) +--FILE-- +getMessage(), "\n"; +} +try { + date_sun_info(1, -INF, 1); +} catch (ValueError $ex) { + echo $ex->getMessage(), "\n"; +} +try { + date_sun_info(1, 1, NAN); +} catch (ValueError $ex) { + echo $ex->getMessage(), "\n"; +} +try { + date_sun_info(1, 1, INF); +} catch (ValueError $ex) { + echo $ex->getMessage(), "\n"; +} +var_dump(date_sunset(1, SUNFUNCS_RET_STRING, NAN, 1)); +var_dump(date_sunrise(1, SUNFUNCS_RET_STRING, 1, NAN)); +?> +--EXPECTF-- +date_sun_info(): Argument #2 ($latitude) must be finite +date_sun_info(): Argument #2 ($latitude) must be finite +date_sun_info(): Argument #3 ($longitude) must be finite +date_sun_info(): Argument #3 ($longitude) must be finite + +Deprecated: Function date_sunset() is deprecated in %s on line %d +bool(false) + +Deprecated: Function date_sunrise() is deprecated in %s on line %d +bool(false) diff -Nru php8.2-8.2.24/ext/date/tests/gh16454.phpt php8.2-8.2.26/ext/date/tests/gh16454.phpt --- php8.2-8.2.24/ext/date/tests/gh16454.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/date/tests/gh16454.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,21 @@ +--TEST-- +GH-16454 (Unhandled INF in date_sunset() with tiny $utcOffset) +--FILE-- + +--EXPECTF-- +Deprecated: Function date_sunrise() is deprecated in %s on line %d +bool(false) + +Deprecated: Function date_sunrise() is deprecated in %s on line %d +bool(false) + +Deprecated: Function date_sunset() is deprecated in %s on line %d +bool(false) + +Deprecated: Function date_sunset() is deprecated in %s on line %d +bool(false) diff -Nru php8.2-8.2.24/ext/dba/dba.c php8.2-8.2.26/ext/dba/dba.c --- php8.2-8.2.24/ext/dba/dba.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/dba/dba.c 2024-11-19 17:11:09.000000000 +0000 @@ -772,11 +772,18 @@ info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path); if (info->lock.fp) { if (is_db_lock) { - /* replace the path info with the real path of the opened file */ - pefree(info->path, persistent); - info->path = pestrndup(ZSTR_VAL(opened_path), ZSTR_LEN(opened_path), persistent); + if (opened_path) { + /* replace the path info with the real path of the opened file */ + pefree(info->path, persistent); + info->path = pestrndup(ZSTR_VAL(opened_path), ZSTR_LEN(opened_path), persistent); + } else { + error = "Unable to determine path for locking"; + } } + } + if (opened_path) { zend_string_release_ex(opened_path, 0); + opened_path = NULL; } } if (!is_db_lock) { @@ -788,10 +795,10 @@ FREE_PERSISTENT_RESOURCE_KEY(); RETURN_FALSE; } - if (!php_stream_supports_lock(info->lock.fp)) { + if (!error && !php_stream_supports_lock(info->lock.fp)) { error = "Stream does not support locking"; } - if (php_stream_lock(info->lock.fp, lock_mode)) { + if (!error && php_stream_lock(info->lock.fp, lock_mode)) { error = "Unable to establish lock"; /* force failure exit */ } } diff -Nru php8.2-8.2.24/ext/dba/tests/gh16390.phpt php8.2-8.2.26/ext/dba/tests/gh16390.phpt --- php8.2-8.2.24/ext/dba/tests/gh16390.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/dba/tests/gh16390.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,11 @@ +--TEST-- +GH-16390 (dba_open() can segfault for "pathless" streams) +--EXTENSIONS-- +dba +--FILE-- + +--EXPECTF-- +Warning: dba_open(): Driver initialization failed for handler: inifile: Unable to determine path for locking in %s on line %d diff -Nru php8.2-8.2.24/ext/dom/node.c php8.2-8.2.26/ext/dom/node.c --- php8.2-8.2.24/ext/dom/node.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/dom/node.c 2024-11-19 17:11:09.000000000 +0000 @@ -843,13 +843,57 @@ } /* }}} */ +static bool dom_node_check_legacy_insertion_validity(xmlNodePtr parentp, xmlNodePtr child, bool stricterror) +{ + if (dom_node_is_read_only(parentp) == SUCCESS || + (child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) { + php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror); + return false; + } + + if (dom_hierarchy(parentp, child) == FAILURE) { + php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror); + return false; + } + + if (child->doc != parentp->doc && child->doc != NULL) { + php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror); + return false; + } + + if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) { + /* TODO Drop Warning? */ + php_error_docref(NULL, E_WARNING, "Document Fragment is empty"); + return false; + } + + /* In old DOM only text nodes and entity nodes can be added as children to attributes. */ + if (parentp->type == XML_ATTRIBUTE_NODE && child->type != XML_TEXT_NODE && child->type != XML_ENTITY_REF_NODE) { + php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror); + return false; + } + /* Attributes must be in elements. */ + if (child->type == XML_ATTRIBUTE_NODE && parentp->type != XML_ELEMENT_NODE) { + php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror); + return false; + } + + /* Documents can never be a child. */ + if (child->type == XML_DOCUMENT_NODE || child->type == XML_HTML_DOCUMENT_NODE) { + php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror); + return false; + } + + return true; +} + /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-952280727 Since: */ PHP_METHOD(DOMNode, insertBefore) { zval *id, *node, *ref = NULL; - xmlNodePtr child, new_child, parentp, refp; + xmlNodePtr child, new_child, parentp, refp = NULL; dom_object *intern, *childobj, *refpobj; int ret, stricterror; @@ -870,26 +914,17 @@ stricterror = dom_get_strict_error(intern->document); - if (dom_node_is_read_only(parentp) == SUCCESS || - (child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) { - php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror); - RETURN_FALSE; - } - - if (dom_hierarchy(parentp, child) == FAILURE) { - php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror); + if (!dom_node_check_legacy_insertion_validity(parentp, child, stricterror)) { RETURN_FALSE; } - if (child->doc != parentp->doc && child->doc != NULL) { - php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror); - RETURN_FALSE; - } - - if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) { - /* TODO Drop Warning? */ - php_error_docref(NULL, E_WARNING, "Document Fragment is empty"); - RETURN_FALSE; + /* Fetch and perform sanity checks before modifying reference pointers. */ + if (ref != NULL) { + DOM_GET_OBJ(refp, ref, xmlNodePtr, refpobj); + if (refp->parent != parentp) { + php_dom_throw_error(NOT_FOUND_ERR, stricterror); + RETURN_FALSE; + } } if (child->doc == NULL && parentp->doc != NULL) { @@ -898,12 +933,6 @@ } if (ref != NULL) { - DOM_GET_OBJ(refp, ref, xmlNodePtr, refpobj); - if (refp->parent != parentp) { - php_dom_throw_error(NOT_FOUND_ERR, stricterror); - RETURN_FALSE; - } - if (child->parent != NULL) { xmlUnlinkNode(child); } @@ -1067,6 +1096,13 @@ RETURN_FALSE; } + /* This is already disallowed by libxml, but we should check it here to avoid + * breaking assumptions and assertions. */ + if ((oldchild->type == XML_ATTRIBUTE_NODE) != (newchild->type == XML_ATTRIBUTE_NODE)) { + php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror); + RETURN_FALSE; + } + if (oldchild->parent != nodep) { php_dom_throw_error(NOT_FOUND_ERR, stricterror); RETURN_FALSE; @@ -1170,25 +1206,7 @@ stricterror = dom_get_strict_error(intern->document); - if (dom_node_is_read_only(nodep) == SUCCESS || - (child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) { - php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror); - RETURN_FALSE; - } - - if (dom_hierarchy(nodep, child) == FAILURE) { - php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror); - RETURN_FALSE; - } - - if (!(child->doc == NULL || child->doc == nodep->doc)) { - php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror); - RETURN_FALSE; - } - - if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) { - /* TODO Drop Warning? */ - php_error_docref(NULL, E_WARNING, "Document Fragment is empty"); + if (!dom_node_check_legacy_insertion_validity(nodep, child, stricterror)) { RETURN_FALSE; } diff -Nru php8.2-8.2.24/ext/dom/parentnode.c php8.2-8.2.26/ext/dom/parentnode.c --- php8.2-8.2.24/ext/dom/parentnode.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/dom/parentnode.c 2024-11-19 17:11:09.000000000 +0000 @@ -272,6 +272,11 @@ if (instanceof_function(ce, dom_node_class_entry)) { xmlNodePtr node = dom_object_get_node(Z_DOMOBJ_P(nodes + i)); + if (!node) { + php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); + return FAILURE; + } + if (node->doc != documentNode) { php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(document)); return FAILURE; diff -Nru php8.2-8.2.24/ext/dom/php_dom.stub.php php8.2-8.2.26/ext/dom/php_dom.stub.php --- php8.2-8.2.24/ext/dom/php_dom.stub.php 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/dom/php_dom.stub.php 2024-11-19 17:11:09.000000000 +0000 @@ -933,4 +933,4 @@ } #endif -function dom_import_simplexml(object $node): DOMElement {} +function dom_import_simplexml(object $node): DOMAttr|DOMElement {} diff -Nru php8.2-8.2.24/ext/dom/php_dom_arginfo.h php8.2-8.2.26/ext/dom/php_dom_arginfo.h --- php8.2-8.2.24/ext/dom/php_dom_arginfo.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/dom/php_dom_arginfo.h 2024-11-19 17:11:09.000000000 +0000 @@ -1,7 +1,7 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7d4dc9e1a3736f2ac9082c32bf5260dfa58b1aa0 */ + * Stub hash: 6d1c16a61f23de241f72f3559a9987d2f4a9c6fd */ -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 0) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_dom_import_simplexml, 0, 1, DOMAttr|DOMElement, 0) ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0) ZEND_END_ARG_INFO() diff -Nru php8.2-8.2.24/ext/dom/tests/gh16039.phpt php8.2-8.2.26/ext/dom/tests/gh16039.phpt --- php8.2-8.2.24/ext/dom/tests/gh16039.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/dom/tests/gh16039.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,31 @@ +--TEST-- +GH-16039 (Segmentation fault (access null pointer) in ext/dom/parentnode/tree.c) +--EXTENSIONS-- +dom +--FILE-- +appendChild($dom->createElement('root')); +try { + $element->prepend('x', new DOMEntity); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} +echo $dom->saveXML(); +$dom->strictErrorChecking = false; // Should not have influence +try { + $element->prepend('x', new DOMEntity); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} +echo $dom->saveXML(); + +?> +--EXPECT-- +Invalid State Error + + +Invalid State Error + + diff -Nru php8.2-8.2.24/ext/dom/tests/gh16151.phpt php8.2-8.2.26/ext/dom/tests/gh16151.phpt --- php8.2-8.2.24/ext/dom/tests/gh16151.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/dom/tests/gh16151.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,35 @@ +--TEST-- +GH-16151 (Assertion failure in ext/dom/parentnode/tree.c) +--EXTENSIONS-- +dom +--FILE-- +appendChild($element); +$element->setAttributeNodeNS($attr); + +try { + $attr->insertBefore(new DOMComment("h")); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} +try { + $attr->appendChild(new DOMComment("h")); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} + +$attr->insertBefore($doc->createEntityReference('amp')); +$attr->appendChild($doc->createEntityReference('amp')); + +echo $doc->saveXML(); + +?> +--EXPECT-- +Hierarchy Request Error +Hierarchy Request Error + +W diff -Nru php8.2-8.2.24/ext/dom/tests/gh16316.phpt php8.2-8.2.26/ext/dom/tests/gh16316.phpt --- php8.2-8.2.24/ext/dom/tests/gh16316.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/dom/tests/gh16316.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,32 @@ +--TEST-- +GH-16316 (DOMXPath breaks when not initialized properly) +--EXTENSIONS-- +dom +--FILE-- +getMessage(), "\n"; +} + +try { + var_dump($demo->document); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +object(Demo)#1 (1) { + ["registerNodeNamespaces"]=> + bool(true) +} +Invalid State Error +Invalid State Error diff -Nru php8.2-8.2.24/ext/dom/tests/gh16473.phpt php8.2-8.2.26/ext/dom/tests/gh16473.phpt --- php8.2-8.2.24/ext/dom/tests/gh16473.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/dom/tests/gh16473.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,13 @@ +--TEST-- +GH-16473 (dom_import_simplexml stub is wrong) +--EXTENSIONS-- +dom +simplexml +--FILE-- +'); +$attr = $root->attributes('urn:x'); +var_dump(dom_import_simplexml($attr)->textContent); +?> +--EXPECT-- +string(3) "foo" diff -Nru php8.2-8.2.24/ext/dom/tests/gh16533.phpt php8.2-8.2.26/ext/dom/tests/gh16533.phpt --- php8.2-8.2.24/ext/dom/tests/gh16533.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/dom/tests/gh16533.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,20 @@ +--TEST-- +GH-16533 (Segfault when adding attribute to parent that is not an element) +--EXTENSIONS-- +dom +--FILE-- +appendChild($doc->createAttribute('foo')); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} + +echo $doc->saveXML(); + +?> +--EXPECT-- +Hierarchy Request Error + diff -Nru php8.2-8.2.24/ext/dom/tests/gh16535.phpt php8.2-8.2.26/ext/dom/tests/gh16535.phpt --- php8.2-8.2.24/ext/dom/tests/gh16535.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/dom/tests/gh16535.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,25 @@ +--TEST-- +GH-16535 (UAF when using document as a child) +--EXTENSIONS-- +dom +--FILE-- +loadHTML("t"); +$v4 = $v2->createElement('foo'); +try { + $v4->appendChild($v2); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} +$v2->loadHTML("oU"); +echo $v2->saveXML(); + +?> +--EXPECT-- +Hierarchy Request Error + + +

oU

diff -Nru php8.2-8.2.24/ext/dom/tests/gh16593.phpt php8.2-8.2.26/ext/dom/tests/gh16593.phpt --- php8.2-8.2.24/ext/dom/tests/gh16593.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/dom/tests/gh16593.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,22 @@ +--TEST-- +GH-16593 (Assertion failure in DOM->replaceChild) +--EXTENSIONS-- +dom +--FILE-- +appendChild($doc->createElement('root')); +$child = $root->appendChild($doc->createElement('child')); +try { + $root->replaceChild($doc->createAttribute('foo'), $child); +} catch (DOMException $e) { + echo $e->getMessage(), "\n"; +} +echo $doc->saveXML(); + +?> +--EXPECT-- +Hierarchy Request Error + + diff -Nru php8.2-8.2.24/ext/dom/xml_common.h php8.2-8.2.26/ext/dom/xml_common.h --- php8.2-8.2.24/ext/dom/xml_common.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/dom/xml_common.h 2024-11-19 17:11:09.000000000 +0000 @@ -60,21 +60,23 @@ (const xmlChar *) "http://www.w3.org/2000/xmlns/" #define NODE_GET_OBJ(__ptr, __id, __prtype, __intern) { \ - __intern = Z_LIBXML_NODE_P(__id); \ + zval *__zv = (__id); \ + __intern = Z_LIBXML_NODE_P(__zv); \ if (__intern->node == NULL || !(__ptr = (__prtype)__intern->node->node)) { \ - php_error_docref(NULL, E_WARNING, "Couldn't fetch %s", \ - ZSTR_VAL(__intern->std.ce->name));\ - RETURN_NULL();\ + php_error_docref(NULL, E_WARNING, "Couldn't fetch %s", \ + ZSTR_VAL(Z_OBJCE_P(__zv)->name));\ + RETURN_NULL();\ } \ } #define DOC_GET_OBJ(__ptr, __id, __prtype, __intern) { \ - __intern = Z_LIBXML_NODE_P(__id); \ + zval *__zv = (__id); \ + __intern = Z_LIBXML_NODE_P(__zv); \ if (__intern->document != NULL) { \ if (!(__ptr = (__prtype)__intern->document->ptr)) { \ - php_error_docref(NULL, E_WARNING, "Couldn't fetch %s", __intern->std.ce->name);\ - RETURN_NULL();\ - } \ + php_error_docref(NULL, E_WARNING, "Couldn't fetch %s", ZSTR_VAL(Z_OBJCE_P(__zv)->name));\ + RETURN_NULL();\ + } \ } \ } diff -Nru php8.2-8.2.24/ext/dom/xpath.c php8.2-8.2.26/ext/dom/xpath.c --- php8.2-8.2.24/ext/dom/xpath.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/dom/xpath.c 2024-11-19 17:11:09.000000000 +0000 @@ -264,6 +264,11 @@ docp = (xmlDocPtr) ctx->doc; } + if (UNEXPECTED(!docp)) { + php_dom_throw_error(INVALID_STATE_ERR, /* strict */ true); + return FAILURE; + } + php_dom_create_object((xmlNodePtr) docp, retval, obj); return SUCCESS; } diff -Nru php8.2-8.2.24/ext/exif/exif.c php8.2-8.2.26/ext/exif/exif.c --- php8.2-8.2.24/ext/exif/exif.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/exif/exif.c 2024-11-19 17:11:09.000000000 +0000 @@ -4419,7 +4419,7 @@ ImageInfo->FileName = NULL; if (php_stream_is(ImageInfo->infile, PHP_STREAM_IS_STDIO)) { - if (VCWD_STAT(stream->orig_path, &st) >= 0) { + if (stream->orig_path && VCWD_STAT(stream->orig_path, &st) >= 0) { zend_string *base; if ((st.st_mode & S_IFMT) != S_IFREG) { exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Not a file"); diff -Nru php8.2-8.2.24/ext/exif/tests/gh16409.phpt php8.2-8.2.26/ext/exif/tests/gh16409.phpt --- php8.2-8.2.24/ext/exif/tests/gh16409.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/exif/tests/gh16409.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,12 @@ +--TEST-- +GH-16409 (Segfault in exif_thumbnail when not dealing with a real file) +--EXTENSIONS-- +exif +--FILE-- + +--EXPECTF-- +Warning: exif_thumbnail(): File too small (0) in %s on line %d +bool(false)%A diff -Nru php8.2-8.2.24/ext/ffi/ffi.c php8.2-8.2.26/ext/ffi/ffi.c --- php8.2-8.2.24/ext/ffi/ffi.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/ffi/ffi.c 2024-11-19 17:11:09.000000000 +0000 @@ -2922,6 +2922,12 @@ } /* }}} */ +static int zend_fake_compare_objects(zval *o1, zval *o2) +{ + zend_throw_error(zend_ffi_exception_ce, "Cannot compare FFI objects"); + return ZEND_UNCOMPARABLE; +} + static zend_never_inline int zend_ffi_disabled(void) /* {{{ */ { zend_throw_error(zend_ffi_exception_ce, "FFI API is restricted by \"ffi.enable\" configuration directive"); @@ -5367,7 +5373,7 @@ zend_ffi_handlers.has_dimension = zend_fake_has_dimension; zend_ffi_handlers.unset_dimension = zend_fake_unset_dimension; zend_ffi_handlers.get_method = zend_ffi_get_func; - zend_ffi_handlers.compare = NULL; + zend_ffi_handlers.compare = zend_fake_compare_objects; zend_ffi_handlers.cast_object = zend_fake_cast_object; zend_ffi_handlers.get_debug_info = NULL; zend_ffi_handlers.get_closure = NULL; diff -Nru php8.2-8.2.24/ext/ffi/tests/gh16397.phpt php8.2-8.2.26/ext/ffi/tests/gh16397.phpt --- php8.2-8.2.24/ext/ffi/tests/gh16397.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/ffi/tests/gh16397.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,15 @@ +--TEST-- +GH-16397 (Segmentation fault when comparing FFI object) +--EXTENSIONS-- +ffi +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +Cannot compare FFI objects diff -Nru php8.2-8.2.24/ext/filter/logical_filters.c php8.2-8.2.26/ext/filter/logical_filters.c --- php8.2-8.2.24/ext/filter/logical_filters.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/filter/logical_filters.c 2024-11-19 17:11:09.000000000 +0000 @@ -542,7 +542,7 @@ /* Reset label length counter */ i = 1; } else { - if (i > 63 || (hostname && *s != '-' && !isalnum((int)*(unsigned char *)s))) { + if (i > 63 || (hostname && (*s != '-' || *(s + 1) == '\0') && !isalnum((int)*(unsigned char *)s))) { return 0; } diff -Nru php8.2-8.2.24/ext/filter/tests/gh16523.phpt php8.2-8.2.26/ext/filter/tests/gh16523.phpt --- php8.2-8.2.24/ext/filter/tests/gh16523.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/filter/tests/gh16523.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,20 @@ +--TEST-- +GH-16523 (FILTER_FLAG_HOSTNAME accepts ending hyphen) +--EXTENSIONS-- +filter +--FILE-- + +--EXPECT-- +bool(false) +bool(false) +bool(false) diff -Nru php8.2-8.2.24/ext/gd/gd.c php8.2-8.2.26/ext/gd/gd.c --- php8.2-8.2.24/ext/gd/gd.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/gd/gd.c 2024-11-19 17:11:09.000000000 +0000 @@ -1195,6 +1195,11 @@ RETURN_THROWS(); } + if (degrees < (double)(INT_MIN / 100) || degrees > (double)(INT_MAX / 100)) { + zend_argument_value_error(2, "must be between %d and %d", (INT_MIN / 100), (INT_MAX / 100)); + RETURN_THROWS(); + } + im_src = php_gd_libgdimageptr_from_zval_p(SIM); im_dst = gdImageRotateInterpolated(im_src, (const float)degrees, color); @@ -3682,13 +3687,25 @@ if ((zval_affine_elem = zend_hash_index_find(Z_ARRVAL_P(z_affine), i)) != NULL) { switch (Z_TYPE_P(zval_affine_elem)) { case IS_LONG: - affine[i] = Z_LVAL_P(zval_affine_elem); + affine[i] = Z_LVAL_P(zval_affine_elem); + if (affine[i] < INT_MIN || affine[i] > INT_MAX) { + zend_argument_value_error(2, "element %i must be between %d and %d", i, INT_MIN, INT_MAX); + RETURN_THROWS(); + } break; case IS_DOUBLE: affine[i] = Z_DVAL_P(zval_affine_elem); + if (affine[i] < INT_MIN || affine[i] > INT_MAX) { + zend_argument_value_error(2, "element %i must be between %d and %d", i, INT_MIN, INT_MAX); + RETURN_THROWS(); + } break; case IS_STRING: affine[i] = zval_get_double(zval_affine_elem); + if (affine[i] < INT_MIN || affine[i] > INT_MAX) { + zend_argument_value_error(2, "element %i must be between %d and %d", i, INT_MIN, INT_MAX); + RETURN_THROWS(); + } break; default: zend_argument_type_error(3, "contains invalid type for element %i", i); diff -Nru php8.2-8.2.24/ext/gd/libgd/gd_avif.c php8.2-8.2.26/ext/gd/libgd/gd_avif.c --- php8.2-8.2.24/ext/gd/libgd/gd_avif.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/gd/libgd/gd_avif.c 2024-11-19 17:11:09.000000000 +0000 @@ -393,7 +393,13 @@ // (While AVIF image pixel depth can be 8, 10, or 12 bits, GD truecolor images are 8-bit.) avifRGBImageSetDefaults(&rgb, decoder->image); rgb.depth = 8; +#if AVIF_VERSION >= 1000000 + result = avifRGBImageAllocatePixels(&rgb); + if (isAvifError(result, "Allocating RGB pixels failed")) + goto cleanup; +#else avifRGBImageAllocatePixels(&rgb); +#endif result = avifImageYUVToRGB(decoder->image, &rgb); if (isAvifError(result, "Conversion from YUV to RGB failed")) @@ -522,14 +528,25 @@ // Note that MATRIX_COEFFICIENTS_IDENTITY enables lossless conversion from RGB to YUV. avifImage *avifIm = avifImageCreate(gdImageSX(im), gdImageSY(im), 8, subsampling); - +#if AVIF_VERSION >= 1000000 + if (avifIm == NULL) { + gd_error("avif error - Creating image failed\n"); + goto cleanup; + } +#endif avifIm->colorPrimaries = AVIF_COLOR_PRIMARIES_BT709; avifIm->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_SRGB; avifIm->matrixCoefficients = lossless ? AVIF_MATRIX_COEFFICIENTS_IDENTITY : AVIF_MATRIX_COEFFICIENTS_BT709; avifRGBImageSetDefaults(&rgb, avifIm); // this allocates memory, and sets rgb.rowBytes and rgb.pixels. +#if AVIF_VERSION >= 1000000 + result = avifRGBImageAllocatePixels(&rgb); + if (isAvifError(result, "Allocating RGB pixels failed")) + goto cleanup; +#else avifRGBImageAllocatePixels(&rgb); +#endif // Parse RGB data from the GD image, and copy it into the AVIF RGB image. // Convert 7-bit GD alpha channel values to 8-bit AVIF values. @@ -555,6 +572,12 @@ // Encode the image in AVIF format. encoder = avifEncoderCreate(); +#if AVIF_VERSION >= 1000000 + if (encoder == NULL) { + gd_error("avif error - Creating encoder failed\n"); + goto cleanup; + } +#endif int quantizerQuality = quality == QUALITY_DEFAULT ? QUANTIZER_DEFAULT : quality2Quantizer(quality); diff -Nru php8.2-8.2.24/ext/gd/libgd/gd_interpolation.c php8.2-8.2.26/ext/gd/libgd/gd_interpolation.c --- php8.2-8.2.24/ext/gd/libgd/gd_interpolation.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/gd/libgd/gd_interpolation.c 2024-11-19 17:11:09.000000000 +0000 @@ -929,6 +929,32 @@ return res; } +/* Convert a double to an unsigned char, rounding to the nearest + * integer and clamping the result between 0 and max. The absolute + * value of clr must be less than the maximum value of an unsigned + * short. */ +static inline unsigned char +uchar_clamp(double clr, unsigned char max) { + unsigned short result; + + //assert(fabs(clr) <= SHRT_MAX); + + /* Casting a negative float to an unsigned short is undefined. + * However, casting a float to a signed truncates toward zero and + * casting a negative signed value to an unsigned of the same size + * results in a bit-identical value (assuming twos-complement + * arithmetic). This is what we want: all legal negative values + * for clr will be greater than 255. */ + + /* Convert and clamp. */ + result = (unsigned short)(short)(clr + 0.5); + if (result > max) { + result = (clr < 0) ? 0 : max; + }/* if */ + + return result; +}/* uchar_clamp*/ + static inline void _gdScaleRow(gdImagePtr pSrc, unsigned int src_width, gdImagePtr dst, unsigned int dst_width, unsigned int row, LineContribType *contrib) { int *p_src_row = pSrc->tpixels[row]; @@ -936,20 +962,22 @@ unsigned int x; for (x = 0; x < dst_width; x++) { - register unsigned char r = 0, g = 0, b = 0, a = 0; + double r = 0, g = 0, b = 0, a = 0; const int left = contrib->ContribRow[x].Left; const int right = contrib->ContribRow[x].Right; - int i; + int i; - /* Accumulate each channel */ - for (i = left; i <= right; i++) { - const int left_channel = i - left; - r += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetRed(p_src_row[i]))); - g += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetGreen(p_src_row[i]))); - b += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetBlue(p_src_row[i]))); - a += (unsigned char)(contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetAlpha(p_src_row[i]))); - } - p_dst_row[x] = gdTrueColorAlpha(r, g, b, a); + /* Accumulate each channel */ + for (i = left; i <= right; i++) { + const int left_channel = i - left; + r += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetRed(p_src_row[i])); + g += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetGreen(p_src_row[i])); + b += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetBlue(p_src_row[i])); + a += contrib->ContribRow[x].Weights[left_channel] * (double)(gdTrueColorGetAlpha(p_src_row[i])); + } + p_dst_row[x] = gdTrueColorAlpha(uchar_clamp(r, 0xFF), uchar_clamp(g, 0xFF), + uchar_clamp(b, 0xFF), + uchar_clamp(a, 0x7F)); /* alpha is 0..127 */ } } @@ -982,7 +1010,7 @@ { unsigned int y; for (y = 0; y < dst_height; y++) { - register unsigned char r = 0, g = 0, b = 0, a = 0; + double r = 0, g = 0, b = 0, a = 0; const int iLeft = contrib->ContribRow[y].Left; const int iRight = contrib->ContribRow[y].Right; int i; @@ -991,12 +1019,14 @@ for (i = iLeft; i <= iRight; i++) { const int pCurSrc = pSrc->tpixels[i][uCol]; const int i_iLeft = i - iLeft; - r += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetRed(pCurSrc))); - g += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetGreen(pCurSrc))); - b += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetBlue(pCurSrc))); - a += (unsigned char)(contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetAlpha(pCurSrc))); + r += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetRed(pCurSrc)); + g += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetGreen(pCurSrc)); + b += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetBlue(pCurSrc)); + a += contrib->ContribRow[y].Weights[i_iLeft] * (double)(gdTrueColorGetAlpha(pCurSrc)); } - pRes->tpixels[y][uCol] = gdTrueColorAlpha(r, g, b, a); + pRes->tpixels[y][uCol] = gdTrueColorAlpha(uchar_clamp(r, 0xFF), uchar_clamp(g, 0xFF), + uchar_clamp(b, 0xFF), + uchar_clamp(a, 0x7F)); /* alpha is 0..127 */ } } diff -Nru php8.2-8.2.24/ext/gd/libgd/wbmp.c php8.2-8.2.26/ext/gd/libgd/wbmp.c --- php8.2-8.2.24/ext/gd/libgd/wbmp.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/gd/libgd/wbmp.c 2024-11-19 17:11:09.000000000 +0000 @@ -37,7 +37,8 @@ int getmbi (int (*getin) (void *in), void *in) { - int i, mbi = 0; + unsigned int mbi = 0; + int i; do { diff -Nru php8.2-8.2.24/ext/gd/tests/gh16232.phpt php8.2-8.2.26/ext/gd/tests/gh16232.phpt --- php8.2-8.2.24/ext/gd/tests/gh16232.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gd/tests/gh16232.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,27 @@ +--TEST-- +GH-16232 (Overflow on reading wbmp content) +--EXTENSIONS-- +gd +--FILE-- + +--EXPECT-- +DONE diff -Nru php8.2-8.2.24/ext/gd/tests/gh16260.phpt php8.2-8.2.26/ext/gd/tests/gh16260.phpt --- php8.2-8.2.24/ext/gd/tests/gh16260.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gd/tests/gh16260.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,22 @@ +--TEST-- +GH-16260 (Overflow/underflow on imagerotate degrees argument) +--EXTENSIONS-- +gd +--FILE-- +getMessage() . PHP_EOL; +} + +try { + imagerotate($im, PHP_INT_MAX, 0); +} catch (\ValueError $e) { + echo $e->getMessage(); +} +--EXPECTF-- +imagerotate(): Argument #2 ($angle) must be between %s and %s +imagerotate(): Argument #2 ($angle) must be between %s and %s diff -Nru php8.2-8.2.24/ext/gd/tests/gh16322.phpt php8.2-8.2.26/ext/gd/tests/gh16322.phpt --- php8.2-8.2.24/ext/gd/tests/gh16322.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gd/tests/gh16322.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,27 @@ +--TEST-- +GH-16322 (imageaffine overflow/underflow on affine matrix) +--EXTENSIONS-- +gd +--INI-- +memory_limit=-1 +--FILE-- +getMessage() . PHP_EOL; +} +$matrix[0] = 1; +$matrix[3] = -INF; +try { + imageaffine($src, $matrix); +} catch (\ValueError $e) { + echo $e->getMessage(); +} +?> +--EXPECTF-- +imageaffine(): Argument #2 ($affine) element 0 must be between %s and %d +imageaffine(): Argument #2 ($affine) element 3 must be between %s and %d diff -Nru php8.2-8.2.24/ext/gd/tests/gh16559.phpt php8.2-8.2.26/ext/gd/tests/gh16559.phpt --- php8.2-8.2.24/ext/gd/tests/gh16559.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gd/tests/gh16559.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,15 @@ +--TEST-- +GH-16559 (UBSan abort in ext/gd/libgd/gd_interpolation.c:1007) +--EXTENSIONS-- +gd +--FILE-- + +--EXPECT-- +object(GdImage)#2 (0) { +} diff -Nru php8.2-8.2.24/ext/gmp/gmp.c php8.2-8.2.26/ext/gmp/gmp.c --- php8.2-8.2.24/ext/gmp/gmp.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/gmp.c 2024-11-19 17:11:09.000000000 +0000 @@ -334,8 +334,34 @@ } /* }}} */ -static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zval *op1, zval *op2, zend_uchar opcode) { - zend_long shift = zval_get_long(op2); +static zend_result shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zval *op1, zval *op2, zend_uchar opcode) { + zend_long shift = 0; + + if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { + if (UNEXPECTED(!IS_GMP(op2))) { + // For PHP 8.3 and up use zend_try_get_long() + switch (Z_TYPE_P(op2)) { + case IS_DOUBLE: + shift = zval_get_long(op2); + if (UNEXPECTED(EG(exception))) { + return FAILURE; + } + break; + case IS_STRING: + if (is_numeric_str_function(Z_STR_P(op2), &shift, NULL) != IS_LONG) { + goto valueof_op_failure; + } + break; + default: + goto typeof_op_failure; + } + } else { + // TODO We shouldn't cast the GMP object to int here + shift = zval_get_long(op2); + } + } else { + shift = Z_LVAL_P(op2); + } if (shift < 0) { zend_throw_error( @@ -343,16 +369,54 @@ opcode == ZEND_POW ? "Exponent" : "Shift" ); ZVAL_UNDEF(return_value); - return; + return FAILURE; } else { mpz_ptr gmpnum_op, gmpnum_result; gmp_temp_t temp; - FETCH_GMP_ZVAL(gmpnum_op, op1, temp, 1); + /* We do not use FETCH_GMP_ZVAL(...); here as we don't use convert_to_gmp() + * as we want to handle the emitted exception ourself. */ + if (UNEXPECTED(!IS_GMP(op1))) { + if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { + goto typeof_op_failure; + } + mpz_init(temp.num); + mpz_set_si(temp.num, Z_LVAL_P(op1)); + temp.is_used = 1; + gmpnum_op = temp.num; + } else { + gmpnum_op = GET_GMP_FROM_ZVAL(op1); + temp.is_used = 0; + } INIT_GMP_RETVAL(gmpnum_result); op(gmpnum_result, gmpnum_op, (gmp_ulong) shift); FREE_GMP_TEMP(temp); + return SUCCESS; + } + +typeof_op_failure: ; + /* Returning FAILURE without throwing an exception would emit the + * Unsupported operand types: GMP OP TypeOfOp2 + * However, this leads to the engine trying to interpret the GMP object as an integer + * and doing the operation that way, which is not something we want. */ + const char *op_sigil; + switch (opcode) { + case ZEND_POW: + op_sigil = "**"; + break; + case ZEND_SL: + op_sigil = "<<"; + break; + case ZEND_SR: + op_sigil = ">>"; + break; + EMPTY_SWITCH_DEFAULT_CASE(); } + zend_type_error("Unsupported operand types: %s %s %s", zend_zval_type_name(op1), op_sigil, zend_zval_type_name(op2)); + return FAILURE; +valueof_op_failure: + zend_value_error("Number is not an integer string"); + return FAILURE; } #define DO_BINARY_UI_OP_EX(op, uop, check_b_zero) \ @@ -381,18 +445,15 @@ case ZEND_MUL: DO_BINARY_UI_OP(mpz_mul); case ZEND_POW: - shift_operator_helper(mpz_pow_ui, result, op1, op2, opcode); - return SUCCESS; + return shift_operator_helper(mpz_pow_ui, result, op1, op2, opcode); case ZEND_DIV: DO_BINARY_UI_OP_EX(mpz_tdiv_q, gmp_mpz_tdiv_q_ui, 1); case ZEND_MOD: DO_BINARY_UI_OP_EX(mpz_mod, gmp_mpz_mod_ui, 1); case ZEND_SL: - shift_operator_helper(mpz_mul_2exp, result, op1, op2, opcode); - return SUCCESS; + return shift_operator_helper(mpz_mul_2exp, result, op1, op2, opcode); case ZEND_SR: - shift_operator_helper(mpz_fdiv_q_2exp, result, op1, op2, opcode); - return SUCCESS; + return shift_operator_helper(mpz_fdiv_q_2exp, result, op1, op2, opcode); case ZEND_BW_OR: DO_BINARY_OP(mpz_ior); case ZEND_BW_AND: @@ -619,6 +680,13 @@ case IS_STRING: { return convert_zstr_to_gmp(gmpnumber, Z_STR_P(val), base, arg_pos); } + case IS_NULL: + /* Just reject null for operator overloading */ + if (arg_pos == 0) { + zend_type_error("Number must be of type GMP|string|int, %s given", zend_zval_type_name(val)); + return FAILURE; + } + ZEND_FALLTHROUGH; default: { zend_long lval; if (!zend_parse_arg_long_slow(val, &lval, arg_pos)) { @@ -1002,8 +1070,14 @@ if (mpz_sgn(gmpnumber) == 0) { RETVAL_EMPTY_STRING(); } else { - size_t bits_per_word = size * 8; - size_t count = (mpz_sizeinbase(gmpnumber, 2) + bits_per_word - 1) / bits_per_word; + ZEND_ASSERT(size > 0); + size_t size_in_base_2 = mpz_sizeinbase(gmpnumber, 2); + if (size > ZEND_LONG_MAX / 4 || size_in_base_2 > SIZE_MAX - (size_t) size * 8 + 1) { + zend_argument_value_error(2, "is too large for argument #1 ($num)"); + RETURN_THROWS(); + } + size_t bits_per_word = (size_t) size * 8; + size_t count = (size_in_base_2 + bits_per_word - 1) / bits_per_word; zend_string *out_string = zend_string_safe_alloc(count, size, 0, 0); mpz_export(ZSTR_VAL(out_string), NULL, order, size, endian, 0, gmpnumber); @@ -1276,13 +1350,26 @@ RETURN_THROWS(); } + double powmax = log((double)ZEND_LONG_MAX); + if (Z_TYPE_P(base_arg) == IS_LONG && Z_LVAL_P(base_arg) >= 0) { INIT_GMP_RETVAL(gmpnum_result); + if ((log(Z_LVAL_P(base_arg)) * exp) > powmax) { + zend_value_error("base and exponent overflow"); + RETURN_THROWS(); + } mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp); } else { mpz_ptr gmpnum_base; + zend_ulong gmpnum; FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base, 1); INIT_GMP_RETVAL(gmpnum_result); + gmpnum = mpz_get_ui(gmpnum_base); + if ((log(gmpnum) * exp) > powmax) { + FREE_GMP_TEMP(temp_base); + zend_value_error("base and exponent overflow"); + RETURN_THROWS(); + } mpz_pow_ui(gmpnum_result, gmpnum_base, exp); FREE_GMP_TEMP(temp_base); } @@ -1772,15 +1859,21 @@ RETURN_THROWS(); } - if (bits <= 0) { - zend_argument_value_error(1, "must be greater than or equal to 1"); +#if SIZEOF_SIZE_T == 4 + const zend_long maxbits = ULONG_MAX / GMP_NUMB_BITS; +#else + const zend_long maxbits = INT_MAX; +#endif + + if (bits <= 0 || bits > maxbits) { + zend_argument_value_error(1, "must be between 1 and " ZEND_LONG_FMT, maxbits); RETURN_THROWS(); } INIT_GMP_RETVAL(gmpnum_result); gmp_init_random(); - mpz_urandomb(gmpnum_result, GMPG(rand_state), bits); + mpz_urandomb(gmpnum_result, GMPG(rand_state), (mp_bitcnt_t)bits); } /* }}} */ diff -Nru php8.2-8.2.24/ext/gmp/tests/gh16411.phpt php8.2-8.2.26/ext/gmp/tests/gh16411.phpt --- php8.2-8.2.24/ext/gmp/tests/gh16411.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/gh16411.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,11 @@ +--TEST-- +GH-16411 (gmp_export() can cause overflow) +--EXTENSIONS-- +gmp +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught ValueError: gmp_export(): Argument #2 ($word_size) is too large for argument #1 ($num) in %s:%d +%A diff -Nru php8.2-8.2.24/ext/gmp/tests/gh16501.phpt php8.2-8.2.26/ext/gmp/tests/gh16501.phpt --- php8.2-8.2.24/ext/gmp/tests/gh16501.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/gh16501.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,14 @@ +--TEST-- +GH-16501 (gmp_random_bits overflow) +--EXTENSIONS-- +gmp +--FILE-- +getMessage(); +} +?> +--EXPECTF-- +gmp_random_bits(): Argument #1 ($bits) must be between 1 and %d diff -Nru php8.2-8.2.24/ext/gmp/tests/gmp_pow.phpt php8.2-8.2.26/ext/gmp/tests/gmp_pow.phpt --- php8.2-8.2.24/ext/gmp/tests/gmp_pow.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/gmp_pow.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -2,6 +2,8 @@ gmp_pow() basic tests --EXTENSIONS-- gmp +--SKIPIF-- + --FILE-- +--FILE-- +getMessage() . "\n"; +} +var_dump(gmp_strval(gmp_pow("-2",10))); +try { + gmp_pow(20,10); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} +try { + gmp_pow(50,10); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} +try { + gmp_pow(50,-5); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} +try { + $n = gmp_init("20"); + gmp_pow($n,10); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} +try { + $n = gmp_init("-20"); + gmp_pow($n,10); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} +try { + var_dump(gmp_pow(2,array())); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +try { + var_dump(gmp_pow(array(),10)); +} catch (\TypeError $e) { + echo $e->getMessage() . \PHP_EOL; +} + +echo "Done\n"; +?> +--EXPECT-- +string(4) "1024" +string(4) "1024" +string(5) "-2048" +string(4) "1024" +string(1) "1" +gmp_pow(): Argument #2 ($exponent) must be greater than or equal to 0 +string(4) "1024" +base and exponent overflow +base and exponent overflow +gmp_pow(): Argument #2 ($exponent) must be greater than or equal to 0 +base and exponent overflow +base and exponent overflow +gmp_pow(): Argument #2 ($exponent) must be of type int, array given +gmp_pow(): Argument #1 ($num) must be of type GMP|string|int, array given +Done diff -Nru php8.2-8.2.24/ext/gmp/tests/gmp_pow_fpe.phpt php8.2-8.2.26/ext/gmp/tests/gmp_pow_fpe.phpt --- php8.2-8.2.24/ext/gmp/tests/gmp_pow_fpe.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/gmp_pow_fpe.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,35 @@ +--TEST-- +gmp_pow() floating point exception +--EXTENSIONS-- +gmp +--FILE-- +getMessage() . PHP_EOL; +} +try { + gmp_pow(256, PHP_INT_MAX); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + gmp_pow(gmp_add(gmp_mul(gmp_init(PHP_INT_MAX), gmp_init(PHP_INT_MAX)), 3), 256); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} +try { + gmp_pow(gmp_init(PHP_INT_MAX), 256); +} catch (\ValueError $e) { + echo $e->getMessage(); +} +?> +--EXPECTF-- +base and exponent overflow +base and exponent overflow +base and exponent overflow +base and exponent overflow diff -Nru php8.2-8.2.24/ext/gmp/tests/gmp_random_bits.phpt php8.2-8.2.26/ext/gmp/tests/gmp_random_bits.phpt --- php8.2-8.2.24/ext/gmp/tests/gmp_random_bits.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/gmp_random_bits.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -40,7 +40,7 @@ echo "Done\n"; ?> ---EXPECT-- -gmp_random_bits(): Argument #1 ($bits) must be greater than or equal to 1 -gmp_random_bits(): Argument #1 ($bits) must be greater than or equal to 1 +--EXPECTF-- +gmp_random_bits(): Argument #1 ($bits) must be between 1 and %d +gmp_random_bits(): Argument #1 ($bits) must be between 1 and %d Done diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_cmp_op_with_null.phpt php8.2-8.2.26/ext/gmp/tests/overloading_cmp_op_with_null.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_cmp_op_with_null.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_cmp_op_with_null.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GMP comparison operator overloading supports null +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num > null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num <= null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num >= null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num == null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num <=> null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +int(1) diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_with_array.phpt php8.2-8.2.26/ext/gmp/tests/overloading_with_array.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_with_array.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_with_array.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,84 @@ +--TEST-- +GMP operator overloading does not support [] +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num - []); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num * []); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num / []); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num % []); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num ** []); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num | []); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num & []); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num ^ []); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num << []); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num >> []); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +TypeError: Number must be of type GMP|string|int, array given +TypeError: Number must be of type GMP|string|int, array given +TypeError: Number must be of type GMP|string|int, array given +TypeError: Number must be of type GMP|string|int, array given +TypeError: Number must be of type GMP|string|int, array given +TypeError: Unsupported operand types: GMP ** array +TypeError: Number must be of type GMP|string|int, array given +TypeError: Number must be of type GMP|string|int, array given +TypeError: Number must be of type GMP|string|int, array given +TypeError: Unsupported operand types: GMP << array +TypeError: Unsupported operand types: GMP >> array diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_with_float.phpt php8.2-8.2.26/ext/gmp/tests/overloading_with_float.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_with_float.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_with_float.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,117 @@ +--TEST-- +GMP operator overloading does support float with no fractional +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num - 42.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num * 42.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num / 42.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num % 42.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num ** 42.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num | 42.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num & 42.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num ^ 42.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num << 42.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num >> 42.0); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +object(GMP)#2 (1) { + ["num"]=> + string(2) "84" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#2 (1) { + ["num"]=> + string(4) "1764" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "1" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#2 (1) { + ["num"]=> + string(69) "150130937545296572356771972164254457814047970568738777235893533016064" +} +object(GMP)#2 (1) { + ["num"]=> + string(2) "42" +} +object(GMP)#2 (1) { + ["num"]=> + string(2) "42" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#2 (1) { + ["num"]=> + string(15) "184717953466368" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "0" +} diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_with_float_fractional.phpt php8.2-8.2.26/ext/gmp/tests/overloading_with_float_fractional.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_with_float_fractional.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_with_float_fractional.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,132 @@ +--TEST-- +GMP operator overloading support for float with fractional is deprecated +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num - 42.5); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num * 42.5); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num / 42.5); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num % 42.5); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num ** 42.5); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num | 42.5); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num & 42.5); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num ^ 42.5); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num << 42.5); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num >> 42.5); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECTF-- +Deprecated: Implicit conversion from float 42.5 to int loses precision in %s on line %d +object(GMP)#2 (1) { + ["num"]=> + string(2) "84" +} + +Deprecated: Implicit conversion from float 42.5 to int loses precision in %s on line %d +object(GMP)#2 (1) { + ["num"]=> + string(1) "0" +} + +Deprecated: Implicit conversion from float 42.5 to int loses precision in %s on line %d +object(GMP)#2 (1) { + ["num"]=> + string(4) "1764" +} + +Deprecated: Implicit conversion from float 42.5 to int loses precision in %s on line %d +object(GMP)#2 (1) { + ["num"]=> + string(1) "1" +} + +Deprecated: Implicit conversion from float 42.5 to int loses precision in %s on line %d +object(GMP)#2 (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#2 (1) { + ["num"]=> + string(69) "150130937545296572356771972164254457814047970568738777235893533016064" +} + +Deprecated: Implicit conversion from float 42.5 to int loses precision in %s on line %d +object(GMP)#2 (1) { + ["num"]=> + string(2) "42" +} + +Deprecated: Implicit conversion from float 42.5 to int loses precision in %s on line %d +object(GMP)#2 (1) { + ["num"]=> + string(2) "42" +} + +Deprecated: Implicit conversion from float 42.5 to int loses precision in %s on line %d +object(GMP)#2 (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#2 (1) { + ["num"]=> + string(15) "184717953466368" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "0" +} diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_with_float_string.phpt php8.2-8.2.26/ext/gmp/tests/overloading_with_float_string.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_with_float_string.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_with_float_string.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,84 @@ +--TEST-- +GMP operator overloading does not support float strings +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num - "2.0"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num * "2.0"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num / "2.0"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num % "2.0"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num ** "2.0"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num | "2.0"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num & "2.0"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num ^ "2.0"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num << "2.0"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num >> "2.0"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_with_int_string.phpt php8.2-8.2.26/ext/gmp/tests/overloading_with_int_string.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_with_int_string.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_with_int_string.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,117 @@ +--TEST-- +GMP operator overloading does support int strings +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num - "2"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num * "2"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num / "2"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num % "2"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num ** "2"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num | "2"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num & "2"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num ^ "2"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num << "2"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num >> "2"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +object(GMP)#2 (1) { + ["num"]=> + string(2) "44" +} +object(GMP)#2 (1) { + ["num"]=> + string(2) "40" +} +object(GMP)#2 (1) { + ["num"]=> + string(2) "84" +} +object(GMP)#2 (1) { + ["num"]=> + string(2) "21" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "0" +} +object(GMP)#2 (1) { + ["num"]=> + string(4) "1764" +} +object(GMP)#2 (1) { + ["num"]=> + string(2) "42" +} +object(GMP)#2 (1) { + ["num"]=> + string(1) "2" +} +object(GMP)#2 (1) { + ["num"]=> + string(2) "40" +} +object(GMP)#2 (1) { + ["num"]=> + string(3) "168" +} +object(GMP)#2 (1) { + ["num"]=> + string(2) "10" +} diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_with_non_numeric_string.phpt php8.2-8.2.26/ext/gmp/tests/overloading_with_non_numeric_string.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_with_non_numeric_string.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_with_non_numeric_string.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,84 @@ +--TEST-- +GMP operator overloading does not support non-numeric strings +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num - "string"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num * "string"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num / "string"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num % "string"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num ** "string"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num | "string"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num & "string"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num ^ "string"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num << "string"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num >> "string"); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string +ValueError: Number is not an integer string diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_with_null.phpt php8.2-8.2.26/ext/gmp/tests/overloading_with_null.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_with_null.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_with_null.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,84 @@ +--TEST-- +GMP operator overloading does not support null +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num - null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num * null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num / null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num % null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num ** null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num | null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num & null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num ^ null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num << null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num >> null); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +TypeError: Number must be of type GMP|string|int, null given +TypeError: Number must be of type GMP|string|int, null given +TypeError: Number must be of type GMP|string|int, null given +TypeError: Number must be of type GMP|string|int, null given +TypeError: Number must be of type GMP|string|int, null given +TypeError: Unsupported operand types: GMP ** null +TypeError: Number must be of type GMP|string|int, null given +TypeError: Number must be of type GMP|string|int, null given +TypeError: Number must be of type GMP|string|int, null given +TypeError: Unsupported operand types: GMP << null +TypeError: Unsupported operand types: GMP >> null diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_with_object_not_stringable.phpt php8.2-8.2.26/ext/gmp/tests/overloading_with_object_not_stringable.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_with_object_not_stringable.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_with_object_not_stringable.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,85 @@ +--TEST-- +GMP operator overloading does not support non-stringable objects +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num - $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num * $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num / $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num % $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num ** $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num | $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num & $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num ^ $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num << $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num >> $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +TypeError: Number must be of type GMP|string|int, stdClass given +TypeError: Number must be of type GMP|string|int, stdClass given +TypeError: Number must be of type GMP|string|int, stdClass given +TypeError: Number must be of type GMP|string|int, stdClass given +TypeError: Number must be of type GMP|string|int, stdClass given +TypeError: Unsupported operand types: GMP ** stdClass +TypeError: Number must be of type GMP|string|int, stdClass given +TypeError: Number must be of type GMP|string|int, stdClass given +TypeError: Number must be of type GMP|string|int, stdClass given +TypeError: Unsupported operand types: GMP << stdClass +TypeError: Unsupported operand types: GMP >> stdClass diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_with_object_stringable.phpt php8.2-8.2.26/ext/gmp/tests/overloading_with_object_stringable.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_with_object_stringable.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_with_object_stringable.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,91 @@ +--TEST-- +GMP operator overloading does not support stringable objects +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num - $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num * $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num / $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num % $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num ** $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num | $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num & $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num ^ $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num << $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num >> $o); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECTF-- +TypeError: Number must be of type GMP|string|int, T given +TypeError: Number must be of type GMP|string|int, T given +TypeError: Number must be of type GMP|string|int, T given +TypeError: Number must be of type GMP|string|int, T given +TypeError: Number must be of type GMP|string|int, T given +TypeError: Unsupported operand types: GMP ** T +TypeError: Number must be of type GMP|string|int, T given +TypeError: Number must be of type GMP|string|int, T given +TypeError: Number must be of type GMP|string|int, T given +TypeError: Unsupported operand types: GMP << T +TypeError: Unsupported operand types: GMP >> T diff -Nru php8.2-8.2.24/ext/gmp/tests/overloading_with_resource.phpt php8.2-8.2.26/ext/gmp/tests/overloading_with_resource.phpt --- php8.2-8.2.24/ext/gmp/tests/overloading_with_resource.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/gmp/tests/overloading_with_resource.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,84 @@ +--TEST-- +GMP operator overloading does not support resources +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($num - STDERR); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num * STDERR); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num / STDERR); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num % STDERR); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num ** STDERR); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +try { + var_dump($num | STDERR); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num & STDERR); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num ^ STDERR); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num << STDERR); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +try { + var_dump($num >> STDERR); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +TypeError: Number must be of type GMP|string|int, resource given +TypeError: Number must be of type GMP|string|int, resource given +TypeError: Number must be of type GMP|string|int, resource given +TypeError: Number must be of type GMP|string|int, resource given +TypeError: Number must be of type GMP|string|int, resource given +TypeError: Unsupported operand types: GMP ** resource +TypeError: Number must be of type GMP|string|int, resource given +TypeError: Number must be of type GMP|string|int, resource given +TypeError: Number must be of type GMP|string|int, resource given +TypeError: Unsupported operand types: GMP << resource +TypeError: Unsupported operand types: GMP >> resource diff -Nru php8.2-8.2.24/ext/intl/tests/bug62070_3.phpt php8.2-8.2.26/ext/intl/tests/bug62070_3.phpt --- php8.2-8.2.24/ext/intl/tests/bug62070_3.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/intl/tests/bug62070_3.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -4,6 +4,7 @@ intl --SKIPIF-- = 62.1'); ?> += 0) die('skip for ICU < 76.1'); ?> --FILE-- = 76.1'); ?> +--FILE-- + +--EXPECT-- +93AAG%01%09%01%DC%08 diff -Nru php8.2-8.2.24/ext/intl/tests/collator_get_sort_key_variant7.phpt php8.2-8.2.26/ext/intl/tests/collator_get_sort_key_variant7.phpt --- php8.2-8.2.24/ext/intl/tests/collator_get_sort_key_variant7.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/intl/tests/collator_get_sort_key_variant7.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -4,6 +4,7 @@ intl --SKIPIF-- = 62.1'); ?> += 0) die('skip for ICU < 76.1'); ?> --FILE-- = 62.1 +--EXTENSIONS-- +intl +--SKIPIF-- += 76.1'); ?> +--FILE-- + +--EXPECT-- +source: abc +key: 2b2d2f01070107 +source: abd +key: 2b2d3101070107 +source: aaa +key: 2b2b2b01070107 +source: аа +key: 62060601060106 +source: а +key: 620601050105 +source: z +key: 5d01050105 +source: +key: 0101 +source: 3 +key: 1801050105 +source: y +key: 5b01050105 +source: i +key: 3b01050105 +source: k +key: 3f01050105 +source: абг +key: 28060c1001070107 +source: абв +key: 28060c0e01070107 +source: жжж +key: 282c2c2c01070107 +source: эюя +key: 28eef0f401070107 +source: абг +key: 62060c1001070107 +source: абв +key: 62060c0e01070107 +source: жжж +key: 622c2c2c01070107 +source: эюя +key: 62eef0f401070107 diff -Nru php8.2-8.2.24/ext/intl/tests/locale_get_display_name8.phpt php8.2-8.2.26/ext/intl/tests/locale_get_display_name8.phpt --- php8.2-8.2.24/ext/intl/tests/locale_get_display_name8.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/intl/tests/locale_get_display_name8.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -317,14 +317,14 @@ disp_locale=de : display_name=Englisch #Vereinigte Staaten, attribute=islamcal# ----------------- locale='zh-CN-a-myExt-x-private' -disp_locale=en : display_name=Chinese #China, a=myext, Private-Use=private# -disp_locale=fr : display_name=chinois #Chine, a=myext, usage privé=private# -disp_locale=de : display_name=Chinesisch #China, a=myext, Privatnutzung=private# +disp_locale=en : display_name=Chinese #China(, A_MYEXT_X_PRIVATE)?, a=myext, Private-Use=private# +disp_locale=fr : display_name=chinois #Chine(, A_MYEXT_X_PRIVATE)?, a=myext, usage privé=private# +disp_locale=de : display_name=Chinesisch #China(, A_MYEXT_X_PRIVATE)?, a=myext, Privatnutzung=private# ----------------- locale='en-a-myExt-b-another' -disp_locale=en : display_name=English #a=myext, b=another# -disp_locale=fr : display_name=anglais #a=myext, b=another# -disp_locale=de : display_name=Englisch #a=myext, b=another# +disp_locale=en : display_name=English #(A_MYEXT_B_ANOTHER, )?a=myext, b=another# +disp_locale=fr : display_name=anglais #(A_MYEXT_B_ANOTHER, )?a=myext, b=another# +disp_locale=de : display_name=Englisch #(A_MYEXT_B_ANOTHER, )?a=myext, b=another# ----------------- locale='de-419-DE' disp_locale=en : display_name=German #Latin America, DE# @@ -337,7 +337,7 @@ disp_locale=de : display_name=a #Deutschland# ----------------- locale='ar-a-aaa-b-bbb-a-ccc' -disp_locale=en : display_name=Arabic #a=aaa, b=bbb# -disp_locale=fr : display_name=arabe #a=aaa, b=bbb# -disp_locale=de : display_name=Arabisch #a=aaa, b=bbb# +disp_locale=en : display_name=Arabic #(A_AAA_B_BBB_A_CCC, )?a=aaa, b=bbb# +disp_locale=fr : display_name=arabe #(A_AAA_B_BBB_A_CCC, )?a=aaa, b=bbb# +disp_locale=de : display_name=Arabisch #(A_AAA_B_BBB_A_CCC, )?a=aaa, b=bbb# ----------------- diff -Nru php8.2-8.2.24/ext/intl/tests/locale_get_display_variant2.phpt php8.2-8.2.26/ext/intl/tests/locale_get_display_variant2.phpt --- php8.2-8.2.24/ext/intl/tests/locale_get_display_variant2.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/intl/tests/locale_get_display_variant2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -248,14 +248,14 @@ disp_locale=de : display_variant= ----------------- locale='zh-CN-a-myExt-x-private' -disp_locale=en : display_variant= -disp_locale=fr : display_variant= -disp_locale=de : display_variant= +disp_locale=en : display_variant=(A_MYEXT_X_PRIVATE)? +disp_locale=fr : display_variant=(A_MYEXT_X_PRIVATE)? +disp_locale=de : display_variant=(A_MYEXT_X_PRIVATE)? ----------------- locale='en-a-myExt-b-another' -disp_locale=en : display_variant=(MYEXT_B_ANOTHER)? -disp_locale=fr : display_variant=(MYEXT_B_ANOTHER)? -disp_locale=de : display_variant=(MYEXT_B_ANOTHER)? +disp_locale=en : display_variant=((A_)?MYEXT_B_ANOTHER)? +disp_locale=fr : display_variant=((A_)?MYEXT_B_ANOTHER)? +disp_locale=de : display_variant=((A_)?MYEXT_B_ANOTHER)? ----------------- locale='de-419-DE' disp_locale=en : display_variant=DE @@ -268,7 +268,7 @@ disp_locale=de : display_variant= ----------------- locale='ar-a-aaa-b-bbb-a-ccc' -disp_locale=en : display_variant=(AAA_B_BBB_A_CCC)? -disp_locale=fr : display_variant=(AAA_B_BBB_A_CCC)? -disp_locale=de : display_variant=(AAA_B_BBB_A_CCC)? +disp_locale=en : display_variant=((A_)?AAA_B_BBB_A_CCC)? +disp_locale=fr : display_variant=((A_)?AAA_B_BBB_A_CCC)? +disp_locale=de : display_variant=((A_)?AAA_B_BBB_A_CCC)? ----------------- diff -Nru php8.2-8.2.24/ext/intl/tests/timezone_IDforWindowsID_basic2.phpt php8.2-8.2.26/ext/intl/tests/timezone_IDforWindowsID_basic2.phpt --- php8.2-8.2.24/ext/intl/tests/timezone_IDforWindowsID_basic2.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/intl/tests/timezone_IDforWindowsID_basic2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -4,6 +4,7 @@ intl --SKIPIF-- = 58.1'); ?> += 0) die('skip for ICU <= 76.1'); ?> --FILE-- = 76.1'); ?> +--FILE-- + array(NULL), + 'India Standard Time' => array(NULL), + 'Pacific Standard Time' => array('001', 'CA', 'MX', 'US', 'ZZ'), + 'Romance Standard Time' => array('001', 'BE', 'DK', 'ES', 'FR'), +); + +foreach ($tzs as $tz => $regions) { + echo "** $tz\n"; + foreach ($regions as $region) { + var_dump(IntlTimeZone::getIDForWindowsID($tz, $region)); + if (intl_get_error_code() != U_ZERO_ERROR) { + echo "Error: ", intl_get_error_message(), "\n"; + } + } +} +?> +--EXPECTF-- +** Gnomeregan +bool(false) +Error: %snknown windows timezone: U_ILLEGAL_ARGUMENT_ERROR +** India Standard Time +string(13) "Asia/Calcutta" +** Pacific Standard Time +string(19) "America/Los_Angeles" +string(17) "America/Vancouver" +string(19) "America/Los_Angeles" +string(19) "America/Los_Angeles" +string(19) "America/Los_Angeles" +** Romance Standard Time +string(12) "Europe/Paris" +string(15) "Europe/Brussels" +string(17) "Europe/Copenhagen" +string(13) "Europe/Madrid" +string(12) "Europe/Paris" diff -Nru php8.2-8.2.24/ext/ldap/ldap.c php8.2-8.2.26/ext/ldap/ldap.c --- php8.2-8.2.24/ext/ldap/ldap.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/ldap/ldap.c 2024-11-19 17:11:09.000000000 +0000 @@ -1429,6 +1429,11 @@ ret = 0; goto cleanup; } + if (!zend_array_is_list(Z_ARRVAL_P(link))) { + zend_argument_value_error(1, "must be a list"); + ret = 0; + goto cleanup; + } if (base_dn_ht) { nbases = zend_hash_num_elements(base_dn_ht); @@ -2145,17 +2150,11 @@ ldap_mods[i]->mod_type = estrndup(ZSTR_VAL(attribute), ZSTR_LEN(attribute)); } else { php_error_docref(NULL, E_WARNING, "Unknown attribute in the data"); - /* Free allocated memory */ - while (i >= 0) { - if (ldap_mods[i]->mod_type) { - efree(ldap_mods[i]->mod_type); - } - efree(ldap_mods[i]); - i--; - } - efree(num_berval); - efree(ldap_mods); - RETURN_FALSE; + RETVAL_FALSE; + num_berval[i] = 0; + num_attribs = i + 1; + ldap_mods[i]->mod_bvalues = NULL; + goto cleanup; } value = zend_hash_get_current_data(Z_ARRVAL_P(entry)); @@ -2176,6 +2175,8 @@ convert_to_string(value); if (EG(exception)) { RETVAL_FALSE; + num_berval[i] = 0; + num_attribs = i + 1; goto cleanup; } ldap_mods[i]->mod_bvalues[0] = (struct berval *) emalloc (sizeof(struct berval)); @@ -2192,6 +2193,8 @@ } convert_to_string(ivalue); if (EG(exception)) { + num_berval[i] = j; + num_attribs = i + 1; RETVAL_FALSE; goto cleanup; } @@ -2544,8 +2547,11 @@ /* for the modification hashtable... */ zend_hash_internal_pointer_reset(Z_ARRVAL_P(mod)); num_modprops = zend_hash_num_elements(Z_ARRVAL_P(mod)); + bool has_attrib_key = false; + bool has_modtype_key = false; for (j = 0; j < num_modprops; j++) { + /* are the keys strings? */ if (zend_hash_get_current_key(Z_ARRVAL_P(mod), &modkey, &tmpUlong) != HASH_KEY_IS_STRING) { zend_argument_type_error(3, "must only contain string-indexed arrays"); @@ -2567,6 +2573,7 @@ /* does the value type match the key? */ if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_ATTRIB)) { + has_attrib_key = true; if (Z_TYPE_P(modinfo) != IS_STRING) { zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_ATTRIB "\" must be of type string, %s given", get_active_function_name(), zend_zval_type_name(modinfo)); RETURN_THROWS(); @@ -2578,6 +2585,7 @@ } } else if (_ldap_str_equal_to_const(ZSTR_VAL(modkey), ZSTR_LEN(modkey), LDAP_MODIFY_BATCH_MODTYPE)) { + has_modtype_key = true; if (Z_TYPE_P(modinfo) != IS_LONG) { zend_type_error("%s(): Option \"" LDAP_MODIFY_BATCH_MODTYPE "\" must be of type int, %s given", get_active_function_name(), zend_zval_type_name(modinfo)); RETURN_THROWS(); @@ -2641,6 +2649,15 @@ zend_hash_move_forward(Z_ARRVAL_P(mod)); } + + if (!has_attrib_key) { + zend_value_error("%s(): Required option \"" LDAP_MODIFY_BATCH_ATTRIB "\" is missing", get_active_function_name()); + RETURN_THROWS(); + } + if (!has_modtype_key) { + zend_value_error("%s(): Required option \"" LDAP_MODIFY_BATCH_MODTYPE "\" is missing", get_active_function_name()); + RETURN_THROWS(); + } } } /* validation was successful */ @@ -3684,13 +3701,23 @@ zend_string *ret; for (i = 0; i < valuelen; i++) { - len += (map[(unsigned char) value[i]]) ? 3 : 1; + size_t addend = (map[(unsigned char) value[i]]) ? 3 : 1; + if (len > ZSTR_MAX_LEN - addend) { + return NULL; + } + len += addend; } /* Per RFC 4514, a leading and trailing space must be escaped */ if ((flags & PHP_LDAP_ESCAPE_DN) && (value[0] == ' ')) { + if (len > ZSTR_MAX_LEN - 2) { + return NULL; + } len += 2; } if ((flags & PHP_LDAP_ESCAPE_DN) && ((valuelen > 1) && (value[valuelen - 1] == ' '))) { + if (len > ZSTR_MAX_LEN - 2) { + return NULL; + } len += 2; } @@ -3757,7 +3784,13 @@ php_ldap_escape_map_set_chars(map, ignores, ignoreslen, 0); } - RETURN_NEW_STR(php_ldap_do_escape(map, value, valuelen, flags)); + zend_string *result = php_ldap_do_escape(map, value, valuelen, flags); + if (UNEXPECTED(!result)) { + zend_argument_value_error(1, "is too long"); + RETURN_THROWS(); + } + + RETURN_NEW_STR(result); } #ifdef STR_TRANSLATION diff -Nru php8.2-8.2.24/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt php8.2-8.2.26/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt --- php8.2-8.2.24/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/ldap/tests/GHSA-g665-fm4p-vhff-1.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,28 @@ +--TEST-- +GHSA-g665-fm4p-vhff (OOB access in ldap_escape) +--EXTENSIONS-- +ldap +--INI-- +memory_limit=-1 +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +try { + ldap_escape(str_repeat("#", 1431655758).' ', "", LDAP_ESCAPE_DN); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +ldap_escape(): Argument #1 ($value) is too long +ldap_escape(): Argument #1 ($value) is too long diff -Nru php8.2-8.2.24/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt php8.2-8.2.26/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt --- php8.2-8.2.24/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/ldap/tests/GHSA-g665-fm4p-vhff-2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,29 @@ +--TEST-- +GHSA-g665-fm4p-vhff (OOB access in ldap_escape) +--EXTENSIONS-- +ldap +--INI-- +memory_limit=-1 +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +// would allocate a string of length 2 +try { + ldap_escape(str_repeat("*", 1431655766), "", LDAP_ESCAPE_FILTER); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +ldap_escape(): Argument #1 ($value) is too long +ldap_escape(): Argument #1 ($value) is too long diff -Nru php8.2-8.2.24/ext/ldap/tests/gh16032-1.phpt php8.2-8.2.26/ext/ldap/tests/gh16032-1.phpt --- php8.2-8.2.24/ext/ldap/tests/gh16032-1.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/ldap/tests/gh16032-1.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,26 @@ +--TEST-- +Bug GH-16032: Various NULL pointer dereferencements in ldap_modify_batch() +--EXTENSIONS-- +ldap +--FILE-- + LDAP_MODIFY_BATCH_ADD, + "values" => ["value1"], + ], +]; +try { + var_dump(ldap_modify_batch($ldap, $valid_dn, $modification_missing_attrib_key)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ValueError: ldap_modify_batch(): Required option "attrib" is missing diff -Nru php8.2-8.2.24/ext/ldap/tests/gh16032-2.phpt php8.2-8.2.26/ext/ldap/tests/gh16032-2.phpt --- php8.2-8.2.24/ext/ldap/tests/gh16032-2.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/ldap/tests/gh16032-2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,26 @@ +--TEST-- +Bug GH-16032: Various NULL pointer dereferencements in ldap_modify_batch() +--EXTENSIONS-- +ldap +--FILE-- + "attrib1", + "values" => ["value1"], + ], +]; +try { + var_dump(ldap_modify_batch($ldap, $valid_dn, $modification_missing_modtype_key)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ValueError: ldap_modify_batch(): Required option "modtype" is missing diff -Nru php8.2-8.2.24/ext/ldap/tests/gh16101.phpt php8.2-8.2.26/ext/ldap/tests/gh16101.phpt --- php8.2-8.2.24/ext/ldap/tests/gh16101.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/ldap/tests/gh16101.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,25 @@ +--TEST-- +Bug GH-16101: Segfault in ldap_list(), ldap_read(), and ldap_search() when LDAPs array is not a list +--EXTENSIONS-- +ldap +--FILE-- + $ldap, + "world" => $ldap, +]; +try { + var_dump(ldap_list($ldaps_dict, $valid_dn, $valid_filter)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +ValueError: ldap_list(): Argument #1 ($ldap) must be a list diff -Nru php8.2-8.2.24/ext/ldap/tests/gh16132-1.phpt php8.2-8.2.26/ext/ldap/tests/gh16132-1.phpt --- php8.2-8.2.24/ext/ldap/tests/gh16132-1.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/ldap/tests/gh16132-1.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,28 @@ +--TEST-- +Bug GH-16132: Attempting to free pointer not allocated by ZMM +--EXTENSIONS-- +ldap +--FILE-- + new stdClass(), + 'attribute2' => [ + 'value1', + 'value2', + ], +]; +try { + var_dump(ldap_add($ldap, $valid_dn, $dict_key_value_not_string)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Error: Object of class stdClass could not be converted to string diff -Nru php8.2-8.2.24/ext/ldap/tests/gh16132-2.phpt php8.2-8.2.26/ext/ldap/tests/gh16132-2.phpt --- php8.2-8.2.24/ext/ldap/tests/gh16132-2.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/ldap/tests/gh16132-2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,28 @@ +--TEST-- +Bug GH-16132: Attempting to free pointer not allocated by ZMM +--EXTENSIONS-- +ldap +--FILE-- + 'value', + 'attribute2' => [ + 'value1', + new stdClass(), + ], +]; +try { + var_dump(ldap_add($ldap, $valid_dn, $dict_key_multi_value_not_list_of_strings2)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Error: Object of class stdClass could not be converted to string diff -Nru php8.2-8.2.24/ext/ldap/tests/gh16136.phpt php8.2-8.2.26/ext/ldap/tests/gh16136.phpt --- php8.2-8.2.24/ext/ldap/tests/gh16136.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/ldap/tests/gh16136.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,30 @@ +--TEST-- +Bug GH-16136: Memory leak in php_ldap_do_modify() when entry is not a proper dictionary +--EXTENSIONS-- +ldap +--FILE-- + 'value', + 'not_key_entry', + 'attribute3' => [ + 'value1', + 'value2', + ], +]; +try { + var_dump(ldap_add($ldap, $valid_dn, $not_dict_of_attributes)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} + +?> +--EXPECTF-- +Warning: ldap_add(): Unknown attribute in the data in %s on line %d +bool(false) diff -Nru php8.2-8.2.24/ext/libxml/tests/bug61367-read_2.phpt php8.2-8.2.26/ext/libxml/tests/bug61367-read_2.phpt --- php8.2-8.2.24/ext/libxml/tests/bug61367-read_2.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/libxml/tests/bug61367-read_2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -58,6 +58,6 @@ int(4) bool(true) -Warning: DOMDocument::loadXML(): %Sfailed to load external entity "file:///%s/test_bug_61367-read/bad" in %s on line %d +%s: DOMDocument::loadXML(): %Sfailed to load %s Warning: Attempt to read property "nodeValue" on null in %s on line %d diff -Nru php8.2-8.2.24/ext/libxml/tests/libxml_disable_entity_loader_2.phpt php8.2-8.2.26/ext/libxml/tests/libxml_disable_entity_loader_2.phpt --- php8.2-8.2.24/ext/libxml/tests/libxml_disable_entity_loader_2.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/libxml/tests/libxml_disable_entity_loader_2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -39,6 +39,6 @@ Deprecated: Function libxml_disable_entity_loader() is deprecated in %s on line %d bool(false) -Warning: DOMDocument::loadXML(): %Sfailed to load external entity "%s" in %s on line %d +%s: DOMDocument::loadXML(): %Sfailed to load %s bool(true) Done diff -Nru php8.2-8.2.24/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt php8.2-8.2.26/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt --- php8.2-8.2.24/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -61,7 +61,7 @@ string(32) "http://example.com/fooentity.ent" array(4) { ["directory"]=> - string(%d) "%s" + %r(NULL|string\(%d\) "%s")%r ["intSubName"]=> string(3) "foo" ["extSubURI"]=> diff -Nru php8.2-8.2.24/ext/mbstring/mbstring.c php8.2-8.2.26/ext/mbstring/mbstring.c --- php8.2-8.2.24/ext/mbstring/mbstring.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/mbstring/mbstring.c 2024-11-19 17:11:09.000000000 +0000 @@ -2172,6 +2172,16 @@ Z_PARAM_STR_OR_NULL(encoding) ZEND_PARSE_PARAMETERS_END(); + if (from == ZEND_LONG_MIN) { + zend_argument_value_error(2, "must be between " ZEND_LONG_FMT " and " ZEND_LONG_FMT, (ZEND_LONG_MIN + 1), ZEND_LONG_MAX); + RETURN_THROWS(); + } + + if (!len_is_null && len == ZEND_LONG_MIN) { + zend_argument_value_error(3, "must be between " ZEND_LONG_FMT " and " ZEND_LONG_FMT, (ZEND_LONG_MIN + 1), ZEND_LONG_MAX); + RETURN_THROWS(); + } + string.encoding = php_mb_get_encoding(encoding, 4); if (!string.encoding) { RETURN_THROWS(); @@ -3289,7 +3299,7 @@ if (ret != NULL) { zval_ptr_dtor(orig_var); // TODO: avoid reallocation ??? - ZVAL_STRINGL(orig_var, (char *)ret->val, ret->len); + ZVAL_STRINGL(orig_var, (const char *) ret->val, ret->len); efree(ret->val); } } else if (Z_TYPE_P(var) == IS_ARRAY || Z_TYPE_P(var) == IS_OBJECT) { @@ -3305,7 +3315,22 @@ ht = HASH_OF(var); if (ht != NULL) { - ZEND_HASH_FOREACH_VAL_IND(ht, entry) { + ZEND_HASH_FOREACH_VAL(ht, entry) { + /* Can be a typed property declaration, in which case we need to remove the reference from the source list. + * Just using ZEND_TRY_ASSIGN_STRINGL is not sufficient because that would not unwrap the reference + * and change values through references (see bug #26639). */ + if (Z_TYPE_P(entry) == IS_INDIRECT) { + ZEND_ASSERT(Z_TYPE_P(var) == IS_OBJECT); + + entry = Z_INDIRECT_P(entry); + if (Z_ISREF_P(entry) && Z_TYPE_P(Z_REFVAL_P(entry)) == IS_STRING) { + zend_property_info *info = zend_get_typed_property_info_for_slot(Z_OBJ_P(var), entry); + if (info) { + ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(entry), info); + } + } + } + if (mb_recursive_convert_variable(convd, entry)) { if (Z_REFCOUNTED_P(var)) { Z_UNPROTECT_RECURSION_P(var); @@ -4179,7 +4204,8 @@ #define PHP_MBSTR_MAIL_MIME_HEADER2 "Content-Type: text/plain" #define PHP_MBSTR_MAIL_MIME_HEADER3 "; charset=" #define PHP_MBSTR_MAIL_MIME_HEADER4 "Content-Transfer-Encoding: " - if (str_headers != NULL) { + + if (str_headers != NULL && ZSTR_LEN(str_headers) > 0) { p = ZSTR_VAL(str_headers); n = ZSTR_LEN(str_headers); mbfl_memory_device_strncat(&device, p, n); diff -Nru php8.2-8.2.24/ext/mbstring/tests/gh16229.phpt php8.2-8.2.26/ext/mbstring/tests/gh16229.phpt --- php8.2-8.2.24/ext/mbstring/tests/gh16229.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mbstring/tests/gh16229.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,26 @@ +--TEST-- +GH-16229 (Address overflowed in ext/mbstring/mbstring.c:4613 #16229) +--EXTENSIONS-- +mbstring +--INI-- +sendmail_path={MAIL:{PWD}/mb_send_mail_gh16229.eml} +mail.add_x_header=off +--SKIPIF-- + +--FILE-- + +--CLEAN-- + +--EXPECTF-- diff -Nru php8.2-8.2.24/ext/mbstring/tests/gh16261.phpt php8.2-8.2.26/ext/mbstring/tests/gh16261.phpt --- php8.2-8.2.24/ext/mbstring/tests/gh16261.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mbstring/tests/gh16261.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,44 @@ +--TEST-- +GH-16261 (Reference invariant broken in mb_convert_variables()) +--EXTENSIONS-- +mbstring +--FILE-- +x =& $ref; +$test->z =& $ref3; +mb_convert_variables("EUC-JP", "Shift_JIS", $test); + +class Test2 { + public function __construct(public string $x) {} +} +$test2 = new Test2("foo"); + +mb_convert_variables("EUC-JP", "Shift_JIS", $test->x); + +var_dump($test, $test2); +?> +--EXPECT-- +object(Test)#1 (2) { + ["x"]=> + string(5) "hello" + ["y"]=> + uninitialized(string) + ["z"]=> + &array(1) { + [0]=> + string(5) "world" + } +} +object(Test2)#2 (1) { + ["x"]=> + string(3) "foo" +} diff -Nru php8.2-8.2.24/ext/mbstring/tests/gh16360.phpt php8.2-8.2.26/ext/mbstring/tests/gh16360.phpt --- php8.2-8.2.24/ext/mbstring/tests/gh16360.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mbstring/tests/gh16360.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,23 @@ +--TEST-- +GH-16320 mb_substr overflow from negative length +--EXTENSIONS-- +mbstring +--FILE-- +getMessage() . PHP_EOL; +} +try { + mb_substr("abcd", 0, PHP_INT_MIN, "UTF-8"); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} +var_dump(mb_substr("abcd", PHP_INT_MAX, PHP_INT_MAX, "UTF-8")); +?> +--EXPECTF-- +mb_substr(): Argument #2 ($start) must be between %s and %s +mb_substr(): Argument #3 ($length) must be between %s and %s +string(0) "" + diff -Nru php8.2-8.2.24/ext/mysqli/tests/fake_server.inc php8.2-8.2.26/ext/mysqli/tests/fake_server.inc --- php8.2-8.2.24/ext/mysqli/tests/fake_server.inc 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/fake_server.inc 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,856 @@ + [ + 'type' => '03', + 'charset' => '3f00', + 'length' => '0b000000', + 'flags' => '0110', + 'decimal' => '00', + 'query_data_packet_length' => '080000', + 'query_data_value' => '023134', + 'stmt_data_packet_length' => '0b0000', + 'stmt_data_value' => '0e000000' + ], + 'fltval' => [ + 'type' => '04', + 'charset' => '3f00', + 'length' => '0c000000', + 'flags' => '0110', + 'decimal' => '1f', + 'query_data_packet_length' => '090000', + 'query_data_value' => '03322e33', + 'stmt_data_packet_length' => '0b0000', + 'stmt_data_value' => '33331340', + ], + 'dblval' => [ + 'type' => '05', + 'charset' => '3f00', + 'length' => '16000000', + 'flags' => '0110', + 'decimal' => '1f', + 'query_data_packet_length' => '090000', + 'query_data_value' => '03312e32', + 'stmt_data_packet_length' => '0f0000', + 'stmt_data_value' => '333333333333f33f' + ], + 'datval' => [ + 'type' => '0a', + 'charset' => '3f00', + 'length' => '0a000000', + 'flags' => '8110', + 'decimal' => '00', + 'query_data_packet_length' => '100000', + 'query_data_value' => '0a323031342d31322d3135', + 'stmt_data_packet_length' => '0c0000', + 'stmt_data_value' => '04de070c0f' + ], + 'timval' => [ + 'type' => '0b', + 'charset' => '3f00', + 'length' => '0a000000', + 'flags' => '8110', + 'decimal' => '00', + 'query_data_packet_length' => '0e0000', + 'query_data_value' => '0831333a30303a3032', + 'stmt_data_packet_length' => '100000', + 'stmt_data_value' => '080000000000150801' + ], + 'dtival' => [ + 'type' => '0c', + 'charset' => '3f00', + 'length' => '13000000', + 'flags' => '8110', + 'decimal' => '00', + 'query_data_packet_length' => '190000', + 'query_data_value' => '13323031342d31322d31362031333a30303a3031', + 'stmt_data_packet_length' => '0f0000', + 'stmt_data_value' => '07de070c100d0001' + ], + 'bitval' => [ + 'type' => '10', + 'charset' => '3f00', + 'length' => '40000000', + 'flags' => '2110', + 'decimal' => '00', + 'query_data_packet_length' => '0e0000', + 'query_data_value' => '080808080808080808', + 'stmt_data_packet_length' => '100000', + 'stmt_data_value' => '080808080808080808' + ], + 'strval' => [ + 'type' => 'fd', + 'charset' => 'e000', + 'length' => 'c8000000', + 'flags' => '0110', + 'decimal' => '00', + 'query_data_packet_length' => '0a0000', + 'query_data_value' => '0474657374', + 'stmt_data_packet_length' => '0c0000', + 'stmt_data_value' => '0474657374' + ], + ]; +} + +function my_mysqli_data_field(string $field): array +{ + $fields = my_mysqli_data_fields(); + if (!isset($fields[$field])) { + throw new Exception("Unknown field $field"); + } + return $fields[$field]; +} + + + +class my_mysqli_fake_packet_item +{ + public function __construct(public string|null $name, public string $value, public bool $is_hex = true) + { + } +} + +class my_mysqli_fake_packet +{ + private array $data = array(); + + public function __get(string $name) + { + foreach ($this->data as $item) { + if ($item->name === $name) { + return $item->value; + } + } + return null; + } + + public function __set(string $name, string|my_mysqli_fake_packet_item $value) + { + if ($value instanceof my_mysqli_fake_packet_item) { + if ($value->name === null) { + $value->name = $name; + } + } else { + $value = new my_mysqli_fake_packet_item($name, $value, true); + } + + for ($i = 0; $i < count($this->data); $i++) { + if ($this->data[$i]->name === $name) { + $this->data[$i] = $value; + return; + } + } + + $this->data[] = $value; + } + + public function to_bytes(): string + { + $bytes = ''; + foreach ($this->data as $item) { + $bytes .= $item->is_hex ? hex2bin($item->value) : $item->value; + } + return $bytes; + } +} + +class my_mysqli_fake_packet_generator +{ + public static function create_packet_item(int|string $value, bool $is_hex = false, string $format = 'v'): my_mysqli_fake_packet_item + { + if (is_string($value)) { + $packed_value = $value; + } else { + $packed_value = pack($format, $value); + } + return new my_mysqli_fake_packet_item(null, $packed_value, $is_hex); + } + + public function server_ok(): my_mysqli_fake_packet + { + $packet = new my_mysqli_fake_packet(); + $packet->packet_length = "070000"; + $packet->packet_number = "02"; + $packet->header = "00"; // OK + $packet->affected_rows = "00"; + $packet->last_insert_id = "00"; + $packet->server_status = "0200"; + $packet->warning_count = "0000"; + return $packet; + } + + public function server_greetings(): my_mysqli_fake_packet + { + $packet = new my_mysqli_fake_packet(); + $packet->packet_length = "580000"; + $packet->packet_number = "00"; + $packet->proto_version = "0a"; + $packet->version = self::create_packet_item('5.5.5-10.5.18-MariaDB' . chr(0)); + $packet->thread_id = "03000000"; + $packet->salt = "473e3f6047257c67"; + $packet->filler = "00"; + $packet->server_capabilities = self::create_packet_item(0b1111011111111110); + $packet->server_character_set = "08"; + $packet->server_status = self::create_packet_item(0b000000000000010); + $packet->extended_server_capabilities = self::create_packet_item(0b1000000111111111); + $packet->auth_plugin = "15"; + $packet->unused = "000000000000"; + $packet->mariadb_extended_server_capabilities = self::create_packet_item(0b1111, false, 'V'); + $packet->mariadb_extended_server_capabilities_salt = "6c6b55463f49335f686c643100"; + $packet->mariadb_extended_server_capabilities_auth_plugin = self::create_packet_item('mysql_native_password'); + + return $packet; + } + + public function server_tabular_query_response(): array + { + $qr1 = new my_mysqli_fake_packet(); + $qr1->packet_length = "010000"; + $qr1->packet_number = "01"; + $qr1->field_count = "01"; + + $qr2 = new my_mysqli_fake_packet(); + $qr2->packet_length = "190000"; + $qr2->packet_number = "02"; + $qr2->catalog_length_plus_name = "0164"; + $qr2->db_length_plus_name = "0164"; + $qr2->table_length_plus_name = "0164"; + $qr2->original_t = "0164"; + $qr2->name_length_plus_name = "0164"; + $qr2->original_n = "0164"; + $qr2->canary = "0c"; + $qr2->charset = "3f00"; + $qr2->length = "0b000000"; + $qr2->type = "03"; + $qr2->flags = "0350"; + $qr2->decimals = "000000"; + + $qr3 = new my_mysqli_fake_packet(); + $qr3->full = "05000003fe00002200"; + + $qr4 = new my_mysqli_fake_packet(); + $qr4->full = "0400000401350174"; + + $qr5 = new my_mysqli_fake_packet(); + $qr5->full = "05000005fe00002200"; + + return [$qr1, $qr2, $qr3, $qr4, $qr5]; + } + + public function server_upsert_query_response(): array + { + $qr1 = new my_mysqli_fake_packet(); + $qr1->packet_length = "010000"; + $qr1->packet_number = "01"; + $qr1->field_count = "00"; // UPSERT + $qr1->affected_rows = "00"; + $qr1->affected_rows = "00"; + $qr1->last_insert_id = "00"; + $qr1->server_status = "0000"; + $qr1->warning_count = "0000"; + $qr1->len = "01"; + $qr1->filename = "65"; + $qr1->packet_length = sprintf("%02x0000", strlen($qr1->to_bytes())-4); + + return [$qr1]; + } + + public function server_stmt_prepare_response_start($num_field): my_mysqli_fake_packet + { + $pr1 = new my_mysqli_fake_packet(); + $pr1->packet_length = "0c0000"; + $pr1->packet_number = "01"; + $pr1->response_code = '00'; // OK + $pr1->statement_id = '01000000'; + $pr1->num_fields = $num_field; + $pr1->num_params = '0000'; + $pr1->filler = '00'; + $pr1->warnings = '0000'; + + return $pr1; + } + + public function server_stmt_prepare_response_end($packer_number): my_mysqli_fake_packet + { + $pr3 = new my_mysqli_fake_packet(); + $pr3->packet_length = "050000"; + $pr3->packet_number = $packer_number; + $pr3->packet_type = 'fe'; // EOF + $pr3->warnings = '0000'; + $pr3->server_status = '0200'; + + return $pr3; + } + + public function server_stmt_prepare_items_response(): array + { + $pr1 = $this->server_stmt_prepare_response_start('0100'); + + $pr2 = new my_mysqli_fake_packet(); + $pr2->packet_length = "300000"; + $pr2->packet_number = "02"; + $pr2->catalogue_len = '03'; + $pr2->catalogue = '646566'; // def + $pr2->db_len = '08'; + $pr2->db = '7068705f74657374'; // php_test + $pr2->table_len = '05'; + $pr2->table = '6974656d73'; // items + $pr2->orig_table_len = '05'; + $pr2->orig_table = '6974656d73'; // items + $pr2->name_len = '04'; + $pr2->name = '6974656d'; + $pr2->orig_name_len = '04'; + $pr2->orig_name = '6974656d'; + $pr2->something = '0c'; + $pr2->charset = 'e000'; + $pr2->length = 'c8000000'; + $pr2->field_type = 'fd'; // FIELD_TYPE_VAR_STRING + $pr2->flags = '0110'; + $pr2->decimal = '00'; + $pr2->padding = '0000'; + + $pr3 = $this->server_stmt_prepare_response_end('03'); + + return [$pr1, $pr2, $pr3]; + } + + public function server_stmt_prepare_data_response_field($packet_number, $field_name): my_mysqli_fake_packet + { + if (strlen($field_name) != 6) { + throw new Exception("Invalid field length - only 6 is allowed"); + } + + $field = my_mysqli_data_field($field_name); + + $pr = new my_mysqli_fake_packet(); + $pr->packet_length = "320000"; + $pr->packet_number = $packet_number; + $pr->catalogue_len = '03'; + $pr->catalogue = bin2hex('def'); + $pr->db_len = '08'; + $pr->db = bin2hex('php_test'); + $pr->table_len = '04'; + $pr->table = bin2hex('data'); + $pr->orig_table_len = '04'; + $pr->orig_table = bin2hex('data'); + $pr->name_len = '06'; + $pr->name = bin2hex($field_name); + $pr->orig_name_len = '06'; + $pr->orig_name = bin2hex($field_name); + $pr->something = '0c'; + $pr->charset = $field['charset']; + $pr->length = $field['length']; + $pr->field_type = $field['type']; + $pr->flags = $field['flags']; + $pr->decimal = $field['decimal']; + $pr->padding = '0000'; + + return $pr; + } + + public function server_stmt_prepare_data_response(string $field_name): array + { + $pr1 = $this->server_stmt_prepare_response_start('0200'); + + $pr2 = $this->server_stmt_prepare_data_response_field('02', 'strval'); + $pr3 = $this->server_stmt_prepare_data_response_field('03', $field_name); + + $pr4 = $this->server_stmt_prepare_response_end('04'); + + return [$pr1, $pr2, $pr3, $pr4]; + } + + public function server_stmt_execute_items_response(): array + { + $pr1 = new my_mysqli_fake_packet(); + $pr1->packet_length = "010000"; + $pr1->packet_number = "01"; + $pr1->num_fields = '01'; + + $pr2 = new my_mysqli_fake_packet(); + $pr2->packet_length = "300000"; + $pr2->packet_number = "02"; + $pr2->catalogue_len = '03'; + $pr2->catalogue = '646566'; // def + $pr2->db_len = '08'; + $pr2->db = '7068705f74657374'; // php_test + $pr2->table_len = '05'; + $pr2->table = '6974656d73'; // items + $pr2->orig_table_len = '05'; + $pr2->orig_table = '6974656d73'; // items + $pr2->name_len = '04'; + $pr2->name = '6974656d'; + $pr2->orig_name_len = '04'; + $pr2->orig_name = '6974656d'; + $pr2->something = '0c'; + $pr2->charset = 'e000'; + $pr2->length = 'c8000000'; + $pr2->field_type = 'fd'; // FIELD_TYPE_VAR_STRING + $pr2->flags = '0110'; + $pr2->decimal = '00'; + $pr2->padding = '0000'; + + $pr3 = new my_mysqli_fake_packet(); + $pr3->packet_length = "050000"; + $pr3->packet_number = "03"; + $pr3->packet_type = 'fe'; // EOF + $pr3->warnings = '0000'; + $pr3->server_status = '2200'; + + $pr4 = new my_mysqli_fake_packet(); + $pr4->packet_length = "070000"; + $pr4->packet_number = "04"; + $pr4->packet_type = '00'; // OK + $pr4->affected_rows = '00'; + $pr4->row_data_len = '04'; + $pr4->row_data = '74657374'; // item + + $pr5 = new my_mysqli_fake_packet(); + $pr5->full = '05000005fe00002200'; + + return [$pr1, $pr2, $pr3, $pr4, $pr5]; + } + + private function server_execute_data_response_start(string $field_name): array + { + $pr1 = new my_mysqli_fake_packet(); + $pr1->packet_length = "010000"; + $pr1->packet_number = "01"; + $pr1->num_fields = '02'; + + $pr2 = new my_mysqli_fake_packet(); + $pr2->packet_length = "320000"; + $pr2->packet_number = "02"; + $pr2->catalogue_len = '03'; + $pr2->catalogue = '646566'; // def + $pr2->db_len = '08'; + $pr2->db = '7068705f74657374'; // php_test + $pr2->table_len = '04'; + $pr2->table = bin2hex('data'); + $pr2->orig_table_len = '04'; + $pr2->orig_table = bin2hex('data'); + $pr2->name_len = '06'; + $pr2->name = bin2hex('strval'); + $pr2->orig_name_len = '06'; + $pr2->orig_name = bin2hex('strval'); + $pr2->something = '0c'; + $pr2->charset = 'e000'; + $pr2->length = 'c8000000'; + $pr2->field_type = 'fd'; // FIELD_TYPE_VAR_STRING + $pr2->flags = '0110'; + $pr2->decimal = '00'; + $pr2->padding = '0000'; + + $field = my_mysqli_data_field($field_name); + + $pr3 = new my_mysqli_fake_packet(); + $pr3->packet_length = "320000"; + $pr3->packet_number = "03"; + $pr3->catalogue_len = '03'; + $pr3->catalogue = '646566'; // def + $pr3->db_len = '08'; + $pr3->db = '7068705f74657374'; // php_test + $pr3->table_len = '04'; + $pr3->table = bin2hex('data'); + $pr3->orig_table_len = '04'; + $pr3->orig_table = bin2hex('data'); + $pr3->name_len = '06'; + $pr3->name = bin2hex($field_name); + $pr3->orig_name_len = '06'; + $pr3->orig_name = bin2hex($field_name); + $pr3->something = '0c'; + $pr3->charset = $field['charset']; + $pr3->length = $field['length']; + $pr3->field_type = $field['type']; + $pr3->flags = $field['flags']; + $pr3->decimal = $field['decimal']; + $pr3->padding = '0000'; + + $pr4 = new my_mysqli_fake_packet(); + $pr4->packet_length = "050000"; + $pr4->packet_number = "04"; + $pr4->packet_type = 'fe'; // EOF + $pr4->warnings = '0000'; + $pr4->server_status = '2200'; + + return [$field, $pr1, $pr2, $pr3, $pr4]; + } + + private function server_execute_data_response_end(): my_mysqli_fake_packet + { + $pr6 = new my_mysqli_fake_packet(); + $pr6->packet_length = '050000'; + $pr6->packet_number = "06"; + $pr6->packet_type = 'fe'; // EOF + $pr6->warnings = '0000'; + $pr6->server_status = '2200'; + + return $pr6; + } + + public function server_stmt_execute_data_response(string $field_name): array + { + [$field, $pr1, $pr2, $pr3, $pr4] = $this->server_execute_data_response_start($field_name); + + $pr5 = new my_mysqli_fake_packet(); + $pr5->packet_length = $field['stmt_data_packet_length']; + $pr5->packet_number = "05"; + $pr5->packet_type = '00'; // OK + $pr5->affected_rows = '00'; + $pr5->row_field1_len = '04'; + $pr5->row_field1_data = '74657374'; // test + $pr5->row_field2 = $field['stmt_data_value']; + + return [$pr1, $pr2, $pr3, $pr4, $pr5, $this->server_execute_data_response_end()]; + } + + public function server_query_execute_data_response(string $field_name): array + { + [$field, $pr1, $pr2, $pr3, $pr4] = $this->server_execute_data_response_start($field_name); + + $pr5 = new my_mysqli_fake_packet(); + $pr5->packet_length = $field['query_data_packet_length']; + $pr5->packet_number = "05"; + $pr5->row_field1_len = '04'; + $pr5->row_field1_data = '74657374'; // test + $pr5->row_field2 = $field['query_data_value']; + + return [$pr1, $pr2, $pr3, $pr4, $pr5, $this->server_execute_data_response_end()]; + } +} + +class my_mysqli_fake_server_conn +{ + private $conn; + public $packet_generator; + + public function __construct($socket) + { + $this->packet_generator = new my_mysqli_fake_packet_generator(); + $this->conn = stream_socket_accept($socket); + if ($this->conn) { + fprintf(STDERR, "[*] Connection established\n"); + } else { + fprintf(STDERR, "[*] Failed to establish connection\n"); + } + } + + public function packets_to_bytes(array $packets): string + { + return implode('', array_map(fn($s) => $s->to_bytes(), $packets)); + } + + public function send($payload, $message = null): void + { + if ($message) { + fprintf(STDERR, "[*] Sending - %s: %s\n", $message, bin2hex($payload)); + } + fwrite($this->conn, $payload); + } + + public function read($bytes_len = 1024) + { + // wait 10ms to fill the buffer + usleep(10000); + $data = fread($this->conn, $bytes_len); + if ($data) { + fprintf(STDERR, "[*] Received: %s\n", bin2hex($data)); + } + } + + public function close() + { + fclose($this->conn); + } + + public function send_server_greetings() + { + $this->send($this->packet_generator->server_greetings()->to_bytes(), "Server Greeting"); + } + + public function send_server_ok() + { + $this->send($this->packet_generator->server_ok()->to_bytes(), "Server OK"); + } + + public function send_server_tabular_query_response(): void + { + $packets = $this->packet_generator->server_tabular_query_response(); + $this->send($this->packets_to_bytes($packets), "Tabular response"); + } + + public function send_server_stmt_prepare_items_response(): void + { + $packets = $this->packet_generator->server_stmt_prepare_items_response(); + $this->send($this->packets_to_bytes($packets), "Stmt prepare items"); + } + + + public function send_server_stmt_prepare_data_response(string $field_name): void + { + $packets = $this->packet_generator->server_stmt_prepare_data_response($field_name); + $this->send($this->packets_to_bytes($packets), "Stmt prepare data $field_name"); + } + + public function send_server_stmt_execute_items_response(): void + { + $packets = $this->packet_generator->server_stmt_execute_items_response(); + $this->send($this->packets_to_bytes($packets), "Stmt execute items"); + } + + public function send_server_stmt_execute_data_response(string $field_name): void + { + $packets = $this->packet_generator->server_stmt_execute_data_response($field_name); + $this->send($this->packets_to_bytes($packets), "Stmt execute data $field_name"); + } + + public function send_server_query_execute_data_response(string $field_name): void + { + $packets = $this->packet_generator->server_query_execute_data_response($field_name); + $this->send($this->packets_to_bytes($packets), "Query execute data $field_name"); + } +} + +class my_mysqli_fake_server_process +{ + public function __construct(private $process, private array $pipes) {} + + public function terminate(bool $wait = false) + { + if ($wait) { + $this->wait(); + } + proc_terminate($this->process); + } + + public function wait() + { + echo fgets($this->pipes[1]); + } +} + +function my_mysqli_test_tabular_response_def_over_read(my_mysqli_fake_server_conn $conn): void +{ + $rh = $conn->packet_generator->server_tabular_query_response(); + + // Length of the packet is modified to include the next added data + $rh[1]->packet_length = "1e0000"; + + // We add a length field encoded on 4 bytes which evaluates to 65536. If the process crashes because + // the heap has been overread, lower this value. + $rh[1]->extra_def_size = "fd000001"; # 65536 + + // Filler + $rh[1]->extra_def_data = "aa"; + + $trrh = $conn->packets_to_bytes($rh); + + $conn->send_server_greetings(); + $conn->read(); + $conn->send_server_ok(); + $conn->read(); + $conn->send($trrh, "Malicious Tabular Response [Extract heap through buffer over-read]"); + $conn->read(65536); +} + +function my_mysqli_test_upsert_response_filename_over_read(my_mysqli_fake_server_conn $conn): void +{ + $rh = $conn->packet_generator->server_upsert_query_response(); + + // Set extra length to overread + $rh[0]->len = "fa"; + + $trrh = $conn->packets_to_bytes($rh); + + $conn->send_server_greetings(); + $conn->read(); + $conn->send_server_ok(); + $conn->read(); + $conn->send($trrh, "Malicious Tabular Response [Extract heap through buffer over-read]"); + $conn->read(65536); +} + +function my_mysqli_test_auth_response_message_over_read(my_mysqli_fake_server_conn $conn): void +{ + $p = $conn->packet_generator->server_ok(); + $p->packet_length = "090000"; + $p->message_len = "fcff"; + + $conn->send_server_greetings(); + $conn->read(); + $conn->send($p->to_bytes(), "Malicious OK Auth Response [Extract heap through buffer over-read]"); + $conn->read(); +} + +function my_mysqli_test_stmt_response_row_over_read_string(my_mysqli_fake_server_conn $conn): void +{ + $rh = $conn->packet_generator->server_stmt_execute_items_response(); + + // Set extra length to overread + $rh[3]->row_data_len = "fa"; + + $conn->send_server_greetings(); + $conn->read(); + $conn->send_server_ok(); + $conn->read(); + $conn->send_server_stmt_prepare_items_response(); + $conn->read(); + $conn->send($conn->packets_to_bytes($rh), "Malicious Stmt Response for items [Extract heap through buffer over-read]"); + $conn->read(65536); +} + +function my_mysqli_test_stmt_response_row_over_read_two_fields( + my_mysqli_fake_server_conn $conn, + string $field_name, + string $row_field1_len = '06' +): void { + $rh = $conn->packet_generator->server_stmt_execute_data_response($field_name); + + // Set extra length to overread by two bytes + $rh[4]->row_field1_len = $row_field1_len; + + $conn->send_server_greetings(); + $conn->read(); + $conn->send_server_ok(); + $conn->read(); + $conn->send_server_stmt_prepare_data_response($field_name); + $conn->read(); + $conn->send( + $conn->packets_to_bytes($rh), + "Malicious Stmt Response for data $field_name [Extract heap through buffer over-read]" + ); + $conn->read(65536); +} + +function my_mysqli_test_stmt_response_row_over_read_int(my_mysqli_fake_server_conn $conn): void +{ + my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'intval'); +} + +function my_mysqli_test_stmt_response_row_over_read_float(my_mysqli_fake_server_conn $conn): void +{ + my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'fltval'); +} + +function my_mysqli_test_stmt_response_row_over_read_double(my_mysqli_fake_server_conn $conn): void +{ + my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'dblval'); +} + +function my_mysqli_test_stmt_response_row_over_read_date(my_mysqli_fake_server_conn $conn): void +{ + my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'datval'); +} + +function my_mysqli_test_stmt_response_row_over_read_time(my_mysqli_fake_server_conn $conn): void +{ + my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'timval', '0c'); +} + +function my_mysqli_test_stmt_response_row_over_read_datetime(my_mysqli_fake_server_conn $conn): void +{ + my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'dtival'); +} + +function my_mysqli_test_stmt_response_row_no_space(my_mysqli_fake_server_conn $conn): void +{ + my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'strval', '09'); +} + +function my_mysqli_test_stmt_response_row_over_read_bit(my_mysqli_fake_server_conn $conn): void +{ + my_mysqli_test_stmt_response_row_over_read_two_fields($conn, 'bitval'); +} + +function my_mysqli_test_stmt_response_row_read_two_fields(my_mysqli_fake_server_conn $conn): void +{ + $conn->send_server_greetings(); + $conn->read(); + $conn->send_server_ok(); + $conn->read(); + $field_names = array_keys(my_mysqli_data_fields()); + foreach ($field_names as $field_name) { + $conn->send_server_stmt_prepare_data_response($field_name); + $conn->read(65536); + $conn->send_server_stmt_execute_data_response($field_name); + $conn->read(65536); + } +} + +function my_mysqli_test_query_response_row_length_overflow(my_mysqli_fake_server_conn $conn): void +{ + $rh = $conn->packet_generator->server_query_execute_data_response('strval'); + + // Set extra length to overread by two bytes + $rh[4]->row_field2 = 'fefefefefe'; + + $conn->send_server_greetings(); + $conn->read(); + $conn->send_server_ok(); + $conn->read(); + $conn->send($conn->packets_to_bytes($rh), "Malicious Query Response for data strval field [length overflow]"); + $conn->read(65536); +} + +function my_mysqli_test_query_response_row_read_two_fields(my_mysqli_fake_server_conn $conn): void +{ + $conn->send_server_greetings(); + $conn->read(); + $conn->send_server_ok(); + $conn->read(); + $field_names = array_keys(my_mysqli_data_fields()); + foreach ($field_names as $field_name) { + $conn->send_server_query_execute_data_response($field_name); + $conn->read(); + } +} + +function run_fake_server(string $test_function, $port = 33305): void +{ + $address = '127.0.0.1'; + + $socket = @stream_socket_server("tcp://$address:$port", $errno, $errstr); + if (!$socket) { + die("Failed to create socket: $errstr ($errno)\n"); + } + echo "[*] Server started\n"; + + try { + $conn = new my_mysqli_fake_server_conn($socket); + $test_function_name = 'my_mysqli_test_' . $test_function; + call_user_func($test_function_name, $conn); + $conn->close(); + } catch (Exception $e) { + fprintf(STDERR, "[!] Exception: " . $e->getMessage() . "\n"); + } + + fclose($socket); + + echo "[*] Server finished\n"; +} + + +function run_fake_server_in_background($test_function, $port = 33305): my_mysqli_fake_server_process +{ + $command = [PHP_BINARY, '-n', __FILE__, 'mysqli_fake_server', $test_function, $port]; + + $descriptorspec = array( + 0 => array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => STDERR, + ); + + $process = proc_open($command, $descriptorspec, $pipes); + + if (is_resource($process)) { + return new my_mysqli_fake_server_process($process, $pipes); + } else { + throw new Exception("Failed to start server process"); + } +} + +if (isset($argv) && $argc > 2 && $argv[1] == 'mysqli_fake_server') { + run_fake_server($argv[2], $argv[3] ?? '33305'); +} diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-auth-message.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,38 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - auth message buffer over-read) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +try { + $conn = new mysqli( $servername, $username, $password, "", $port ); + $info = mysqli_info($conn); + var_dump($info); +} catch (Exception $e) { + echo $e->getMessage() . PHP_EOL; +} + +$process->terminate(); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Malicious OK Auth Response [Extract heap through buffer over-read]: 0900000200000002000000fcff + +Warning: mysqli::__construct(): OK packet message length is past the packet size in %s on line %d +Unknown error while trying to connect via tcp://127.0.0.1:50001 +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-def.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,47 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - tabular default) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Running query on the fake server...\n"; + +$result = $conn->query("SELECT * from users"); + +if ($result) { + $all_fields = $result->fetch_fields(); + var_dump($result->fetch_all(MYSQLI_ASSOC)); + var_dump(get_object_vars($all_fields[0])["def"]); +} + +$conn->close(); + +$process->terminate(); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Running query on the fake server... +[*] Received: 140000000353454c454354202a2066726f6d207573657273 +[*] Sending - Malicious Tabular Response [Extract heap through buffer over-read]: 01000001011e0000020164016401640164016401640c3f000b000000030350000000fd000001aa05000003fe00002200040000040135017405000005fe00002200 + +Warning: mysqli::query(): Protocol error. Server sent default for unsupported field list (mysqlnd_wireprotocol.c:%d) in %s on line %d +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-filename.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,43 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - upsert filename buffer over-read) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); +echo "[*] Running query on the fake server...\n"; + +$result = $conn->query("SELECT * from users"); +$info = mysqli_info($conn); + +var_dump($info); + +$process->terminate(); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Running query on the fake server... +[*] Received: 140000000353454c454354202a2066726f6d207573657273 +[*] Sending - Malicious Tabular Response [Extract heap through buffer over-read]: 0900000100000000000000fa65 + +Warning: mysqli::query(): RSET_HEADER packet additional data length is past 249 bytes the packet size in %s on line %d + +Warning: mysqli::query(): Error reading result set's header in %s on line %d +NULL +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-query-len-overflow.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-query-len-overflow.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-query-len-overflow.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-query-len-overflow.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,48 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row no space for the field) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Query the fake server...\n"; +$sql = "SELECT strval, strval FROM data"; + +$result = $conn->query($sql); + +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row['strval']); + } +} +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Query the fake server... +[*] Received: 200000000353454c4543542073747276616c2c2073747276616c2046524f4d2064617461 +[*] Sending - Malicious Query Response for data strval field [length overflow]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe000022000a0000050474657374fefefefefe05000006fe00002200 + +Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after end of packet in %s on line %d +[*] Received: 0100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-bit.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-bit.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-bit.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-bit.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row bit buffer over-read) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Preparing statement on the fake server...\n"; +$stmt = $conn->prepare("SELECT bitval, timval FROM data"); + +$stmt->execute(); +$result = $stmt->get_result(); + +// Fetch and display the results +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row["bitval"]); + } +} +$stmt->close(); +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Preparing statement on the fake server... +[*] Received: 200000001653454c4543542062697476616c2c2074696d76616c2046524f4d2064617461 +[*] Sending - Stmt prepare data bitval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610662697476616c0662697476616c0c3f004000000010211000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Malicious Stmt Response for data bitval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610662697476616c0662697476616c0c3f004000000010211000000005000004fe00002200100000050000067465737408080808080808080805000006fe00002200 + +Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d +[*] Received: 0500000019010000000100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-date.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-date.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-date.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-date.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row date buffer over-read) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Preparing statement on the fake server...\n"; +$stmt = $conn->prepare("SELECT strval, datval FROM data"); + +$stmt->execute(); +$result = $stmt->get_result(); + +// Fetch and display the results +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row["datval"]); + } +} +$stmt->close(); +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Preparing statement on the fake server... +[*] Received: 200000001653454c4543542073747276616c2c2064617476616c2046524f4d2064617461 +[*] Sending - Stmt prepare data datval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664617476616c0664617476616c0c3f000a0000000a811000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Malicious Stmt Response for data datval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664617476616c0664617476616c0c3f000a0000000a811000000005000004fe000022000c0000050000067465737404de070c0f05000006fe00002200 + +Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d +[*] Received: 0500000019010000000100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-datetime.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-datetime.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-datetime.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-datetime.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row datetime buffer over-read) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Preparing statement on the fake server...\n"; +$stmt = $conn->prepare("SELECT strval, dtival FROM data"); + +$stmt->execute(); +$result = $stmt->get_result(); + +// Fetch and display the results +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row["dtival"]); + } +} +$stmt->close(); +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Preparing statement on the fake server... +[*] Received: 200000001653454c4543542073747276616c2c2064746976616c2046524f4d2064617461 +[*] Sending - Stmt prepare data dtival: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664746976616c0664746976616c0c3f00130000000c811000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Malicious Stmt Response for data dtival [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664746976616c0664746976616c0c3f00130000000c811000000005000004fe000022000f0000050000067465737407de070c100d000105000006fe00002200 + +Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d +[*] Received: 0500000019010000000100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-double.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-double.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-double.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-double.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row double buffer over-read) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Preparing statement on the fake server...\n"; +$stmt = $conn->prepare("SELECT strval, dblval FROM data"); + +$stmt->execute(); +$result = $stmt->get_result(); + +// Fetch and display the results +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row["dblval"]); + } +} +$stmt->close(); +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Preparing statement on the fake server... +[*] Received: 200000001653454c4543542073747276616c2c2064626c76616c2046524f4d2064617461 +[*] Sending - Stmt prepare data dblval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664626c76616c0664626c76616c0c3f00160000000501101f000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Malicious Stmt Response for data dblval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664626c76616c0664626c76616c0c3f00160000000501101f000005000004fe000022000f00000500000674657374333333333333f33f05000006fe00002200 + +Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d +[*] Received: 0500000019010000000100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-float.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-float.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-float.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-float.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row int buffer over-read) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Preparing statement on the fake server...\n"; +$stmt = $conn->prepare("SELECT strval, fltval FROM data"); + +$stmt->execute(); +$result = $stmt->get_result(); + +// Fetch and display the results +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row["fltval"]); + } +} +$stmt->close(); +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Preparing statement on the fake server... +[*] Received: 200000001653454c4543542073747276616c2c20666c7476616c2046524f4d2064617461 +[*] Sending - Stmt prepare data fltval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106666c7476616c06666c7476616c0c3f000c0000000401101f000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Malicious Stmt Response for data fltval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106666c7476616c06666c7476616c0c3f000c0000000401101f000005000004fe000022000b000005000006746573743333134005000006fe00002200 + +Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d +[*] Received: 0500000019010000000100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-int.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-int.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-int.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-int.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row int buffer over-read) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Preparing statement on the fake server...\n"; +$stmt = $conn->prepare("SELECT strval, intval FROM data"); + +$stmt->execute(); +$result = $stmt->get_result(); + +// Fetch and display the results +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row["intval"]); + } +} +$stmt->close(); +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Preparing statement on the fake server... +[*] Received: 200000001653454c4543542073747276616c2c20696e7476616c2046524f4d2064617461 +[*] Sending - Stmt prepare data intval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106696e7476616c06696e7476616c0c3f000b00000003011000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Malicious Stmt Response for data intval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106696e7476616c06696e7476616c0c3f000b00000003011000000005000004fe000022000b000005000006746573740e00000005000006fe00002200 + +Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d +[*] Received: 0500000019010000000100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-no-space.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-no-space.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-no-space.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-no-space.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row no space for the field) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Preparing statement on the fake server...\n"; +$stmt = $conn->prepare("SELECT strval, strval FROM data"); + +$stmt->execute(); +$result = $stmt->get_result(); + +// Fetch and display the results +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row["strval"]); + } +} +$stmt->close(); +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Preparing statement on the fake server... +[*] Received: 200000001653454c4543542073747276616c2c2073747276616c2046524f4d2064617461 +[*] Sending - Stmt prepare data strval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Malicious Stmt Response for data strval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe000022000c00000500000974657374047465737405000006fe00002200 + +Warning: mysqli_result::fetch_assoc(): Malformed server packet. No packet space left for the field in %s on line %d +[*] Received: 0500000019010000000100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-string.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-string.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-string.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-string.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row string buffer over-read) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Preparing statement on the fake server...\n"; +$stmt = $conn->prepare("SELECT item FROM items"); + +$stmt->execute(); +$result = $stmt->get_result(); + +// Fetch and display the results +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row["item"]); + } +} +$stmt->close(); +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Preparing statement on the fake server... +[*] Received: 170000001653454c454354206974656d2046524f4d206974656d73 +[*] Sending - Stmt prepare items: 0c0000010001000000010000000000003000000203646566087068705f74657374056974656d73056974656d73046974656d046974656d0ce000c8000000fd011000000005000003fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Malicious Stmt Response for items [Extract heap through buffer over-read]: 01000001013000000203646566087068705f74657374056974656d73056974656d73046974656d046974656d0ce000c8000000fd011000000005000003fe00002200070000040000fa7465737405000005fe00002200 + +Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d +[*] Received: 0500000019010000000100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-time.phpt php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-time.phpt --- php8.2-8.2.24/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-time.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/ghsa-h35g-vwh6-m678-stmt-row-time.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GHSA-h35g-vwh6-m678 (mysqlnd leaks partial content of the heap - stmt row time buffer over-read) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +echo "[*] Preparing statement on the fake server...\n"; +$stmt = $conn->prepare("SELECT strval, timval FROM data"); + +$stmt->execute(); +$result = $stmt->get_result(); + +// Fetch and display the results +if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row["timval"]); + } +} +$stmt->close(); +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Preparing statement on the fake server... +[*] Received: 200000001653454c4543542073747276616c2c2074696d76616c2046524f4d2064617461 +[*] Sending - Stmt prepare data timval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610674696d76616c0674696d76616c0c3f000a0000000b811000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Malicious Stmt Response for data timval [Extract heap through buffer over-read]: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610674696d76616c0674696d76616c0c3f000a0000000b811000000005000004fe000022001000000500000c7465737408000000000015080105000006fe00002200 + +Warning: mysqli_result::fetch_assoc(): Malformed server packet. Field length pointing after the end of packet in %s on line %d +[*] Received: 0500000019010000000100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/protocol_query_row_fetch_data.phpt php8.2-8.2.26/ext/mysqli/tests/protocol_query_row_fetch_data.phpt --- php8.2-8.2.24/ext/mysqli/tests/protocol_query_row_fetch_data.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/protocol_query_row_fetch_data.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,74 @@ +--TEST-- +MySQL protocol - statement row data fetch) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +function my_query($conn, $field) +{ + $sql = "SELECT strval, $field FROM data"; + + $result = $conn->query($sql); + + if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row[$field]); + } + } +} + +foreach (my_mysqli_data_fields() as $field_name => $field) { + my_query($conn, $field_name); +} + +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECT-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Received: 200000000353454c4543542073747276616c2c20696e7476616c2046524f4d2064617461 +[*] Sending - Query execute data intval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106696e7476616c06696e7476616c0c3f000b00000003011000000005000004fe0000220008000005047465737402313405000006fe00002200 +string(2) "14" +[*] Received: 200000000353454c4543542073747276616c2c20666c7476616c2046524f4d2064617461 +[*] Sending - Query execute data fltval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106666c7476616c06666c7476616c0c3f000c0000000401101f000005000004fe0000220009000005047465737403322e3305000006fe00002200 +string(3) "2.3" +[*] Received: 200000000353454c4543542073747276616c2c2064626c76616c2046524f4d2064617461 +[*] Sending - Query execute data dblval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664626c76616c0664626c76616c0c3f00160000000501101f000005000004fe0000220009000005047465737403312e3205000006fe00002200 +string(3) "1.2" +[*] Received: 200000000353454c4543542073747276616c2c2064617476616c2046524f4d2064617461 +[*] Sending - Query execute data datval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664617476616c0664617476616c0c3f000a0000000a811000000005000004fe000022001000000504746573740a323031342d31322d313505000006fe00002200 +string(10) "2014-12-15" +[*] Received: 200000000353454c4543542073747276616c2c2074696d76616c2046524f4d2064617461 +[*] Sending - Query execute data timval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610674696d76616c0674696d76616c0c3f000a0000000b811000000005000004fe000022000e00000504746573740831333a30303a303205000006fe00002200 +string(8) "13:00:02" +[*] Received: 200000000353454c4543542073747276616c2c2064746976616c2046524f4d2064617461 +[*] Sending - Query execute data dtival: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664746976616c0664746976616c0c3f00130000000c811000000005000004fe0000220019000005047465737413323031342d31322d31362031333a30303a303105000006fe00002200 +string(19) "2014-12-16 13:00:01" +[*] Received: 200000000353454c4543542073747276616c2c2062697476616c2046524f4d2064617461 +[*] Sending - Query execute data bitval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610662697476616c0662697476616c0c3f004000000010211000000005000004fe000022000e000005047465737408080808080808080805000006fe00002200 +string(18) "578721382704613384" +[*] Received: 200000000353454c4543542073747276616c2c2073747276616c2046524f4d2064617461 +[*] Sending - Query execute data strval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe000022000a0000050474657374047465737405000006fe00002200 +string(4) "test" +[*] Received: 0100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqli/tests/protocol_stmt_row_fetch_data.phpt php8.2-8.2.26/ext/mysqli/tests/protocol_stmt_row_fetch_data.phpt --- php8.2-8.2.24/ext/mysqli/tests/protocol_stmt_row_fetch_data.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/mysqli/tests/protocol_stmt_row_fetch_data.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,91 @@ +--TEST-- +MySQL protocol - statement row data fetch) +--EXTENSIONS-- +mysqli +--FILE-- +wait(); + +$conn = new mysqli($servername, $username, $password, "", $port); + +function my_query($conn, $field) +{ + $stmt = $conn->prepare("SELECT strval, $field FROM data"); + + $stmt->execute(); + $result = $stmt->get_result(); + + if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + var_dump($row[$field]); + } + } +} + +foreach (my_mysqli_data_fields() as $field_name => $field) { + my_query($conn, $field_name); +} + +$conn->close(); + +$process->terminate(true); + +print "done!"; +?> +--EXPECTF-- +[*] Server started +[*] Connection established +[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264 +[*] Received: 6900000185a21a00000000c0080000000000000000000000000000000000000000000000726f6f7400006d7973716c5f6e61746976655f70617373776f7264002c0c5f636c69656e745f6e616d65076d7973716c6e640c5f7365727665725f686f7374093132372e302e302e31 +[*] Sending - Server OK: 0700000200000002000000 +[*] Received: 200000001653454c4543542073747276616c2c20696e7476616c2046524f4d2064617461 +[*] Sending - Stmt prepare data intval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106696e7476616c06696e7476616c0c3f000b00000003011000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Stmt execute data intval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106696e7476616c06696e7476616c0c3f000b00000003011000000005000004fe000022000b000005000004746573740e00000005000006fe00002200 +int(14) +[*] Received: 050000001901000000200000001653454c4543542073747276616c2c20666c7476616c2046524f4d2064617461 +[*] Sending - Stmt prepare data fltval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106666c7476616c06666c7476616c0c3f000c0000000401101f000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Stmt execute data fltval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f746573740464617461046461746106666c7476616c06666c7476616c0c3f000c0000000401101f000005000004fe000022000b000005000004746573743333134005000006fe00002200 +float(2.3) +[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2064626c76616c2046524f4d2064617461 +[*] Sending - Stmt prepare data dblval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664626c76616c0664626c76616c0c3f00160000000501101f000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Stmt execute data dblval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664626c76616c0664626c76616c0c3f00160000000501101f000005000004fe000022000f00000500000474657374333333333333f33f05000006fe00002200 +float(1.2) +[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2064617476616c2046524f4d2064617461 +[*] Sending - Stmt prepare data datval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664617476616c0664617476616c0c3f000a0000000a811000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Stmt execute data datval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664617476616c0664617476616c0c3f000a0000000a811000000005000004fe000022000c0000050000047465737404de070c0f05000006fe00002200 +string(10) "2014-12-15" +[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2074696d76616c2046524f4d2064617461 +[*] Sending - Stmt prepare data timval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610674696d76616c0674696d76616c0c3f000a0000000b811000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Stmt execute data timval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610674696d76616c0674696d76616c0c3f000a0000000b811000000005000004fe00002200100000050000047465737408000000000015080105000006fe00002200 +string(8) "21:08:01" +[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2064746976616c2046524f4d2064617461 +[*] Sending - Stmt prepare data dtival: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664746976616c0664746976616c0c3f00130000000c811000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Stmt execute data dtival: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610664746976616c0664746976616c0c3f00130000000c811000000005000004fe000022000f0000050000047465737407de070c100d000105000006fe00002200 +string(19) "2014-12-16 13:00:01" +[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2062697476616c2046524f4d2064617461 +[*] Sending - Stmt prepare data bitval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610662697476616c0662697476616c0c3f004000000010211000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Stmt execute data bitval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610662697476616c0662697476616c0c3f004000000010211000000005000004fe00002200100000050000047465737408080808080808080805000006fe00002200 +%s578721382704613384%s +[*] Received: 050000001901000000200000001653454c4543542073747276616c2c2073747276616c2046524f4d2064617461 +[*] Sending - Stmt prepare data strval: 0c0000010001000000020000000000003200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe00000200 +[*] Received: 0a00000017010000000001000000 +[*] Sending - Stmt execute data strval: 01000001023200000203646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd01100000003200000303646566087068705f74657374046461746104646174610673747276616c0673747276616c0ce000c8000000fd011000000005000004fe000022000c00000500000474657374047465737405000006fe00002200 +string(4) "test" +[*] Received: 0500000019010000000100000001 +[*] Server finished +done! diff -Nru php8.2-8.2.24/ext/mysqlnd/mysqlnd_ps_codec.c php8.2-8.2.26/ext/mysqlnd/mysqlnd_ps_codec.c --- php8.2-8.2.24/ext/mysqlnd/mysqlnd_ps_codec.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/mysqlnd/mysqlnd_ps_codec.c 2024-11-19 17:11:09.000000000 +0000 @@ -50,11 +50,46 @@ #define MYSQLND_PS_SKIP_RESULT_W_LEN -1 #define MYSQLND_PS_SKIP_RESULT_STR -2 +static inline void ps_fetch_over_read_error(const zend_uchar ** row) +{ + php_error_docref(NULL, E_WARNING, "Malformed server packet. Field length pointing after the end of packet"); + *row = NULL; +} + +static inline bool ps_fetch_is_packet_over_read_with_variable_length(const unsigned int pack_len, + const zend_uchar ** row, const zend_uchar *p, unsigned int length) +{ + if (pack_len == 0) { + return false; + } + size_t length_len = *row - p; + if (length_len > pack_len || length > pack_len - length_len) { + ps_fetch_over_read_error(row); + return true; + } + return false; +} + +static inline bool ps_fetch_is_packet_over_read_with_static_length(const unsigned int pack_len, + const zend_uchar ** row, unsigned int length) +{ + if (pack_len > 0 && length > pack_len) { + ps_fetch_over_read_error(row); + return true; + } + return false; +} + + /* {{{ ps_fetch_from_1_to_8_bytes */ void ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row, unsigned int byte_count) { + if (UNEXPECTED(ps_fetch_is_packet_over_read_with_static_length(pack_len, row, byte_count))) { + return; + } + bool is_bit = field->type == MYSQL_TYPE_BIT; DBG_ENTER("ps_fetch_from_1_to_8_bytes"); DBG_INF_FMT("zv=%p byte_count=%u", zv, byte_count); @@ -174,6 +209,11 @@ float fval; double dval; DBG_ENTER("ps_fetch_float"); + + if (UNEXPECTED(ps_fetch_is_packet_over_read_with_static_length(pack_len, row, 4))) { + return; + } + float4get(fval, *row); (*row)+= 4; DBG_INF_FMT("value=%f", fval); @@ -196,6 +236,11 @@ { double value; DBG_ENTER("ps_fetch_double"); + + if (UNEXPECTED(ps_fetch_is_packet_over_read_with_static_length(pack_len, row, 8))) { + return; + } + float8get(value, *row); ZVAL_DOUBLE(zv, value); (*row)+= 8; @@ -211,9 +256,14 @@ { struct st_mysqlnd_time t; zend_ulong length; /* First byte encodes the length */ + const zend_uchar *p = *row; DBG_ENTER("ps_fetch_time"); if ((length = php_mysqlnd_net_field_length(row))) { + if (UNEXPECTED(ps_fetch_is_packet_over_read_with_variable_length(pack_len, row, p, length))) { + return; + } + const zend_uchar * to = *row; t.time_type = MYSQLND_TIMESTAMP_TIME; @@ -256,9 +306,14 @@ { struct st_mysqlnd_time t = {0}; zend_ulong length; /* First byte encodes the length*/ + const zend_uchar *p = *row; DBG_ENTER("ps_fetch_date"); if ((length = php_mysqlnd_net_field_length(row))) { + if (UNEXPECTED(ps_fetch_is_packet_over_read_with_variable_length(pack_len, row, p, length))) { + return; + } + const zend_uchar * to = *row; t.time_type = MYSQLND_TIMESTAMP_DATE; @@ -288,9 +343,14 @@ { struct st_mysqlnd_time t; zend_ulong length; /* First byte encodes the length*/ + const zend_uchar *p = *row; DBG_ENTER("ps_fetch_datetime"); if ((length = php_mysqlnd_net_field_length(row))) { + if (UNEXPECTED(ps_fetch_is_packet_over_read_with_variable_length(pack_len, row, p, length))) { + return; + } + const zend_uchar * to = *row; t.time_type = MYSQLND_TIMESTAMP_DATETIME; @@ -332,7 +392,11 @@ static void ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row) { + const zend_uchar *p = *row; const zend_ulong length = php_mysqlnd_net_field_length(row); + if (UNEXPECTED(ps_fetch_is_packet_over_read_with_variable_length(pack_len, row, p, length))) { + return; + } DBG_ENTER("ps_fetch_string"); DBG_INF_FMT("len = " ZEND_ULONG_FMT, length); DBG_INF("copying from the row buffer"); @@ -348,7 +412,11 @@ static void ps_fetch_bit(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row) { + const zend_uchar *p = *row; const zend_ulong length = php_mysqlnd_net_field_length(row); + if (UNEXPECTED(ps_fetch_is_packet_over_read_with_variable_length(pack_len, row, p, length))) { + return; + } ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, length); } /* }}} */ diff -Nru php8.2-8.2.24/ext/mysqlnd/mysqlnd_wireprotocol.c php8.2-8.2.26/ext/mysqlnd/mysqlnd_wireprotocol.c --- php8.2-8.2.24/ext/mysqlnd/mysqlnd_wireprotocol.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/mysqlnd/mysqlnd_wireprotocol.c 2024-11-19 17:11:09.000000000 +0000 @@ -447,8 +447,31 @@ if (packet->server_capabilities & CLIENT_PLUGIN_AUTH) { BAIL_IF_NO_MORE_DATA; /* The server is 5.5.x and supports authentication plugins */ - packet->auth_protocol = estrdup((char *)p); - p+= strlen(packet->auth_protocol) + 1; /* eat the '\0' */ + size_t remaining_size = packet->header.size - (size_t)(p - buf); + if (remaining_size == 0) { + /* Might be better to fail but this will fail anyway */ + packet->auth_protocol = estrdup(""); + } else { + /* Check if NUL present */ + char *null_terminator = memchr(p, '\0', remaining_size); + size_t auth_protocol_len; + if (null_terminator) { + /* If present, do basically estrdup */ + auth_protocol_len = null_terminator - (char *)p; + } else { + /* If not present, copy the rest of the buffer */ + auth_protocol_len = remaining_size; + } + char *auth_protocol = emalloc(auth_protocol_len + 1); + memcpy(auth_protocol, p, auth_protocol_len); + auth_protocol[auth_protocol_len] = '\0'; + packet->auth_protocol = auth_protocol; + + p += auth_protocol_len; + if (null_terminator) { + p++; + } + } } DBG_INF_FMT("proto=%u server=%s thread_id=%u", @@ -721,7 +744,14 @@ /* There is a message */ if (packet->header.size > (size_t) (p - buf) && (net_len = php_mysqlnd_net_field_length(&p))) { - packet->message_len = MIN(net_len, buf_len - (p - begin)); + /* p can get past packet size when getting field length so it needs to be checked first + * and after that it can be checked that the net_len is not greater than the packet size */ + if ((p - buf) > packet->header.size || packet->header.size - (p - buf) < net_len) { + DBG_ERR_FMT("OK packet message length is past the packet size"); + php_error_docref(NULL, E_WARNING, "OK packet message length is past the packet size"); + DBG_RETURN(FAIL); + } + packet->message_len = net_len; packet->message = mnd_pestrndup((char *)p, packet->message_len, FALSE); } else { packet->message = NULL; @@ -1105,6 +1135,17 @@ BAIL_IF_NO_MORE_DATA; /* Check for additional textual data */ if (packet->header.size > (size_t) (p - buf) && (len = php_mysqlnd_net_field_length(&p))) { + /* p can get past packet size when getting field length so it needs to be checked first + * and after that it can be checked that the len is not greater than the packet size */ + if ((p - buf) > packet->header.size || packet->header.size - (p - buf) < len) { + size_t local_file_name_over_read = ((p - buf) - packet->header.size) + len; + DBG_ERR_FMT("RSET_HEADER packet additional data length is past %zu bytes the packet size", + local_file_name_over_read); + php_error_docref(NULL, E_WARNING, + "RSET_HEADER packet additional data length is past %zu bytes the packet size", + local_file_name_over_read); + DBG_RETURN(FAIL); + } packet->info_or_local_file.s = mnd_emalloc(len + 1); memcpy(packet->info_or_local_file.s, p, len); packet->info_or_local_file.s[len] = '\0'; @@ -1255,23 +1296,16 @@ meta->flags |= NUM_FLAG; } - - /* - def could be empty, thus don't allocate on the root. - NULL_LENGTH (0xFB) comes from COM_FIELD_LIST when the default value is NULL. - Otherwise the string is length encoded. - */ + /* COM_FIELD_LIST is no longer supported so def should not be present */ if (packet->header.size > (size_t) (p - buf) && (len = php_mysqlnd_net_field_length(&p)) && len != MYSQLND_NULL_LENGTH) { - BAIL_IF_NO_MORE_DATA; - DBG_INF_FMT("Def found, length " ZEND_ULONG_FMT, len); - meta->def = packet->memory_pool->get_chunk(packet->memory_pool, len + 1); - memcpy(meta->def, p, len); - meta->def[len] = '\0'; - meta->def_length = len; - p += len; + DBG_ERR_FMT("Protocol error. Server sent default for unsupported field list"); + php_error_docref(NULL, E_WARNING, + "Protocol error. Server sent default for unsupported field list (mysqlnd_wireprotocol.c:%u)", + __LINE__); + DBG_RETURN(FAIL); } root_ptr = meta->root = packet->memory_pool->get_chunk(packet->memory_pool, total_len); @@ -1434,8 +1468,10 @@ const unsigned int field_count, const MYSQLND_FIELD * const fields_metadata, const bool as_int_or_float, MYSQLND_STATS * const stats) { - unsigned int i; - const zend_uchar * p = row_buffer->ptr; + unsigned int i, j; + size_t rbs = row_buffer->size; + const zend_uchar * rbp = row_buffer->ptr; + const zend_uchar * p = rbp; const zend_uchar * null_ptr; zend_uchar bit; zval *current_field, *end_field, *start_field; @@ -1468,7 +1504,21 @@ statistic = STAT_BINARY_TYPE_FETCHED_NULL; } else { enum_mysqlnd_field_types type = fields_metadata[i].type; - mysqlnd_ps_fetch_functions[type].func(current_field, &fields_metadata[i], 0, &p); + size_t row_position = p - rbp; + if (rbs <= row_position) { + for (j = 0, current_field = start_field; j < i; current_field++, j++) { + zval_ptr_dtor(current_field); + } + php_error_docref(NULL, E_WARNING, "Malformed server packet. No packet space left for the field"); + DBG_RETURN(FAIL); + } + mysqlnd_ps_fetch_functions[type].func(current_field, &fields_metadata[i], rbs - row_position, &p); + if (p == NULL) { + for (j = 0, current_field = start_field; j < i; current_field++, j++) { + zval_ptr_dtor(current_field); + } + DBG_RETURN(FAIL); + } if (MYSQLND_G(collect_statistics)) { switch (fields_metadata[i].type) { @@ -1525,7 +1575,7 @@ unsigned int field_count, const MYSQLND_FIELD * fields_metadata, bool as_int_or_float, MYSQLND_STATS * stats) { - unsigned int i; + unsigned int i, j; zval *current_field, *end_field, *start_field; zend_uchar * p = row_buffer->ptr; const size_t data_size = row_buffer->size; @@ -1546,9 +1596,11 @@ /* NULL or NOT NULL, this is the question! */ if (len == MYSQLND_NULL_LENGTH) { ZVAL_NULL(current_field); - } else if ((p + len) > packet_end) { - php_error_docref(NULL, E_WARNING, "Malformed server packet. Field length pointing %zu" - " bytes after end of packet", (p + len) - packet_end - 1); + } else if (p > packet_end || len > packet_end - p) { + php_error_docref(NULL, E_WARNING, "Malformed server packet. Field length pointing after end of packet"); + for (j = 0, current_field = start_field; j < i; current_field++, j++) { + zval_ptr_dtor(current_field); + } DBG_RETURN(FAIL); } else { struct st_mysqlnd_perm_bind perm_bind = diff -Nru php8.2-8.2.24/ext/opcache/jit/zend_jit.c php8.2-8.2.26/ext/opcache/jit/zend_jit.c --- php8.2-8.2.24/ext/opcache/jit/zend_jit.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/opcache/jit/zend_jit.c 2024-11-19 17:11:09.000000000 +0000 @@ -4190,16 +4190,19 @@ } } -static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, const zend_op *rt_opline) +static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, const zend_op *rt_opline, uint8_t trigger) { zend_ssa ssa; void *checkpoint; zend_func_info *func_info; + uint8_t orig_trigger; if (*dasm_ptr == dasm_end) { return FAILURE; } + orig_trigger = JIT_G(trigger); + JIT_G(trigger) = trigger; checkpoint = zend_arena_checkpoint(CG(arena)); /* Build SSA */ @@ -4232,11 +4235,13 @@ zend_jit_cleanup_func_info(op_array); zend_arena_release(&CG(arena), checkpoint); + JIT_G(trigger) = orig_trigger; return SUCCESS; jit_failure: zend_jit_cleanup_func_info(op_array); zend_arena_release(&CG(arena), checkpoint); + JIT_G(trigger) = orig_trigger; return FAILURE; } @@ -4267,7 +4272,7 @@ opline->handler = jit_extension->orig_handler; /* perform real JIT for this function */ - zend_real_jit_func(op_array, NULL, NULL); + zend_real_jit_func(op_array, NULL, NULL, ZEND_JIT_ON_FIRST_EXEC); } zend_catch { do_bailout = true; } zend_end_try(); @@ -4313,7 +4318,7 @@ jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array); opline->handler = jit_extension->orig_handler; if (((double)counter / (double)zend_jit_profile_counter) > JIT_G(prof_threshold)) { - zend_real_jit_func(op_array, NULL, NULL); + zend_real_jit_func(op_array, NULL, NULL, ZEND_JIT_ON_PROF_REQUEST); } } } ZEND_HASH_FOREACH_END(); @@ -4339,7 +4344,7 @@ } /* perform real JIT for this function */ - zend_real_jit_func(op_array, NULL, opline); + zend_real_jit_func(op_array, NULL, opline, ZEND_JIT_ON_HOT_COUNTERS); } zend_catch { do_bailout = 1; } zend_end_try(); @@ -4507,7 +4512,7 @@ } else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) { return zend_jit_setup_hot_trace_counters(op_array); } else if (JIT_G(trigger) == ZEND_JIT_ON_SCRIPT_LOAD) { - return zend_real_jit_func(op_array, script, NULL); + return zend_real_jit_func(op_array, script, NULL, ZEND_JIT_ON_SCRIPT_LOAD); } else { ZEND_UNREACHABLE(); } diff -Nru php8.2-8.2.24/ext/opcache/jit/zend_jit_arm64.dasc php8.2-8.2.26/ext/opcache/jit/zend_jit_arm64.dasc --- php8.2-8.2.24/ext/opcache/jit/zend_jit_arm64.dasc 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/opcache/jit/zend_jit_arm64.dasc 2024-11-19 17:11:09.000000000 +0000 @@ -13829,7 +13829,9 @@ static int zend_jit_fetch_this(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, bool check_only) { - if (!op_array->scope || (op_array->fn_flags & ZEND_ACC_STATIC)) { + if (!op_array->scope || + (op_array->fn_flags & ZEND_ACC_STATIC) || + ((op_array->fn_flags & (ZEND_ACC_CLOSURE|ZEND_ACC_IMMUTABLE)) == ZEND_ACC_CLOSURE)) { if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) { if (!JIT_G(current_frame) || !TRACE_FRAME_IS_THIS_CHECKED(JIT_G(current_frame))) { diff -Nru php8.2-8.2.24/ext/opcache/jit/zend_jit_helpers.c php8.2-8.2.26/ext/opcache/jit/zend_jit_helpers.c --- php8.2-8.2.24/ext/opcache/jit/zend_jit_helpers.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/opcache/jit/zend_jit_helpers.c 2024-11-19 17:11:09.000000000 +0000 @@ -1828,6 +1828,12 @@ static void ZEND_FASTCALL zend_jit_verify_return_slow(zval *arg, const zend_op_array *op_array, zend_arg_info *arg_info, void **cache_slot) { + if (Z_TYPE_P(arg) == IS_NULL) { + ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type)); + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(arg_info->type, IS_NULL))) { + return; + } + } if (UNEXPECTED(!zend_check_user_type_slow( &arg_info->type, arg, /* ref */ NULL, cache_slot, /* is_return_type */ true))) { zend_verify_return_error((zend_function*)op_array, arg); diff -Nru php8.2-8.2.24/ext/opcache/jit/zend_jit_trace.c php8.2-8.2.26/ext/opcache/jit/zend_jit_trace.c --- php8.2-8.2.24/ext/opcache/jit/zend_jit_trace.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/opcache/jit/zend_jit_trace.c 2024-11-19 17:11:09.000000000 +0000 @@ -1247,7 +1247,8 @@ } } else if (p->op == ZEND_JIT_TRACE_DO_ICALL) { if (JIT_G(opt_level) < ZEND_JIT_LEVEL_OPT_FUNC) { - if (p->func != (zend_function*)&zend_pass_function + if (p->func + && p->func != (zend_function*)&zend_pass_function && (zend_string_equals_literal(p->func->common.function_name, "extract") || zend_string_equals_literal(p->func->common.function_name, "compact") || zend_string_equals_literal(p->func->common.function_name, "get_defined_vars"))) { @@ -6221,7 +6222,7 @@ goto jit_failure; } if ((p+1)->op == ZEND_JIT_TRACE_INIT_CALL && (p+1)->func) { - if (opline->opcode == ZEND_NEW && ssa_op->result_def >= 0) { + if (opline->opcode == ZEND_NEW && opline->result_type != IS_UNUSED) { SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_OBJECT, 1); } if (zend_jit_may_be_polymorphic_call(opline) || diff -Nru php8.2-8.2.24/ext/opcache/jit/zend_jit_x86.dasc php8.2-8.2.26/ext/opcache/jit/zend_jit_x86.dasc --- php8.2-8.2.24/ext/opcache/jit/zend_jit_x86.dasc 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/opcache/jit/zend_jit_x86.dasc 2024-11-19 17:11:09.000000000 +0000 @@ -14749,7 +14749,9 @@ static int zend_jit_fetch_this(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, bool check_only) { - if (!op_array->scope || (op_array->fn_flags & ZEND_ACC_STATIC)) { + if (!op_array->scope || + (op_array->fn_flags & ZEND_ACC_STATIC) || + ((op_array->fn_flags & (ZEND_ACC_CLOSURE|ZEND_ACC_IMMUTABLE)) == ZEND_ACC_CLOSURE)) { if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) { if (!JIT_G(current_frame) || !TRACE_FRAME_IS_THIS_CHECKED(JIT_G(current_frame))) { diff -Nru php8.2-8.2.24/ext/opcache/tests/jit/gh15973.phpt php8.2-8.2.26/ext/opcache/tests/jit/gh15973.phpt --- php8.2-8.2.24/ext/opcache/tests/jit/gh15973.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/opcache/tests/jit/gh15973.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,24 @@ +--TEST-- +GH-15973 (Segmentation fault in JIT mode 1135) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1215 +opcache.jit_buffer_size=64M +--FILE-- +prop[] = 1; +})->bindTo($test, Test::class); +$appendProp2(); +?> +--EXPECTF-- +Warning: Undefined variable $test in %sgh15973.php on line 6 + +Fatal error: Uncaught Error: Using $this when not in object context in %sgh15973.php:5 +Stack trace: +#0 %sgh15973.php(7): Test::{closure}() +#1 {main} + thrown in %sgh15973.php on line 5 \ No newline at end of file diff -Nru php8.2-8.2.24/ext/opcache/tests/jit/gh16393.phpt php8.2-8.2.26/ext/opcache/tests/jit/gh16393.phpt --- php8.2-8.2.24/ext/opcache/tests/jit/gh16393.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/opcache/tests/jit/gh16393.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,18 @@ +--TEST-- +GH-16393 (Assertion failure in ext/opcache/jit/zend_jit.c:2897) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1215 +opcache.jit_buffer_size=64M +--FILE-- +bindTo($test, Test::class); +$appendProp2(); +?> +--EXPECTF-- +Warning: Undefined variable $test in %sgh16393.php on line 6 diff -Nru php8.2-8.2.24/ext/opcache/tests/jit/gh16499.phpt php8.2-8.2.26/ext/opcache/tests/jit/gh16499.phpt --- php8.2-8.2.24/ext/opcache/tests/jit/gh16499.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/opcache/tests/jit/gh16499.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,28 @@ +--TEST-- +GH-16499 (Undefined to null coercion issues for return) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit_buffer_size=64M +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $i in %sgh16499.php on line 6 + +Warning: Undefined variable $i in %sgh16499.php on line 6 +NULL + +Warning: Undefined variable $i in %sgh16499.php on line 6 + +Warning: Undefined variable $i in %sgh16499.php on line 6 +NULL \ No newline at end of file diff -Nru php8.2-8.2.24/ext/opcache/zend_accelerator_util_funcs.c php8.2-8.2.26/ext/opcache/zend_accelerator_util_funcs.c --- php8.2-8.2.24/ext/opcache/zend_accelerator_util_funcs.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/opcache/zend_accelerator_util_funcs.c 2024-11-19 17:11:09.000000000 +0000 @@ -170,13 +170,13 @@ function2 = Z_PTR_P(t); CG(in_compilation) = 1; zend_set_compiled_filename(function1->op_array.filename); - CG(zend_lineno) = function1->op_array.opcodes[0].lineno; + CG(zend_lineno) = function1->op_array.line_start; if (function2->type == ZEND_USER_FUNCTION && function2->op_array.last > 0) { zend_error(E_ERROR, "Cannot redeclare %s() (previously declared in %s:%d)", ZSTR_VAL(function1->common.function_name), ZSTR_VAL(function2->op_array.filename), - (int)function2->op_array.opcodes[0].lineno); + (int)function2->op_array.line_start); } else { zend_error(E_ERROR, "Cannot redeclare %s()", ZSTR_VAL(function1->common.function_name)); } diff -Nru php8.2-8.2.24/ext/openssl/openssl.c php8.2-8.2.26/ext/openssl/openssl.c --- php8.2-8.2.24/ext/openssl/openssl.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/openssl/openssl.c 2024-11-19 17:11:09.000000000 +0000 @@ -1457,11 +1457,13 @@ *free_cert = 1; - if (!try_convert_to_string(val)) { + zend_string *str = zval_try_get_string(val); + if (str == NULL) { return NULL; } - - return php_openssl_x509_from_str(Z_STR_P(val), arg_num, is_from_array, option_name); + X509 *cert = php_openssl_x509_from_str(str, arg_num, is_from_array, option_name); + zend_string_release(str); + return cert; } /* }}} */ @@ -2089,7 +2091,7 @@ /* Can return NULL on error or memory allocation failure */ if (!bn_serial) { php_openssl_store_errors(); - RETURN_FALSE; + goto err; } hex_serial = BN_bn2hex(bn_serial); @@ -2097,7 +2099,7 @@ /* Can return NULL on error or memory allocation failure */ if (!hex_serial) { php_openssl_store_errors(); - RETURN_FALSE; + goto err; } str_serial = i2s_ASN1_INTEGER(NULL, asn1_serial); @@ -2169,19 +2171,15 @@ bio_out = BIO_new(BIO_s_mem()); if (bio_out == NULL) { php_openssl_store_errors(); - RETURN_FALSE; + goto err_subitem; } if (nid == NID_subject_alt_name) { if (openssl_x509v3_subjectAltName(bio_out, extension) == 0) { BIO_get_mem_ptr(bio_out, &bio_buf); add_assoc_stringl(&subitem, extname, bio_buf->data, bio_buf->length); } else { - zend_array_destroy(Z_ARR_P(return_value)); BIO_free(bio_out); - if (cert_str) { - X509_free(cert); - } - RETURN_FALSE; + goto err_subitem; } } else if (X509V3_EXT_print(bio_out, extension, 0, 0)) { @@ -2196,6 +2194,16 @@ if (cert_str) { X509_free(cert); } + return; + +err_subitem: + zval_ptr_dtor(&subitem); +err: + zend_array_destroy(Z_ARR_P(return_value)); + if (cert_str) { + X509_free(cert); + } + RETURN_FALSE; } /* }}} */ @@ -3198,6 +3206,11 @@ goto cleanup; } + if (num_days < 0 || num_days > LONG_MAX / 86400) { + php_error_docref(NULL, E_WARNING, "Days must be between 0 and %ld", LONG_MAX / 86400); + goto cleanup; + } + if (PHP_SSL_REQ_PARSE(&req, args) == FAILURE) { goto cleanup; } @@ -3249,7 +3262,7 @@ goto cleanup; } X509_gmtime_adj(X509_getm_notBefore(new_cert), 0); - X509_gmtime_adj(X509_getm_notAfter(new_cert), 60*60*24*(long)num_days); + X509_gmtime_adj(X509_getm_notAfter(new_cert), 60*60*24*num_days); i = X509_set_pubkey(new_cert, key); if (!i) { php_openssl_store_errors(); diff -Nru php8.2-8.2.24/ext/openssl/openssl.stub.php php8.2-8.2.26/ext/openssl/openssl.stub.php --- php8.2-8.2.24/ext/openssl/openssl.stub.php 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/openssl/openssl.stub.php 2024-11-19 17:11:09.000000000 +0000 @@ -433,9 +433,9 @@ function openssl_csr_sign(OpenSSLCertificateSigningRequest|string $csr, OpenSSLCertificate|string|null $ca_certificate, #[\SensitiveParameter] $private_key, int $days, ?array $options = null, int $serial = 0): OpenSSLCertificate|false {} /** - * @param OpenSSLAsymmetricKey $private_key + * @param OpenSSLAsymmetricKey|null $private_key */ -function openssl_csr_new(array $distinguished_names, #[\SensitiveParameter] &$private_key, ?array $options = null, ?array $extra_attributes = null): OpenSSLCertificateSigningRequest|false {} +function openssl_csr_new(array $distinguished_names, #[\SensitiveParameter] &$private_key, ?array $options = null, ?array $extra_attributes = null): OpenSSLCertificateSigningRequest|bool {} /** * @return array|false diff -Nru php8.2-8.2.24/ext/openssl/openssl_arginfo.h php8.2-8.2.26/ext/openssl/openssl_arginfo.h --- php8.2-8.2.24/ext/openssl/openssl_arginfo.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/openssl/openssl_arginfo.h 2024-11-19 17:11:09.000000000 +0000 @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: be79b4cc0d9eb4469c43f10208b86369dcc1239d */ + * Stub hash: f68e5002b3f1b224b3dd979307f0e4093f42d5e9 */ 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) @@ -92,7 +92,7 @@ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, serial, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_openssl_csr_new, 0, 2, OpenSSLCertificateSigningRequest, MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_openssl_csr_new, 0, 2, OpenSSLCertificateSigningRequest, MAY_BE_BOOL) ZEND_ARG_TYPE_INFO(0, distinguished_names, IS_ARRAY, 0) ZEND_ARG_INFO(1, private_key) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null") diff -Nru php8.2-8.2.24/ext/openssl/tests/gh16357.phpt php8.2-8.2.26/ext/openssl/tests/gh16357.phpt --- php8.2-8.2.24/ext/openssl/tests/gh16357.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/openssl/tests/gh16357.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,22 @@ +--TEST-- +GH-16357 (openssl may modify member types of certificate arrays) +--EXTENSIONS-- +openssl +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(false) +array(1) { + [0]=> + int(123) +} diff -Nru php8.2-8.2.24/ext/openssl/tests/gh16433.phpt php8.2-8.2.26/ext/openssl/tests/gh16433.phpt --- php8.2-8.2.24/ext/openssl/tests/gh16433.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/openssl/tests/gh16433.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,17 @@ +--TEST-- +GH-16433 (Large values for openssl_csr_sign() $days overflow) +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECTF-- +Warning: openssl_csr_sign(): Days must be between 0 and %d in %s on line %d +bool(false) + +Warning: openssl_csr_sign(): Days must be between 0 and %d in %s on line %d +bool(false) diff -Nru php8.2-8.2.24/ext/pcre/php_pcre.c php8.2-8.2.26/ext/pcre/php_pcre.c --- php8.2-8.2.24/ext/pcre/php_pcre.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/pcre/php_pcre.c 2024-11-19 17:11:09.000000000 +0000 @@ -1135,6 +1135,11 @@ RETURN_FALSE; } + if (start_offset == ZEND_LONG_MIN) { + zend_argument_value_error(5, "must be greater than " ZEND_LONG_FMT, ZEND_LONG_MIN); + RETURN_THROWS(); + } + pce->refcount++; php_pcre_match_impl(pce, subject, return_value, subpats, global, ZEND_NUM_ARGS() >= 4, flags, start_offset); @@ -1742,9 +1747,11 @@ } if (preg_get_backref(&walk, &backref)) { if (backref < count) { - match_len = offsets[(backref<<1)+1] - offsets[backref<<1]; - memcpy(walkbuf, subject + offsets[backref<<1], match_len); - walkbuf += match_len; + if (offsets[backref<<1] < SIZE_MAX) { + match_len = offsets[(backref<<1)+1] - offsets[backref<<1]; + memcpy(walkbuf, subject + offsets[backref<<1], match_len); + walkbuf += match_len; + } } continue; } diff -Nru php8.2-8.2.24/ext/pcre/tests/gh16184.phpt php8.2-8.2.26/ext/pcre/tests/gh16184.phpt --- php8.2-8.2.24/ext/pcre/tests/gh16184.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/pcre/tests/gh16184.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,13 @@ +--TEST-- +GH-16184 (UBSan address overflowed in ext/pcre/php_pcre.c) +--CREDITS-- +YuanchengJiang +--FILE-- + +--EXPECT-- +This test a string. It contains numbers * to 0* to 9* test well test parentheses and some other things* diff -Nru php8.2-8.2.24/ext/pcre/tests/gh16189.phpt php8.2-8.2.26/ext/pcre/tests/gh16189.phpt --- php8.2-8.2.24/ext/pcre/tests/gh16189.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/pcre/tests/gh16189.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,19 @@ +--TEST-- +GH-16189 (preg_match/preg_match_all underflow on start_offset argument) +--FILE-- +/', '
', $matches, 0, PHP_INT_MIN); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} +try { + preg_match_all( '/<(\w+)[\s\w\-]+ id="S44_i89ew">/', '
', $matches, 0, PHP_INT_MIN); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} +?> +--EXPECTF-- +preg_match(): Argument #5 ($offset) must be greater than %s +preg_match_all(): Argument #5 ($offset) must be greater than %s diff -Nru php8.2-8.2.24/ext/pdo_dblib/dblib_driver.c php8.2-8.2.26/ext/pdo_dblib/dblib_driver.c --- php8.2-8.2.24/ext/pdo_dblib/dblib_driver.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/pdo_dblib/dblib_driver.c 2024-11-19 17:11:09.000000000 +0000 @@ -148,7 +148,7 @@ bool use_national_character_set = 0; size_t i; char *q; - size_t quotedlen = 0; + size_t quotedlen = 0, extralen = 0; zend_string *quoted_str; if (H->assume_national_character_set_strings) { @@ -163,7 +163,7 @@ /* Detect quoted length, adding extra char for doubled single quotes */ for (i = 0; i < ZSTR_LEN(unquoted); i++) { - if (ZSTR_VAL(unquoted)[i] == '\'') ++quotedlen; + if (ZSTR_VAL(unquoted)[i] == '\'') ++extralen; ++quotedlen; } @@ -171,6 +171,12 @@ if (use_national_character_set) { ++quotedlen; /* N prefix */ } + + if (UNEXPECTED(quotedlen > ZSTR_MAX_LEN - extralen)) { + return NULL; + } + + quotedlen += extralen; quoted_str = zend_string_alloc(quotedlen, 0); q = ZSTR_VAL(quoted_str); if (use_national_character_set) { diff -Nru php8.2-8.2.24/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt php8.2-8.2.26/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt --- php8.2-8.2.24/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/pdo_dblib/tests/GHSA-5hqh-c84r-qjcv.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,24 @@ +--TEST-- +GHSA-5hqh-c84r-qjcv (Integer overflow in the dblib quoter causing OOB writes) +--EXTENSIONS-- +pdo_dblib +--SKIPIF-- + +--INI-- +memory_limit=-1 +--FILE-- +quote(str_repeat("'", 2147483646))); + +?> +--EXPECT-- +bool(false) diff -Nru php8.2-8.2.24/ext/pdo_firebird/firebird_driver.c php8.2-8.2.26/ext/pdo_firebird/firebird_driver.c --- php8.2-8.2.24/ext/pdo_firebird/firebird_driver.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/pdo_firebird/firebird_driver.c 2024-11-19 17:11:09.000000000 +0000 @@ -664,7 +664,7 @@ /* called by the PDO SQL parser to add quotes to values that are copied into SQL */ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype) { - int qcount = 0; + size_t qcount = 0; char const *co, *l, *r; char *c; size_t quotedlen; @@ -678,6 +678,10 @@ /* count the number of ' characters */ for (co = ZSTR_VAL(unquoted); (co = strchr(co,'\'')); qcount++, co++); + if (UNEXPECTED(ZSTR_LEN(unquoted) + 2 > ZSTR_MAX_LEN - qcount)) { + return NULL; + } + quotedlen = ZSTR_LEN(unquoted) + qcount + 2; quoted_str = zend_string_alloc(quotedlen, 0); c = ZSTR_VAL(quoted_str); diff -Nru php8.2-8.2.24/ext/pdo_odbc/odbc_stmt.c php8.2-8.2.26/ext/pdo_odbc/odbc_stmt.c --- php8.2-8.2.24/ext/pdo_odbc/odbc_stmt.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/pdo_odbc/odbc_stmt.c 2024-11-19 17:11:09.000000000 +0000 @@ -689,11 +689,12 @@ /* read block. 256 bytes => 255 bytes are actually read, the last 1 is NULL */ rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, buf2, 256, &C->fetched_len); - /* adjust `used` in case we have length info from the driver */ + /* adjust `used` in case we have proper length info from the driver */ if (orig_fetched_len >= 0 && C->fetched_len >= 0) { SQLLEN fixed_used = orig_fetched_len - C->fetched_len; - ZEND_ASSERT(fixed_used <= used + 1); - used = fixed_used; + if (fixed_used <= used + 1) { + used = fixed_used; + } } /* resize output buffer and reassemble block */ diff -Nru php8.2-8.2.24/ext/pdo_odbc/tests/gh16450.phpt php8.2-8.2.26/ext/pdo_odbc/tests/gh16450.phpt --- php8.2-8.2.24/ext/pdo_odbc/tests/gh16450.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/pdo_odbc/tests/gh16450.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,35 @@ +--TEST-- +GH-16450 (PDO_ODBC can inject garbage into field values) +--EXTENSIONS-- +pdo_odbc +--SKIPIF-- + +--FILE-- +exec("CREATE TABLE gh16450 (Id INT, MyLongText LONGCHAR)"); +$pdo->exec(sprintf("INSERT INTO gh16450 VALUES (1, '%s')", str_repeat("_", 2048))); +$pdo->exec(sprintf("INSERT INTO gh16450 VALUES (1, '%s')", str_repeat("_", 2049))); + +$stmt = $pdo->query("SELECT MyLongText FROM gh16450"); +var_dump($stmt->fetchColumn(0)); +var_dump($stmt->fetchColumn(0)); +?> +--CLEAN-- +exec("DROP TABLE gh16450"); +?> +--EXPECT-- +string(2048) "________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________" +string(2049) "_________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________" Binary files /srv/release.debian.org/tmp/b1K5c6j1Ka/php8.2-8.2.24/ext/pdo_odbc/tests/test.mdb and /srv/release.debian.org/tmp/1nVyDKFjuf/php8.2-8.2.26/ext/pdo_odbc/tests/test.mdb differ diff -Nru php8.2-8.2.24/ext/phar/phar.c php8.2-8.2.26/ext/phar/phar.c --- php8.2-8.2.24/ext/phar/phar.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/phar/phar.c 2024-11-19 17:11:09.000000000 +0000 @@ -457,14 +457,14 @@ #ifdef WORDS_BIGENDIAN # define PHAR_GET_32(buffer, var) \ - var = ((((unsigned char*)(buffer))[3]) << 24) \ - | ((((unsigned char*)(buffer))[2]) << 16) \ - | ((((unsigned char*)(buffer))[1]) << 8) \ - | (((unsigned char*)(buffer))[0]); \ + var = ((uint32_t)(((unsigned char*)(buffer))[3]) << 24) \ + | ((uint32_t)(((unsigned char*)(buffer))[2]) << 16) \ + | ((uint32_t)(((unsigned char*)(buffer))[1]) << 8) \ + | ((uint32_t)((unsigned char*)(buffer))[0]); \ (buffer) += 4 # define PHAR_GET_16(buffer, var) \ - var = ((((unsigned char*)(buffer))[1]) << 8) \ - | (((unsigned char*)(buffer))[0]); \ + var = ((uint16_t)(((unsigned char*)(buffer))[1]) << 8) \ + | ((uint16_t)((unsigned char*)(buffer))[0]); \ (buffer) += 2 #else # define PHAR_GET_32(buffer, var) \ diff -Nru php8.2-8.2.24/ext/phar/phar_object.c php8.2-8.2.26/ext/phar/phar_object.c --- php8.2-8.2.24/ext/phar/phar_object.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/phar/phar_object.c 2024-11-19 17:11:09.000000000 +0000 @@ -2286,6 +2286,9 @@ newentry.tar_type = (entry->is_dir ? TAR_DIR : TAR_FILE); } + /* The header offset is only used for unmodified zips. + * Once modified, phar_zip_changed_apply_int() will update the header_offset. */ + newentry.header_offset = 0; newentry.is_modified = 1; newentry.phar = phar; newentry.old_flags = newentry.flags & ~PHAR_ENT_COMPRESSION_MASK; /* remove compression from old_flags */ diff -Nru php8.2-8.2.24/ext/phar/tests/033a.phpt php8.2-8.2.26/ext/phar/tests/033a.phpt --- php8.2-8.2.24/ext/phar/tests/033a.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/phar/tests/033a.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -5,6 +5,12 @@ --INI-- phar.readonly=1 phar.require_hash=0 +--SKIPIF-- + --FILE-- '; +$files['b'] = 'b'; +$files['c'] = 'c'; +include __DIR__.'/files/phar_test.inc'; +$phar = new Phar($fname); +$phar->compressFiles(Phar::GZ); +$phar = $phar->convertToExecutable(Phar::TAR); +$phar = $phar->convertToExecutable(Phar::PHAR, Phar::GZ); +var_dump($phar['b']->openFile()->fread(4096)); +var_dump($phar['c']->openFile()->fread(4096)); +?> +--CLEAN-- + +--EXPECT-- +string(1) "b" +string(1) "c" diff -Nru php8.2-8.2.24/ext/phar/tests/phar_oo_002.phpt php8.2-8.2.26/ext/phar/tests/phar_oo_002.phpt --- php8.2-8.2.24/ext/phar/tests/phar_oo_002.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/phar/tests/phar_oo_002.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -5,6 +5,12 @@ --INI-- phar.readonly=1 phar.require_hash=0 +--SKIPIF-- + --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- unmangled_name, 0); + efree(reference); +} + +static void reflection_free_parameter_reference(parameter_reference *reference) +{ + _free_function(reference->fptr); + efree(reference); +} + static void reflection_free_objects_storage(zend_object *object) /* {{{ */ { reflection_object *intern = reflection_object_from_obj(object); - parameter_reference *reference; - property_reference *prop_reference; if (intern->ptr) { switch (intern->ref_type) { case REF_TYPE_PARAMETER: - reference = (parameter_reference*)intern->ptr; - _free_function(reference->fptr); - efree(intern->ptr); + reflection_free_parameter_reference(intern->ptr); break; case REF_TYPE_TYPE: { @@ -243,9 +251,7 @@ _free_function(intern->ptr); break; case REF_TYPE_PROPERTY: - prop_reference = (property_reference*)intern->ptr; - zend_string_release_ex(prop_reference->unmangled_name, 0); - efree(intern->ptr); + reflection_free_property_reference(intern->ptr); break; case REF_TYPE_ATTRIBUTE: { attribute_reference *attr_ref = intern->ptr; @@ -477,7 +483,7 @@ count = 0; if (properties && zend_hash_num_elements(properties)) { - ZEND_HASH_MAP_FOREACH_STR_KEY(properties, prop_name) { + ZEND_HASH_FOREACH_STR_KEY(properties, prop_name) { if (prop_name && ZSTR_LEN(prop_name) && ZSTR_VAL(prop_name)[0]) { /* skip all private and protected properties */ if (!zend_hash_exists(&ce->properties_info, prop_name)) { count++; @@ -2546,6 +2552,10 @@ } } + if (intern->ptr) { + reflection_free_parameter_reference(intern->ptr); + } + ref = (parameter_reference*) emalloc(sizeof(parameter_reference)); ref->arg_info = &arg_info[position]; ref->offset = (uint32_t)position; @@ -2555,11 +2565,15 @@ intern->ptr = ref; intern->ref_type = REF_TYPE_PARAMETER; intern->ce = ce; + zval_ptr_dtor(&intern->obj); if (reference && is_closure) { ZVAL_COPY_VALUE(&intern->obj, reference); + } else { + ZVAL_UNDEF(&intern->obj); } prop_name = reflection_prop_name(object); + zval_ptr_dtor(prop_name); if (has_internal_arg_info(fptr)) { ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)[position].name); } else { @@ -4015,10 +4029,12 @@ object = ZEND_THIS; intern = Z_REFLECTION_P(object); + /* Note: class entry name is interned, no need to destroy them */ if (arg_obj) { ZVAL_STR_COPY(reflection_prop_name(object), arg_obj->ce->name); intern->ptr = arg_obj->ce; if (is_object) { + zval_ptr_dtor(&intern->obj); ZVAL_OBJ_COPY(&intern->obj, arg_obj); } } else { @@ -5510,13 +5526,20 @@ } } - ZVAL_STR_COPY(reflection_prop_name(object), name); + zval *prop_name = reflection_prop_name(object); + zval_ptr_dtor(prop_name); + ZVAL_STR_COPY(prop_name, name); + /* Note: class name are always interned, no need to destroy them */ if (dynam_prop == 0) { ZVAL_STR_COPY(reflection_prop_class(object), property_info->ce->name); } else { ZVAL_STR_COPY(reflection_prop_class(object), ce->name); } + if (intern->ptr) { + reflection_free_property_reference(intern->ptr); + } + reference = (property_reference*) emalloc(sizeof(property_reference)); reference->prop = dynam_prop ? NULL : property_info; reference->unmangled_name = zend_string_copy(name); @@ -5949,7 +5972,9 @@ RETURN_THROWS(); } free_alloca(lcname, use_heap); - ZVAL_STRING(reflection_prop_name(object), module->name); + zval *prop_name = reflection_prop_name(object); + zval_ptr_dtor(prop_name); + ZVAL_STRING(prop_name, module->name); intern->ptr = module; intern->ref_type = REF_TYPE_OTHER; intern->ce = NULL; diff -Nru php8.2-8.2.24/ext/reflection/tests/ReflectionExtension_double_construct.phpt php8.2-8.2.26/ext/reflection/tests/ReflectionExtension_double_construct.phpt --- php8.2-8.2.24/ext/reflection/tests/ReflectionExtension_double_construct.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/reflection/tests/ReflectionExtension_double_construct.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,20 @@ +--TEST-- +ReflectionExtension double construct call +--FILE-- +__construct('standard'); +var_dump($r); + +?> +--EXPECT-- +object(ReflectionExtension)#1 (1) { + ["name"]=> + string(8) "standard" +} +object(ReflectionExtension)#1 (1) { + ["name"]=> + string(8) "standard" +} diff -Nru php8.2-8.2.24/ext/reflection/tests/ReflectionObject_double_construct.phpt php8.2-8.2.26/ext/reflection/tests/ReflectionObject_double_construct.phpt --- php8.2-8.2.24/ext/reflection/tests/ReflectionObject_double_construct.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/reflection/tests/ReflectionObject_double_construct.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,21 @@ +--TEST-- +ReflectionObject double construct call +--FILE-- +__construct($obj); +var_dump($r); + +?> +--EXPECT-- +object(ReflectionObject)#2 (1) { + ["name"]=> + string(8) "stdClass" +} +object(ReflectionObject)#2 (1) { + ["name"]=> + string(8) "stdClass" +} diff -Nru php8.2-8.2.24/ext/reflection/tests/ReflectionParameter_double_construct.phpt php8.2-8.2.26/ext/reflection/tests/ReflectionParameter_double_construct.phpt --- php8.2-8.2.24/ext/reflection/tests/ReflectionParameter_double_construct.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/reflection/tests/ReflectionParameter_double_construct.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,27 @@ +--TEST-- +ReflectionParameter double construct call +--FILE-- +__construct($closure, 'x'); +var_dump($r); +$r->__construct('ord', 'character'); +var_dump($r); + +?> +--EXPECT-- +object(ReflectionParameter)#2 (1) { + ["name"]=> + string(1) "x" +} +object(ReflectionParameter)#2 (1) { + ["name"]=> + string(1) "x" +} +object(ReflectionParameter)#2 (1) { + ["name"]=> + string(9) "character" +} diff -Nru php8.2-8.2.24/ext/reflection/tests/ReflectionProperty_double_construct.phpt php8.2-8.2.26/ext/reflection/tests/ReflectionProperty_double_construct.phpt --- php8.2-8.2.24/ext/reflection/tests/ReflectionProperty_double_construct.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/reflection/tests/ReflectionProperty_double_construct.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,24 @@ +--TEST-- +ReflectionProperty double construct call +--FILE-- +__construct(Exception::class, 'message'); +var_dump($r); + +?> +--EXPECT-- +object(ReflectionProperty)#1 (2) { + ["name"]=> + string(7) "message" + ["class"]=> + string(9) "Exception" +} +object(ReflectionProperty)#1 (2) { + ["name"]=> + string(7) "message" + ["class"]=> + string(9) "Exception" +} diff -Nru php8.2-8.2.24/ext/reflection/tests/gh16187.phpt php8.2-8.2.26/ext/reflection/tests/gh16187.phpt --- php8.2-8.2.24/ext/reflection/tests/gh16187.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/reflection/tests/gh16187.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,14 @@ +--TEST-- +GH-16187 (ReflectionClass::__toString() with unpacked properties) +--EXTENSIONS-- +simplexml +--FILE-- +'; +$simplexml = simplexml_load_string($xml); +$reflector = new ReflectionObject($simplexml['name']); +$reflector->__toString(); +?> +DONE +--EXPECT-- +DONE diff -Nru php8.2-8.2.24/ext/session/session.c php8.2-8.2.26/ext/session/session.c --- php8.2-8.2.24/ext/session/session.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/session/session.c 2024-11-19 17:11:09.000000000 +0000 @@ -693,9 +693,18 @@ { SESSION_CHECK_ACTIVE_STATE; SESSION_CHECK_OUTPUT_STATE; - if (atol(ZSTR_VAL(new_value)) < 0) { + +#ifdef ZEND_ENABLE_ZVAL_LONG64 + const zend_long maxcookie = ZEND_LONG_MAX - INT_MAX - 1; +#else + const zend_long maxcookie = ZEND_LONG_MAX / 2 - 1; +#endif + zend_long v = (zend_long)atol(ZSTR_VAL(new_value)); + if (v < 0) { php_error_docref(NULL, E_WARNING, "CookieLifetime cannot be negative"); return FAILURE; + } else if (v > maxcookie) { + return SUCCESS; } return OnUpdateLongGEZero(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } @@ -1668,10 +1677,6 @@ zend_result result; int found = 0; - if (!PS(use_cookies)) { - return; - } - ZEND_PARSE_PARAMETERS_START(1, 5) Z_PARAM_ARRAY_HT_OR_LONG(options_ht, lifetime_long) Z_PARAM_OPTIONAL @@ -1681,6 +1686,11 @@ Z_PARAM_BOOL_OR_NULL(httponly, httponly_null) ZEND_PARSE_PARAMETERS_END(); + if (!PS(use_cookies)) { + php_error_docref(NULL, E_WARNING, "Session cookies cannot be used when session.use_cookies is disabled"); + RETURN_FALSE; + } + if (PS(session_status) == php_session_active) { php_error_docref(NULL, E_WARNING, "Session cookie parameters cannot be changed when a session is active"); RETURN_FALSE; diff -Nru php8.2-8.2.24/ext/session/tests/gh16290.phpt php8.2-8.2.26/ext/session/tests/gh16290.phpt --- php8.2-8.2.24/ext/session/tests/gh16290.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/session/tests/gh16290.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,13 @@ +--TEST-- +GH-16290 (overflow on session cookie_lifetime ini) +--EXTENSIONS-- +session +--SKIPIF-- + +--FILE-- + +--EXPECT-- +DONE diff -Nru php8.2-8.2.24/ext/session/tests/gh16385.phpt php8.2-8.2.26/ext/session/tests/gh16385.phpt --- php8.2-8.2.24/ext/session/tests/gh16385.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/session/tests/gh16385.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,13 @@ +--TEST-- +GH-16385 (Unexpected null returned by session_set_cookie_params) +--EXTENSIONS-- +session +--INI-- +session.use_cookies=0 +--FILE-- + +--EXPECTF-- +Warning: session_set_cookie_params(): Session cookies cannot be used when session.use_cookies is disabled in %s on line %d +bool(false) diff -Nru php8.2-8.2.24/ext/session/tests/session_get_cookie_params_basic.phpt php8.2-8.2.26/ext/session/tests/session_get_cookie_params_basic.phpt --- php8.2-8.2.24/ext/session/tests/session_get_cookie_params_basic.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/session/tests/session_get_cookie_params_basic.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -35,7 +35,7 @@ echo "Done"; ob_end_flush(); ?> ---EXPECT-- +--EXPECTF-- *** Testing session_get_cookie_params() : basic functionality *** array(6) { ["lifetime"]=> @@ -69,7 +69,7 @@ bool(true) array(6) { ["lifetime"]=> - int(1234567890) + int(%d) ["path"]=> string(5) "/guff" ["domain"]=> diff -Nru php8.2-8.2.24/ext/simplexml/simplexml.c php8.2-8.2.26/ext/simplexml/simplexml.c --- php8.2-8.2.24/ext/simplexml/simplexml.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/simplexml/simplexml.c 2024-11-19 17:11:09.000000000 +0000 @@ -2547,6 +2547,11 @@ { php_sxe_iterator *iterator = (php_sxe_iterator *)iter; zval *curobj = &iterator->sxe->iter.data; + if (Z_ISUNDEF_P(curobj)) { + ZVAL_NULL(key); + return; + } + php_sxe_object *intern = Z_SXEOBJ_P(curobj); xmlNodePtr curnode = NULL; diff -Nru php8.2-8.2.24/ext/simplexml/tests/gh15837.phpt php8.2-8.2.26/ext/simplexml/tests/gh15837.phpt --- php8.2-8.2.24/ext/simplexml/tests/gh15837.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/simplexml/tests/gh15837.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,30 @@ +--TEST-- +GH-15837 (Segmentation fault in ext/simplexml/simplexml.c) +--CREDITS-- +YuanchengJiang +--FILE-- + + + + + + + + +EOF; +$sxe = new SimpleXMLIterator($xml); +$rit = new RecursiveIteratorIterator($sxe, RecursiveIteratorIterator::LEAVES_ONLY); +foreach ($rit as $child) { + $ancestry = $child->xpath('ancestor-or-self::*'); + // Exhaust internal iterator + foreach ($ancestry as $ancestor) { + } +} +var_dump($rit->valid()); +var_dump($rit->key()); +?> +--EXPECT-- +bool(false) +NULL diff -Nru php8.2-8.2.24/ext/soap/php_encoding.c php8.2-8.2.26/ext/soap/php_encoding.c --- php8.2-8.2.24/ext/soap/php_encoding.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/soap/php_encoding.c 2024-11-19 17:11:09.000000000 +0000 @@ -1408,7 +1408,9 @@ return ret; } - object_init_ex(ret, ce); + if (object_init_ex(ret, ce) != SUCCESS) { + return ret; + } master_to_zval_int(&base, enc, data); set_zval_property(ret, "_", &base); } else { @@ -1417,7 +1419,9 @@ if (soap_check_xml_ref(ret, data)) { return ret; } - object_init_ex(ret, ce); + if (object_init_ex(ret, ce) != SUCCESS) { + return ret; + } soap_add_xml_ref(ret, data); } } else if (sdlType->kind == XSD_TYPEKIND_EXTENSION && @@ -1462,7 +1466,9 @@ return ret; } - object_init_ex(ret, ce); + if (object_init_ex(ret, ce) != SUCCESS) { + return ret; + } soap_add_xml_ref(ret, data); master_to_zval_int(&base, sdlType->encode, data); set_zval_property(ret, "_", &base); @@ -1473,7 +1479,9 @@ if (soap_check_xml_ref(ret, data)) { return ret; } - object_init_ex(ret, ce); + if (object_init_ex(ret, ce) != SUCCESS) { + return ret; + } soap_add_xml_ref(ret, data); } if (sdlType->model) { @@ -1533,7 +1541,9 @@ return ret; } - object_init_ex(ret, ce); + if (object_init_ex(ret, ce) != SUCCESS) { + return ret; + } soap_add_xml_ref(ret, data); trav = data->children; @@ -2200,8 +2210,8 @@ iter = ce->get_iterator(ce, data, 0); - if (EG(exception)) { - goto iterator_done; + if (!iter) { + goto iterator_failed_to_get; } if (iter->funcs->rewind) { @@ -2241,6 +2251,7 @@ } iterator_done: OBJ_RELEASE(&iter->std); +iterator_failed_to_get: if (EG(exception)) { zval_ptr_dtor(&array_copy); ZVAL_UNDEF(&array_copy); diff -Nru php8.2-8.2.24/ext/soap/php_http.c php8.2-8.2.26/ext/soap/php_http.c --- php8.2-8.2.24/ext/soap/php_http.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/soap/php_http.c 2024-11-19 17:11:09.000000000 +0000 @@ -461,6 +461,7 @@ } add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL); smart_str_free(&soap_headers_z); + efree(http_msg); return FALSE; } @@ -474,6 +475,7 @@ } add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL); smart_str_free(&soap_headers_z); + efree(http_msg); return FALSE; } @@ -487,6 +489,7 @@ add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL); PG(allow_url_fopen) = old_allow_url_fopen; smart_str_free(&soap_headers_z); + efree(http_msg); return FALSE; } @@ -541,6 +544,7 @@ add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL); PG(allow_url_fopen) = old_allow_url_fopen; smart_str_free(&soap_headers_z); + efree(http_msg); return FALSE; } } @@ -684,6 +688,7 @@ convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); smart_str_free(&soap_headers_z); smart_str_free(&soap_headers); + efree(http_msg); return FALSE; } @@ -901,12 +906,14 @@ convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL); smart_str_free(&soap_headers_z); + efree(http_msg); return FALSE; } smart_str_free(&soap_headers); } else { add_soap_fault(this_ptr, "HTTP", "Failed to create stream??", NULL, NULL); smart_str_free(&soap_headers_z); + efree(http_msg); return FALSE; } @@ -915,6 +922,7 @@ convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr)); convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); smart_str_free(&soap_headers_z); + efree(http_msg); return TRUE; } @@ -929,6 +937,7 @@ convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr)); add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL); smart_str_free(&soap_headers_z); + efree(http_msg); return FALSE; } @@ -1157,6 +1166,7 @@ if (--redirect_max < 1) { add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL); smart_str_free(&soap_headers_z); + efree(http_msg); return FALSE; } diff -Nru php8.2-8.2.24/ext/soap/php_schema.c php8.2-8.2.26/ext/soap/php_schema.c --- php8.2-8.2.24/ext/soap/php_schema.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/soap/php_schema.c 2024-11-19 17:11:09.000000000 +0000 @@ -92,6 +92,13 @@ return enc; } +/* Necessary for some error paths to avoid leaking persistent memory. */ +static void requestify_string(xmlChar **str) { + xmlChar *copy = (xmlChar *) estrdup((const char *) *str); + xmlFree(*str); + *str = copy; +} + static void schema_load_file(sdlCtx *ctx, xmlAttrPtr ns, xmlChar *location, xmlAttrPtr tns, int import) { if (location != NULL && !zend_hash_str_exists(&ctx->docs, (char*)location, xmlStrlen(location))) { @@ -104,22 +111,35 @@ sdl_restore_uri_credentials(ctx); if (doc == NULL) { + requestify_string(&location); soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s'", location); } schema = get_node(doc->children, "schema"); if (schema == NULL) { + requestify_string(&location); xmlFreeDoc(doc); soap_error1(E_ERROR, "Parsing Schema: can't import schema from '%s'", location); } new_tns = get_attribute(schema->properties, "targetNamespace"); if (import) { if (ns != NULL && (new_tns == NULL || xmlStrcmp(ns->children->content, new_tns->children->content) != 0)) { - xmlFreeDoc(doc); - soap_error2(E_ERROR, "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s'", location, ns->children->content); + requestify_string(&location); + if (new_tns == NULL) { + xmlFreeDoc(doc); + soap_error2(E_ERROR, "Parsing Schema: can't import schema from '%s', missing 'targetNamespace', expected '%s'", location, ns->children->content); + } else { + /* Have to make a copy to avoid a UAF after freeing `doc` */ + const char *target_ns_copy = estrdup((const char *) new_tns->children->content); + xmlFreeDoc(doc); + soap_error3(E_ERROR, "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s', expected '%s'", location, target_ns_copy, ns->children->content); + } } if (ns == NULL && new_tns != NULL) { + requestify_string(&location); + /* Have to make a copy to avoid a UAF after freeing `doc` */ + const char *target_ns_copy = estrdup((const char *) new_tns->children->content); xmlFreeDoc(doc); - soap_error2(E_ERROR, "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s'", location, new_tns->children->content); + soap_error2(E_ERROR, "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s', expected no 'targetNamespace'", location, target_ns_copy); } } else { new_tns = get_attribute(schema->properties, "targetNamespace"); @@ -128,6 +148,7 @@ xmlSetProp(schema, BAD_CAST("targetNamespace"), tns->children->content); } } else if (tns != NULL && xmlStrcmp(tns->children->content, new_tns->children->content) != 0) { + requestify_string(&location); xmlFreeDoc(doc); soap_error1(E_ERROR, "Parsing Schema: can't include schema from '%s', different 'targetNamespace'", location); } diff -Nru php8.2-8.2.24/ext/soap/soap.c php8.2-8.2.26/ext/soap/soap.c --- php8.2-8.2.24/ext/soap/soap.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/soap/soap.c 2024-11-19 17:11:09.000000000 +0000 @@ -412,6 +412,7 @@ memcpy(&soap_server_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); soap_server_object_handlers.offset = XtOffsetOf(soap_server_object, std); soap_server_object_handlers.free_obj = soap_server_object_free; + soap_server_object_handlers.clone_obj = NULL; /* Register SoapFault class */ soap_fault_class_entry = register_class_SoapFault(zend_ce_exception); @@ -837,6 +838,9 @@ if ((tmp = zend_hash_str_find(ht, "classmap", sizeof("classmap")-1)) != NULL && Z_TYPE_P(tmp) == IS_ARRAY) { + if (HT_IS_PACKED(Z_ARRVAL_P(tmp))) { + php_error_docref(NULL, E_ERROR, "'classmap' option must be an associative array"); + } service->class_map = zend_array_dup(Z_ARRVAL_P(tmp)); } @@ -2003,6 +2007,9 @@ } if ((tmp = zend_hash_str_find(ht, "classmap", sizeof("classmap")-1)) != NULL && Z_TYPE_P(tmp) == IS_ARRAY) { + if (HT_IS_PACKED(Z_ARRVAL_P(tmp))) { + php_error_docref(NULL, E_ERROR, "'classmap' option must be an associative array"); + } ZVAL_COPY(Z_CLIENT_CLASSMAP_P(this_ptr), tmp); } diff -Nru php8.2-8.2.24/ext/soap/tests/bug71610.phpt php8.2-8.2.26/ext/soap/tests/bug71610.phpt --- php8.2-8.2.24/ext/soap/tests/bug71610.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/soap/tests/bug71610.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -4,11 +4,20 @@ soap --SKIPIF-- --FILE-- blahblah(); } catch(SoapFault $e) { diff -Nru php8.2-8.2.24/ext/soap/tests/bugs/bug27722.phpt php8.2-8.2.26/ext/soap/tests/bugs/bug27722.phpt --- php8.2-8.2.24/ext/soap/tests/bugs/bug27722.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/soap/tests/bugs/bug27722.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -2,8 +2,6 @@ Bug #27722 (Segfault on schema without targetNamespace) --EXTENSIONS-- soap ---GET-- -wsdl --INI-- soap.wsdl_cache_enabled=0 --FILE-- diff -Nru php8.2-8.2.24/ext/soap/tests/bugs/bug27742.phpt php8.2-8.2.26/ext/soap/tests/bugs/bug27742.phpt --- php8.2-8.2.24/ext/soap/tests/bugs/bug27742.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/soap/tests/bugs/bug27742.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -2,8 +2,6 @@ Bug #27742 (WDSL SOAP Parsing Schema bug) --EXTENSIONS-- soap ---GET-- -wsdl --INI-- soap.wsdl_cache_enabled=0 --FILE-- diff -Nru php8.2-8.2.24/ext/soap/tests/bugs/bug62900.phpt php8.2-8.2.26/ext/soap/tests/bugs/bug62900.phpt --- php8.2-8.2.24/ext/soap/tests/bugs/bug62900.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/soap/tests/bugs/bug62900.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,95 @@ +--TEST-- +Bug #62900 (Wrong namespace on xsd import error message) +--EXTENSIONS-- +soap +--INI-- +soap.wsdl_cache_enabled=0 +--FILE-- + + + + + + + +XML; + +$wsdl_without_ns = << + + + + + + +XML; + +$xsd_with_wrong_ns = << + +XML; + +$xsd_without_ns = << + +XML; + +$combinations = [ + [$wsdl_with_ns, $xsd_with_wrong_ns], + [$wsdl_with_ns, $xsd_without_ns], + [$wsdl_without_ns, $xsd_with_wrong_ns], + [$wsdl_without_ns, $xsd_without_ns], +]; + +chdir(__DIR__); + +$args = ["-d", "display_startup_errors=0", "-d", "extension_dir=" . ini_get("extension_dir"), "-d", "extension=" . (substr(PHP_OS, 0, 3) == "WIN" ? "php_" : "") . "soap." . PHP_SHLIB_SUFFIX]; +if (php_ini_loaded_file()) { + // Necessary such that it works from a development directory in which case extension_dir might not be the real extension dir + $args[] = "-c"; + $args[] = php_ini_loaded_file(); +} + +foreach ($combinations as list($wsdl, $xsd)) { + file_put_contents(__DIR__."/bug62900.wsdl", $wsdl); + file_put_contents(__DIR__."/bug62900.xsd", $xsd); + + $proc = proc_open([PHP_BINARY, ...$args, __DIR__.'/bug62900_run'], [1 => ["pipe", "w"], 2 => ["pipe", "w"]], $pipes); + echo stream_get_contents($pipes[1]); + fclose($pipes[1]); + proc_close($proc); +} + +?> +--CLEAN-- + +--EXPECTF-- +Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing Schema: can't import schema from '%sbug62900.xsd', unexpected 'targetNamespace'='http://www.w3.org/XML/1998/namespacex', expected 'http://www.w3.org/XML/1998/namespace' in %s:%d +Stack trace: +#0 %s(%d): SoapClient->__construct(%s) +#1 {main} + thrown in %s on line %d + +Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing Schema: can't import schema from '%sbug62900.xsd', missing 'targetNamespace', expected 'http://www.w3.org/XML/1998/namespace' in %s:%d +Stack trace: +#0 %s(%d): SoapClient->__construct(%s) +#1 {main} + thrown in %s on line %d + +Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing Schema: can't import schema from '%sbug62900.xsd', unexpected 'targetNamespace'='http://www.w3.org/XML/1998/namespacex', expected no 'targetNamespace' in %s:%d +Stack trace: +#0 %s(%d): SoapClient->__construct(%s) +#1 {main} + thrown in %s on line %d + +Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't bind to service in %s:%d +Stack trace: +#0 %s(%d): SoapClient->__construct(%s) +#1 {main} + thrown in %s on line %d diff -Nru php8.2-8.2.24/ext/soap/tests/bugs/bug62900_run php8.2-8.2.26/ext/soap/tests/bugs/bug62900_run --- php8.2-8.2.24/ext/soap/tests/bugs/bug62900_run 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/soap/tests/bugs/bug62900_run 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,2 @@ +"http://testuri.org"]); +try { + clone $server; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Trying to clone an uncloneable object of class SoapServer diff -Nru php8.2-8.2.24/ext/soap/tests/bugs/gh16256.phpt php8.2-8.2.26/ext/soap/tests/bugs/gh16256.phpt --- php8.2-8.2.24/ext/soap/tests/bugs/gh16256.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/soap/tests/bugs/gh16256.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,25 @@ +--TEST-- +GH-16256 (Assertion failure in ext/soap/php_encoding.c:460) +--EXTENSIONS-- +soap +--FILE-- + $classmap]); +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} +try { + new SoapServer($wsdl, ["classmap" => $classmap]); +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +SoapClient::__construct(): 'classmap' option must be an associative array + +SOAP-ENV:ServerSoapServer::__construct(): 'classmap' option must be an associative array diff -Nru php8.2-8.2.24/ext/soap/tests/bugs/gh16259.phpt php8.2-8.2.26/ext/soap/tests/bugs/gh16259.phpt --- php8.2-8.2.24/ext/soap/tests/bugs/gh16259.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/soap/tests/bugs/gh16259.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,23 @@ +--TEST-- +GH-16259 (Soap segfault when classmap instantiation fails) +--EXTENSIONS-- +soap +--FILE-- + "CT_A1", "A2" => "CT_A2"); +$client = new SoapClient(__DIR__."/bug36575.wsdl", array("trace" => 1, "exceptions" => 0)); +$a2 = new CT_A2(); +$client->test($a2); +$soapRequest = $client->__getLastRequest(); + +$server = new SoapServer(__DIR__."/bug36575.wsdl", array("classmap" => $classMap)); +$server->handle($soapRequest); +?> +--EXPECT-- + +SOAP-ENV:ServerCannot instantiate abstract class CT_A1 diff -Nru php8.2-8.2.24/ext/soap/tests/bugs/gh16429.phpt php8.2-8.2.26/ext/soap/tests/bugs/gh16429.phpt --- php8.2-8.2.24/ext/soap/tests/bugs/gh16429.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/soap/tests/bugs/gh16429.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,22 @@ +--TEST-- +GH-16429 (Segmentation fault (access null pointer) in SoapClient) +--EXTENSIONS-- +soap +--FILE-- +send(10); +$fusion = $gen; +$client = new SoapClient(__DIR__."/../interop/Round2/GroupB/round2_groupB.wsdl",array("trace"=>1,"exceptions"=>0)); +try { + $client->echo2DStringArray($fusion); +} catch (Exception $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +string(10) "xxxxxxxxxx" +Cannot traverse an already closed generator diff -Nru php8.2-8.2.24/ext/soap/tests/server011.phpt php8.2-8.2.26/ext/soap/tests/server011.phpt --- php8.2-8.2.24/ext/soap/tests/server011.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/soap/tests/server011.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -1,5 +1,11 @@ --TEST-- SOAP Server 11: bind +--SKIPIF-- + --EXTENSIONS-- soap --GET-- diff -Nru php8.2-8.2.24/ext/soap/tests/server012.phpt php8.2-8.2.26/ext/soap/tests/server012.phpt --- php8.2-8.2.24/ext/soap/tests/server012.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/soap/tests/server012.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -1,5 +1,11 @@ --TEST-- SOAP Server 12: WSDL generation +--SKIPIF-- + --EXTENSIONS-- soap --GET-- diff -Nru php8.2-8.2.24/ext/sockets/sockets.c php8.2-8.2.26/ext/sockets/sockets.c --- php8.2-8.2.24/ext/sockets/sockets.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/sockets/sockets.c 2024-11-19 17:11:09.000000000 +0000 @@ -1211,6 +1211,11 @@ RETURN_THROWS(); } + if (ZEND_LONG_EXCEEDS_INT(arg1)) { + zend_argument_value_error(1, "must be between %d and %d", INT_MIN, INT_MAX); + RETURN_THROWS(); + } + RETURN_STRING(sockets_strerror(arg1)); } /* }}} */ @@ -1397,7 +1402,8 @@ /* overflow check */ /* Shouldthrow ? */ - if ((arg3 + 2) < 3) { + + if (arg3 <= 0 || arg3 > ZEND_LONG_MAX - 1) { RETURN_FALSE; } diff -Nru php8.2-8.2.24/ext/sockets/tests/gh16267.phpt php8.2-8.2.26/ext/sockets/tests/gh16267.phpt --- php8.2-8.2.24/ext/sockets/tests/gh16267.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/sockets/tests/gh16267.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,22 @@ +--TEST-- +GH-16267 - overflow on socket_strerror argument +--EXTENSIONS-- +sockets +--SKIPIF-- + +--FILE-- +getMessage() . PHP_EOL; +} +try { + socket_strerror(PHP_INT_MAX); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} +?> +--EXPECTF-- +socket_strerror(): Argument #1 ($error_code) must be between %s and %s +socket_strerror(): Argument #1 ($error_code) must be between %s and %s diff -Nru php8.2-8.2.24/ext/sockets/tests/socket_recv_overflow.phpt php8.2-8.2.26/ext/sockets/tests/socket_recv_overflow.phpt --- php8.2-8.2.24/ext/sockets/tests/socket_recv_overflow.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/sockets/tests/socket_recv_overflow.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,19 @@ +--TEST-- +socket_recvfrom overflow on length argument +--EXTENSIONS-- +sockets +--SKIPIF-- + +--EXPECT-- +bool(false) +bool(false) diff -Nru php8.2-8.2.24/ext/spl/spl_array.c php8.2-8.2.26/ext/spl/spl_array.c --- php8.2-8.2.24/ext/spl/spl_array.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/spl/spl_array.c 2024-11-19 17:11:09.000000000 +0000 @@ -555,13 +555,15 @@ if (Z_TYPE_P(data) == IS_INDIRECT) { data = Z_INDIRECT_P(data); if (Z_TYPE_P(data) != IS_UNDEF) { - zval_ptr_dtor(data); + zval garbage; + ZVAL_COPY_VALUE(&garbage, data); ZVAL_UNDEF(data); HT_FLAGS(ht) |= HASH_FLAG_HAS_EMPTY_IND; zend_hash_move_forward_ex(ht, spl_array_get_pos_ptr(ht, intern)); if (spl_array_is_object(intern)) { spl_array_skip_protected(intern, ht); } + zval_ptr_dtor(&garbage); } } else { zend_hash_del(ht, key.key); @@ -1052,8 +1054,10 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *array, zend_long ar_flags, bool just_array) { /* Handled by ZPP prior to this, or for __unserialize() before passing to here */ ZEND_ASSERT(Z_TYPE_P(array) == IS_ARRAY || Z_TYPE_P(array) == IS_OBJECT); + zval garbage; + ZVAL_UNDEF(&garbage); if (Z_TYPE_P(array) == IS_ARRAY) { - zval_ptr_dtor(&intern->array); + ZVAL_COPY_VALUE(&garbage, &intern->array); if (Z_REFCOUNT_P(array) == 1) { ZVAL_COPY(&intern->array, array); } else { @@ -1071,7 +1075,7 @@ } } else { if (Z_OBJ_HT_P(array) == &spl_handler_ArrayObject || Z_OBJ_HT_P(array) == &spl_handler_ArrayIterator) { - zval_ptr_dtor(&intern->array); + ZVAL_COPY_VALUE(&garbage, &intern->array); if (just_array) { spl_array_object *other = Z_SPLARRAY_P(array); ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK; @@ -1089,9 +1093,10 @@ zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Overloaded object of type %s is not compatible with %s", ZSTR_VAL(Z_OBJCE_P(array)->name), ZSTR_VAL(intern->std.ce->name)); + ZEND_ASSERT(Z_TYPE(garbage) == IS_UNDEF); return; } - zval_ptr_dtor(&intern->array); + ZVAL_COPY_VALUE(&garbage, &intern->array); ZVAL_COPY(&intern->array, array); } } @@ -1102,6 +1107,8 @@ zend_hash_iterator_del(intern->ht_iter); intern->ht_iter = (uint32_t)-1; } + + zval_ptr_dtor(&garbage); } /* }}} */ diff -Nru php8.2-8.2.24/ext/spl/spl_directory.c php8.2-8.2.26/ext/spl/spl_directory.c --- php8.2-8.2.24/ext/spl/spl_directory.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/spl/spl_directory.c 2024-11-19 17:11:09.000000000 +0000 @@ -668,7 +668,7 @@ if (intern->type == SPL_FS_DIR) { #ifdef HAVE_GLOB pnstr = spl_gen_private_prop_name(spl_ce_DirectoryIterator, "glob", sizeof("glob")-1); - if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) { + if (intern->u.dir.dirp && php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) { ZVAL_STR_COPY(&tmp, intern->path); } else { ZVAL_FALSE(&tmp); @@ -2042,22 +2042,27 @@ PHP_METHOD(SplFileObject, __construct) { spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS)); + zend_string *file_name = NULL; zend_string *open_mode = ZSTR_CHAR('r'); + zval *stream_context = NULL; bool use_include_path = 0; size_t path_len; zend_error_handling error_handling; - intern->u.file.open_mode = ZSTR_CHAR('r'); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|Sbr!", &file_name, &open_mode, &use_include_path, &stream_context) == FAILURE) { + RETURN_THROWS(); + } - if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|Sbr!", - &intern->file_name, &open_mode, - &use_include_path, &intern->u.file.zcontext) == FAILURE) { - intern->u.file.open_mode = NULL; - intern->file_name = NULL; + /* Prevent reinitialization of Object */ + if (UNEXPECTED(intern->u.file.stream)) { + zend_throw_error(NULL, "Cannot call constructor twice"); RETURN_THROWS(); } intern->u.file.open_mode = zend_string_copy(open_mode); + /* file_name and zcontext are copied by spl_filesystem_file_open() */ + intern->file_name = file_name; + intern->u.file.zcontext = stream_context; /* spl_filesystem_file_open() can generate E_WARNINGs which we want to promote to exceptions */ zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling); @@ -2096,6 +2101,12 @@ RETURN_THROWS(); } + /* Prevent reinitialization of Object */ + if (UNEXPECTED(intern->u.file.stream)) { + zend_throw_error(NULL, "Cannot call constructor twice"); + RETURN_THROWS(); + } + if (max_memory < 0) { file_name = zend_string_init("php://memory", sizeof("php://memory")-1, 0); } else if (ZEND_NUM_ARGS()) { diff -Nru php8.2-8.2.24/ext/spl/spl_dllist.c php8.2-8.2.26/ext/spl/spl_dllist.c --- php8.2-8.2.24/ext/spl/spl_dllist.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/spl/spl_dllist.c 2024-11-19 17:11:09.000000000 +0000 @@ -44,10 +44,13 @@ efree(elem); \ } -#define SPL_LLIST_CHECK_DELREF(elem) if ((elem) && !--SPL_LLIST_RC(elem)) { \ +#define SPL_LLIST_CHECK_DELREF_EX(elem, on_free) if ((elem) && !--SPL_LLIST_RC(elem)) { \ efree(elem); \ + on_free \ } +#define SPL_LLIST_CHECK_DELREF(elem) SPL_LLIST_CHECK_DELREF_EX(elem, ;) + #define SPL_LLIST_ADDREF(elem) SPL_LLIST_RC(elem)++ #define SPL_LLIST_CHECK_ADDREF(elem) if (elem) SPL_LLIST_RC(elem)++ @@ -737,8 +740,10 @@ if (element != NULL) { /* the element is replaced, delref the old one as in * SplDoublyLinkedList::pop() */ - zval_ptr_dtor(&element->data); + zval garbage; + ZVAL_COPY_VALUE(&garbage, &element->data); ZVAL_COPY(&element->data, value); + zval_ptr_dtor(&garbage); } else { zval_ptr_dtor(value); zend_argument_error(spl_ce_OutOfRangeException, 1, "is an invalid offset"); @@ -1022,8 +1027,12 @@ smart_str_appendc(&buf, ':'); next = current->next; + SPL_LLIST_CHECK_ADDREF(next); + php_var_serialize(&buf, ¤t->data, &var_hash); + SPL_LLIST_CHECK_DELREF_EX(next, break;); + current = next; } diff -Nru php8.2-8.2.24/ext/spl/spl_fixedarray.c php8.2-8.2.26/ext/spl/spl_fixedarray.c --- php8.2-8.2.24/ext/spl/spl_fixedarray.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/spl/spl_fixedarray.c 2024-11-19 17:11:09.000000000 +0000 @@ -484,8 +484,10 @@ return; } else { intern->array.should_rebuild_properties = true; - zval_ptr_dtor(&(intern->array.elements[index])); + zval garbage; + ZVAL_COPY_VALUE(&garbage, &intern->array.elements[index]); ZVAL_NULL(&intern->array.elements[index]); + zval_ptr_dtor(&garbage); } } diff -Nru php8.2-8.2.24/ext/spl/spl_heap.c php8.2-8.2.26/ext/spl/spl_heap.c --- php8.2-8.2.24/ext/spl/spl_heap.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/spl/spl_heap.c 2024-11-19 17:11:09.000000000 +0000 @@ -32,6 +32,7 @@ #define PTR_HEAP_BLOCK_SIZE 64 #define SPL_HEAP_CORRUPTED 0x00000001 +#define SPL_HEAP_WRITE_LOCKED 0x00000002 zend_object_handlers spl_handler_SplHeap; zend_object_handlers spl_handler_SplPriorityQueue; @@ -278,12 +279,16 @@ heap->max_size *= 2; } + heap->flags |= SPL_HEAP_WRITE_LOCKED; + /* sifting up */ for (i = heap->count; i > 0 && heap->cmp(spl_heap_elem(heap, (i-1)/2), elem, cmp_userdata) < 0; i = (i-1)/2) { spl_heap_elem_copy(heap, spl_heap_elem(heap, i), spl_heap_elem(heap, (i-1)/2)); } heap->count++; + heap->flags &= ~SPL_HEAP_WRITE_LOCKED; + if (EG(exception)) { /* exception thrown during comparison */ heap->flags |= SPL_HEAP_CORRUPTED; @@ -311,6 +316,8 @@ return FAILURE; } + heap->flags |= SPL_HEAP_WRITE_LOCKED; + if (elem) { spl_heap_elem_copy(heap, elem, spl_heap_elem(heap, 0)); } else { @@ -334,6 +341,8 @@ } } + heap->flags &= ~SPL_HEAP_WRITE_LOCKED; + if (EG(exception)) { /* exception thrown during comparison */ heap->flags |= SPL_HEAP_CORRUPTED; @@ -374,10 +383,14 @@ static void spl_ptr_heap_destroy(spl_ptr_heap *heap) { /* {{{ */ int i; + heap->flags |= SPL_HEAP_WRITE_LOCKED; + for (i = 0; i < heap->count; ++i) { heap->dtor(spl_heap_elem(heap, i)); } + heap->flags &= ~SPL_HEAP_WRITE_LOCKED; + efree(heap->elements); efree(heap); } @@ -597,6 +610,21 @@ } /* }}} */ +static zend_result spl_heap_consistency_validations(const spl_heap_object *intern, bool write) +{ + if (intern->heap->flags & SPL_HEAP_CORRUPTED) { + zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + return FAILURE; + } + + if (write && (intern->heap->flags & SPL_HEAP_WRITE_LOCKED)) { + zend_throw_exception(spl_ce_RuntimeException, "Heap cannot be changed when it is already being modified.", 0); + return FAILURE; + } + + return SUCCESS; +} + /* {{{ Push $value on the heap */ PHP_METHOD(SplHeap, insert) { @@ -609,8 +637,7 @@ intern = Z_SPLHEAP_P(ZEND_THIS); - if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) { RETURN_THROWS(); } @@ -632,8 +659,7 @@ intern = Z_SPLHEAP_P(ZEND_THIS); - if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) { RETURN_THROWS(); } @@ -658,8 +684,7 @@ intern = Z_SPLHEAP_P(ZEND_THIS); - if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) { RETURN_THROWS(); } @@ -699,8 +724,7 @@ intern = Z_SPLHEAP_P(ZEND_THIS); - if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) { RETURN_THROWS(); } @@ -726,8 +750,7 @@ intern = Z_SPLHEAP_P(ZEND_THIS); - if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + if (UNEXPECTED(spl_heap_consistency_validations(intern, false) != SUCCESS)) { RETURN_THROWS(); } @@ -837,8 +860,7 @@ intern = Z_SPLHEAP_P(ZEND_THIS); - if (intern->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + if (UNEXPECTED(spl_heap_consistency_validations(intern, false) != SUCCESS)) { RETURN_THROWS(); } @@ -902,8 +924,7 @@ { spl_heap_object *object = Z_SPLHEAP_P(&iter->data); - if (object->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + if (UNEXPECTED(spl_heap_consistency_validations(object, false) != SUCCESS)) { return NULL; } @@ -920,8 +941,7 @@ zend_user_iterator *user_it = (zend_user_iterator *) iter; spl_heap_object *object = Z_SPLHEAP_P(&iter->data); - if (object->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + if (UNEXPECTED(spl_heap_consistency_validations(object, false) != SUCCESS)) { return NULL; } @@ -949,8 +969,7 @@ { spl_heap_object *object = Z_SPLHEAP_P(&iter->data); - if (object->heap->flags & SPL_HEAP_CORRUPTED) { - zend_throw_exception(spl_ce_RuntimeException, "Heap is corrupted, heap properties are no longer ensured.", 0); + if (UNEXPECTED(spl_heap_consistency_validations(object, false) != SUCCESS)) { return; } diff -Nru php8.2-8.2.24/ext/spl/spl_iterators.c php8.2-8.2.26/ext/spl/spl_iterators.c --- php8.2-8.2.24/ext/spl/spl_iterators.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/spl/spl_iterators.c 2024-11-19 17:11:09.000000000 +0000 @@ -538,6 +538,20 @@ return SUCCESS; } +static void spl_RecursiveIteratorIterator_free_iterators(spl_recursive_it_object *object) +{ + if (object->iterators) { + while (object->level >= 0) { + zend_object_iterator *sub_iter = object->iterators[object->level].iterator; + zend_iterator_dtor(sub_iter); + zval_ptr_dtor(&object->iterators[object->level].zobject); + object->level--; + } + efree(object->iterators); + object->iterators = NULL; + } +} + static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_base, zend_class_entry *ce_inner, recursive_it_it_type rit_type) { zval *object = ZEND_THIS; @@ -604,6 +618,7 @@ } intern = Z_SPLRECURSIVE_IT_P(object); + spl_RecursiveIteratorIterator_free_iterators(intern); intern->iterators = emalloc(sizeof(spl_sub_iterator)); intern->level = 0; intern->mode = mode; @@ -650,6 +665,7 @@ intern->iterators[0].getchildren = NULL; if (EG(exception)) { + // TODO: use spl_RecursiveIteratorIterator_free_iterators zend_object_iterator *sub_iter; while (intern->level >= 0) { @@ -958,16 +974,7 @@ { spl_recursive_it_object *object = spl_recursive_it_from_obj(_object); - if (object->iterators) { - while (object->level >= 0) { - zend_object_iterator *sub_iter = object->iterators[object->level].iterator; - zend_iterator_dtor(sub_iter); - zval_ptr_dtor(&object->iterators[object->level].zobject); - object->level--; - } - efree(object->iterators); - object->iterators = NULL; - } + spl_RecursiveIteratorIterator_free_iterators(object); zend_object_std_dtor(&object->std); for (size_t i = 0; i < 6; i++) { diff -Nru php8.2-8.2.24/ext/spl/spl_observer.c php8.2-8.2.26/ext/spl/spl_observer.c --- php8.2-8.2.24/ext/spl/spl_observer.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/spl/spl_observer.c 2024-11-19 17:11:09.000000000 +0000 @@ -746,8 +746,10 @@ if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) { RETURN_NULL(); } - zval_ptr_dtor(&element->inf); + zval garbage; + ZVAL_COPY_VALUE(&garbage, &element->inf); ZVAL_COPY(&element->inf, inf); + zval_ptr_dtor(&garbage); } /* }}} */ /* {{{ Moves position forward */ @@ -795,11 +797,18 @@ RETURN_NULL(); } ZVAL_OBJ(&obj, element->obj); + + /* Protect against modification; we need a full copy because the data may be refcounted. */ + zval inf_copy; + ZVAL_COPY(&inf_copy, &element->inf); + php_var_serialize(&buf, &obj, &var_hash); smart_str_appendc(&buf, ','); - php_var_serialize(&buf, &element->inf, &var_hash); + php_var_serialize(&buf, &inf_copy, &var_hash); smart_str_appendc(&buf, ';'); zend_hash_move_forward_ex(&intern->storage, &pos); + + zval_ptr_dtor(&inf_copy); } /* members */ diff -Nru php8.2-8.2.24/ext/spl/tests/gh14687.phpt php8.2-8.2.26/ext/spl/tests/gh14687.phpt --- php8.2-8.2.24/ext/spl/tests/gh14687.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh14687.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,49 @@ +--TEST-- +GH-14687 segfault on debugging SplObjectStorage instance after __destruct. +--CREDITS-- +YuanchengJiang +--EXTENSIONS-- +phar +--INI-- +phar.require_hash=0 +phar.readonly=0 +--FILE-- + +--CLEAN-- + +--EXPECT-- +object(SplObjectStorage)#2 (1) { + ["storage":"SplObjectStorage":private]=> + array(1) { + [0]=> + array(2) { + ["obj"]=> + object(Phar)#1 (3) { + ["pathName":"SplFileInfo":private]=> + string(0) "" + ["glob":"DirectoryIterator":private]=> + bool(false) + ["subPathName":"RecursiveDirectoryIterator":private]=> + string(0) "" + } + ["inf"]=> + object(HasDestructor)#3 (0) { + } + } + } +} diff -Nru php8.2-8.2.24/ext/spl/tests/gh16337.phpt php8.2-8.2.26/ext/spl/tests/gh16337.phpt --- php8.2-8.2.24/ext/spl/tests/gh16337.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16337.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,49 @@ +--TEST-- +GH-16337 (Use-after-free in SplHeap) +--FILE-- +extract(); + } catch (Throwable $e) { + echo $e->getMessage(), "\n"; + } + try { + $heap->insert(1); + } catch (Throwable $e) { + echo $e->getMessage(), "\n"; + } + echo $heap->top(), "\n"; + return "0"; + } +} + +$heap = new SplMinHeap; +for ($i = 0; $i < 100; $i++) { + $heap->insert((string) $i); +} +$heap->insert(new C); + +?> +--EXPECT-- +Heap cannot be changed when it is already being modified. +Heap cannot be changed when it is already being modified. +0 +Heap cannot be changed when it is already being modified. +Heap cannot be changed when it is already being modified. +0 +Heap cannot be changed when it is already being modified. +Heap cannot be changed when it is already being modified. +0 +Heap cannot be changed when it is already being modified. +Heap cannot be changed when it is already being modified. +0 +Heap cannot be changed when it is already being modified. +Heap cannot be changed when it is already being modified. +0 +Heap cannot be changed when it is already being modified. +Heap cannot be changed when it is already being modified. +0 diff -Nru php8.2-8.2.24/ext/spl/tests/gh16464.phpt php8.2-8.2.26/ext/spl/tests/gh16464.phpt --- php8.2-8.2.24/ext/spl/tests/gh16464.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16464.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,29 @@ +--TEST-- +GH-16464: Use-after-free in SplDoublyLinkedList::offsetSet() when modifying list in destructor of overwritten object +--FILE-- +pop()); + } +} + +$list = new SplDoublyLinkedList; +$list->add(0, new C); +$list[0] = 42; +var_dump($list); + +?> +--EXPECTF-- +int(42) +object(SplDoublyLinkedList)#%d (2) { + ["flags":"SplDoublyLinkedList":private]=> + int(0) + ["dllist":"SplDoublyLinkedList":private]=> + array(0) { + } +} diff -Nru php8.2-8.2.24/ext/spl/tests/gh16477-2.phpt php8.2-8.2.26/ext/spl/tests/gh16477-2.phpt --- php8.2-8.2.24/ext/spl/tests/gh16477-2.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16477-2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,19 @@ +--TEST-- +GH-16477-2: Memory leak when calling SplTempFileObject::__constructor() twice +--FILE-- +__construct(); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +$obj->__debugInfo(); + +?> +DONE +--EXPECT-- +Error: Cannot call constructor twice +DONE diff -Nru php8.2-8.2.24/ext/spl/tests/gh16477.phpt php8.2-8.2.26/ext/spl/tests/gh16477.phpt --- php8.2-8.2.24/ext/spl/tests/gh16477.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16477.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,19 @@ +--TEST-- +GH-16477: Segmentation fault when calling __debugInfo() after failed SplFileObject::__constructor +--FILE-- +__construct(); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} +$obj->__debugInfo(); + +?> +DONE +--EXPECT-- +ArgumentCountError: SplFileObject::__construct() expects at least 1 argument, 0 given +DONE diff -Nru php8.2-8.2.24/ext/spl/tests/gh16478.phpt php8.2-8.2.26/ext/spl/tests/gh16478.phpt --- php8.2-8.2.24/ext/spl/tests/gh16478.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16478.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,21 @@ +--TEST-- +GH-16478: Use-after-free in SplFixedArray::unset() +--FILE-- +setSize(0); + } +} + +$arr = new SplFixedArray(2); +$arr[0] = new C; +unset($arr[0]); +var_dump($arr); + +?> +--EXPECT-- +object(SplFixedArray)#1 (0) { +} diff -Nru php8.2-8.2.24/ext/spl/tests/gh16479.phpt php8.2-8.2.26/ext/spl/tests/gh16479.phpt --- php8.2-8.2.24/ext/spl/tests/gh16479.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16479.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,25 @@ +--TEST-- +GH-16479: Use-after-free in SplObjectStorage::setInfo() +--FILE-- +removeAll($store); + } +} + +$o = new stdClass; +$store = new SplObjectStorage; +$store[$o] = new C; +$store->setInfo(1); +var_dump($store); + +?> +--EXPECT-- +object(SplObjectStorage)#2 (1) { + ["storage":"SplObjectStorage":private]=> + array(0) { + } +} diff -Nru php8.2-8.2.24/ext/spl/tests/gh16588.phpt php8.2-8.2.26/ext/spl/tests/gh16588.phpt --- php8.2-8.2.24/ext/spl/tests/gh16588.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16588.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,22 @@ +--TEST-- +GH-16588 (UAF in Observer->serialize) +--CREDITS-- +chibinz +--FILE-- +removeAll($store); + return []; + } +} + +$store = new SplObjectStorage; +$store[new C] = new stdClass; +var_dump($store->serialize()); + +?> +--EXPECT-- +string(47) "x:i:1;O:1:"C":0:{},O:8:"stdClass":0:{};m:a:0:{}" diff -Nru php8.2-8.2.24/ext/spl/tests/gh16589.phpt php8.2-8.2.26/ext/spl/tests/gh16589.phpt --- php8.2-8.2.24/ext/spl/tests/gh16589.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16589.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,23 @@ +--TEST-- +GH-16589 (UAF in SplDoublyLinked->serialize()) +--CREDITS-- +chibinz +--FILE-- +pop(); + return []; + } +} + +$list = new SplDoublyLinkedList; +$list->add(0, new C); +$list->add(1, 1); +var_dump($list->serialize()); + +?> +--EXPECT-- +string(17) "i:0;:O:1:"C":0:{}" diff -Nru php8.2-8.2.24/ext/spl/tests/gh16604_1.phpt php8.2-8.2.26/ext/spl/tests/gh16604_1.phpt --- php8.2-8.2.24/ext/spl/tests/gh16604_1.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16604_1.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,15 @@ +--TEST-- +GH-16604 (Memory leaks in SPL constructors) - recursive iterators +--FILE-- +__construct( $traversable ); + +$obj = new RecursiveTreeIterator( $traversable ); +$obj->__construct( $traversable ); + +?> +--EXPECT-- diff -Nru php8.2-8.2.24/ext/spl/tests/gh16604_2.phpt php8.2-8.2.26/ext/spl/tests/gh16604_2.phpt --- php8.2-8.2.24/ext/spl/tests/gh16604_2.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16604_2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,21 @@ +--TEST-- +GH-16604 (Memory leaks in SPL constructors) - SplFileObject +--FILE-- +__construct(__DIR__.'/gh16604_2.tmp'); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--CLEAN-- + +--EXPECT-- +Cannot call constructor twice diff -Nru php8.2-8.2.24/ext/spl/tests/gh16646.phpt php8.2-8.2.26/ext/spl/tests/gh16646.phpt --- php8.2-8.2.24/ext/spl/tests/gh16646.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16646.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,32 @@ +--TEST-- +GH-16646: Use-after-free in ArrayObject::unset() with destructor +--FILE-- +b = $arg; + } +} + +class C { + function __destruct() { + global $arr; + echo __METHOD__, "\n"; + $arr->exchangeArray([]); + } +} + +$arr = new ArrayObject(new B(new C)); +unset($arr["b"]); +var_dump($arr); + +?> +--EXPECT-- +C::__destruct +object(ArrayObject)#1 (1) { + ["storage":"ArrayObject":private]=> + array(0) { + } +} diff -Nru php8.2-8.2.24/ext/spl/tests/gh16646_2.phpt php8.2-8.2.26/ext/spl/tests/gh16646_2.phpt --- php8.2-8.2.24/ext/spl/tests/gh16646_2.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/spl/tests/gh16646_2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,25 @@ +--TEST-- +GH-16646: Use-after-free in ArrayObject::exchangeArray() with destructor +--FILE-- +exchangeArray([]); + } +} + +$arr = new ArrayObject(new C); +$arr->exchangeArray([]); +var_dump($arr); + +?> +--EXPECT-- +C::__destruct +object(ArrayObject)#1 (1) { + ["storage":"ArrayObject":private]=> + array(0) { + } +} diff -Nru php8.2-8.2.24/ext/standard/array.c php8.2-8.2.26/ext/standard/array.c --- php8.2-8.2.24/ext/standard/array.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/standard/array.c 2024-11-19 17:11:09.000000000 +0000 @@ -705,9 +705,9 @@ ZEND_PARSE_PARAMETERS_END(); if (fold_case) { - zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_case_compare, 0); + zend_array_sort(Z_ARRVAL_P(array), php_array_natural_case_compare, 0); } else { - zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_compare, 0); + zend_array_sort(Z_ARRVAL_P(array), php_array_natural_compare, 0); } RETURN_TRUE; @@ -743,7 +743,7 @@ cmp = php_get_data_compare_func(sort_type, 0); - zend_hash_sort(Z_ARRVAL_P(array), cmp, 0); + zend_array_sort(Z_ARRVAL_P(array), cmp, 0); RETURN_TRUE; } @@ -764,7 +764,7 @@ cmp = php_get_data_compare_func(sort_type, 1); - zend_hash_sort(Z_ARRVAL_P(array), cmp, 0); + zend_array_sort(Z_ARRVAL_P(array), cmp, 0); RETURN_TRUE; } @@ -785,7 +785,7 @@ cmp = php_get_data_compare_func(sort_type, 0); - zend_hash_sort(Z_ARRVAL_P(array), cmp, 1); + zend_array_sort(Z_ARRVAL_P(array), cmp, 1); RETURN_TRUE; } @@ -806,7 +806,7 @@ cmp = php_get_data_compare_func(sort_type, 1); - zend_hash_sort(Z_ARRVAL_P(array), cmp, 1); + zend_array_sort(Z_ARRVAL_P(array), cmp, 1); RETURN_TRUE; } @@ -904,7 +904,7 @@ /* Copy array, so the in-place modifications will not be visible to the callback function */ arr = zend_array_dup(arr); - zend_hash_sort(arr, compare_func, renumber); + zend_array_sort(arr, compare_func, renumber); zval garbage; ZVAL_COPY_VALUE(&garbage, array); @@ -3700,7 +3700,6 @@ } ZEND_ASSERT(!Z_ISREF_P(dest_entry) || Z_REFCOUNT_P(dest_entry) > 1); - SEPARATE_ZVAL(dest_entry); dest_zval = dest_entry; if (Z_TYPE_P(dest_zval) == IS_NULL) { @@ -3709,6 +3708,8 @@ } else { convert_to_array(dest_zval); } + SEPARATE_ZVAL(dest_zval); + ZVAL_UNDEF(&tmp); if (Z_TYPE_P(src_zval) == IS_OBJECT) { ZVAL_COPY(&tmp, src_zval); diff -Nru php8.2-8.2.24/ext/standard/assert.c php8.2-8.2.26/ext/standard/assert.c --- php8.2-8.2.24/ext/standard/assert.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/standard/assert.c 2024-11-19 17:11:09.000000000 +0000 @@ -195,6 +195,11 @@ } if (ASSERTG(bail)) { + if (EG(exception)) { + /* The callback might have thrown. Use E_WARNING to print the + * exception so we can avoid bailout and use unwind_exit. */ + zend_exception_error(EG(exception), E_WARNING); + } zend_throw_unwind_exit(); RETURN_THROWS(); } else { diff -Nru php8.2-8.2.24/ext/standard/filters.c php8.2-8.2.26/ext/standard/filters.c --- php8.2-8.2.24/ext/standard/filters.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/standard/filters.c 2024-11-19 17:11:09.000000000 +0000 @@ -996,6 +996,9 @@ } break; case 5: { + if (icnt == 0) { + goto out; + } if (!inst->lbchars && lb_cnt == 1 && *ps == '\n') { /* auto-detect soft line breaks, found network line break */ lb_cnt = lb_ptr = 0; @@ -1009,15 +1012,13 @@ /* soft line break */ lb_cnt = lb_ptr = 0; scan_stat = 0; - } else if (icnt > 0) { + } else { if (*ps == (unsigned char)inst->lbchars[lb_cnt]) { lb_cnt++; ps++, icnt--; } else { scan_stat = 6; /* no break for short-cut */ } - } else { - goto out; } } break; diff -Nru php8.2-8.2.24/ext/standard/http_fopen_wrapper.c php8.2-8.2.26/ext/standard/http_fopen_wrapper.c --- php8.2-8.2.24/ext/standard/http_fopen_wrapper.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/standard/http_fopen_wrapper.c 2024-11-19 17:11:09.000000000 +0000 @@ -183,6 +183,11 @@ return NULL; } + /* Should we send the entire path in the request line, default to no. */ + if (context && (tmpzval = php_stream_context_get_option(context, "http", "request_fulluri")) != NULL) { + request_fulluri = zend_is_true(tmpzval); + } + use_ssl = resource->scheme && (ZSTR_LEN(resource->scheme) > 4) && ZSTR_VAL(resource->scheme)[4] == 's'; /* choose default ports */ if (use_ssl && resource->port == 0) @@ -201,6 +206,13 @@ } } + if (request_fulluri && (strchr(path, '\n') != NULL || strchr(path, '\r') != NULL)) { + php_stream_wrapper_log_error(wrapper, options, "HTTP wrapper full URI path does not allow CR or LF characters"); + php_url_free(resource); + zend_string_release(transport_string); + return NULL; + } + if (context && (tmpzval = php_stream_context_get_option(context, wrapper->wops->label, "timeout")) != NULL) { double d = zval_get_double(tmpzval); #ifndef PHP_WIN32 @@ -381,12 +393,6 @@ smart_str_appends(&req_buf, "GET "); } - /* Should we send the entire path in the request line, default to no. */ - if (!request_fulluri && context && - (tmpzval = php_stream_context_get_option(context, "http", "request_fulluri")) != NULL) { - request_fulluri = zend_is_true(tmpzval); - } - if (request_fulluri) { /* Ask for everything */ smart_str_appends(&req_buf, path); diff -Nru php8.2-8.2.24/ext/standard/pack.c php8.2-8.2.26/ext/standard/pack.c --- php8.2-8.2.24/ext/standard/pack.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/standard/pack.c 2024-11-19 17:11:09.000000000 +0000 @@ -979,6 +979,13 @@ zend_string *buf; zend_long ipos, opos; + + if (size > INT_MAX / 2) { + zend_string_release(real_name); + zend_argument_value_error(1, "repeater must be less than or equal to %d", INT_MAX / 2); + RETURN_THROWS(); + } + /* If size was given take minimum of len and size */ if (size >= 0 && len > (size * 2)) { len = size * 2; diff -Nru php8.2-8.2.24/ext/standard/tests/array/gh16053.phpt php8.2-8.2.26/ext/standard/tests/array/gh16053.phpt --- php8.2-8.2.24/ext/standard/tests/array/gh16053.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/standard/tests/array/gh16053.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,28 @@ +--TEST-- +GH-16053: Assertion failure in Zend/zend_hash.c +--FILE-- + $x); +$arr2 = array("string" => "hello"); +var_dump($arr1); +var_dump(array_merge_recursive($arr1, $arr2)); + +?> +--EXPECTF-- +array(1) { + ["string"]=> + object(test)#%d (0) { + } +} +array(1) { + ["string"]=> + array(1) { + [0]=> + string(5) "hello" + } +} diff -Nru php8.2-8.2.24/ext/standard/tests/file/file_get_contents_basic.phpt php8.2-8.2.26/ext/standard/tests/file/file_get_contents_basic.phpt --- php8.2-8.2.24/ext/standard/tests/file/file_get_contents_basic.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/standard/tests/file/file_get_contents_basic.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -13,15 +13,15 @@ echo "-- Testing with simple valid data file --\n"; -create_files($file_path, 1, "text", 0755, 100, "w", "file", 1, "byte"); -var_dump( file_get_contents($file_path."/file1.tmp") ); -delete_files($file_path, 1); +create_files($file_path, 1, "text", 0755, 100, "w", "file_get_contents_basic", 1, "byte"); +var_dump( file_get_contents($file_path."/file_get_contents_basic1.tmp") ); +delete_files($file_path, 1, "file_get_contents_basic", 1); echo "\n-- Testing with empty file --\n"; -create_files($file_path, 1, "empty", 0755, 100, "w", "file", 1, "byte"); -var_dump( file_get_contents($file_path."/file1.tmp") ); -delete_files($file_path, 1); +create_files($file_path, 1, "empty", 0755, 100, "w", "file_get_contents_basic", 1, "byte"); +var_dump( file_get_contents($file_path."/file_get_contents_basic1.tmp") ); +delete_files($file_path, 1, "file_get_contents_basic", 1); echo "\n*** Done ***"; ?> diff -Nru php8.2-8.2.24/ext/standard/tests/file/file_get_contents_error.phpt php8.2-8.2.26/ext/standard/tests/file/file_get_contents_error.phpt --- php8.2-8.2.24/ext/standard/tests/file/file_get_contents_error.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/standard/tests/file/file_get_contents_error.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -13,17 +13,17 @@ echo "\n-- Testing with Non-existing file --\n"; print( file_get_contents("/no/such/file/or/dir") ); -create_files($file_path, 1, "text", 0755, 100, "w", "file", 1, "byte"); +create_files($file_path, 1, "text", 0755, 100, "w", "file_get_contents_error", 1, "byte"); $file_handle = fopen($file_path."/file_put_contents_error.tmp", "w"); echo "\n-- Testing for invalid negative maxlen values --\n"; try { - file_get_contents($file_path."/file1.tmp", FALSE, $file_handle, 0, -5); + file_get_contents($file_path."/file_get_contents_error1.tmp", FALSE, $file_handle, 0, -5); } catch (ValueError $exception) { echo $exception->getMessage() . "\n"; } -delete_files($file_path, 1); +delete_files($file_path, 1, "file_get_contents_error", 1); fclose($file_handle); unlink($file_path."/file_put_contents_error.tmp"); diff -Nru php8.2-8.2.24/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt php8.2-8.2.26/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt --- php8.2-8.2.24/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/standard/tests/filters/ghsa-r977-prxv-hc43.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,12 @@ +--TEST-- +GHSA-r977-prxv-hc43: Single byte overread with convert.quoted-printable-decode filter +--FILE-- + +--EXPECT-- +string(8190) "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX" diff -Nru php8.2-8.2.24/ext/standard/tests/general_functions/phpinfo.phpt php8.2-8.2.26/ext/standard/tests/general_functions/phpinfo.phpt --- php8.2-8.2.24/ext/standard/tests/general_functions/phpinfo.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/standard/tests/general_functions/phpinfo.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -16,21 +16,21 @@ PHP Version => %s System => %s -Build Date => %s%a +Build Date => %r(.+?)%r Configure Command => %s Server API => Command Line Interface Virtual Directory Support => %s Configuration File (php.ini) Path => %s -Loaded Configuration File => %a -Scan this dir for additional .ini files => %a -Additional .ini files parsed => %a +Loaded Configuration File => %r(.+?)%r +Scan this dir for additional .ini files => %r(.+?)%r +Additional .ini files parsed => %r(.+?)%r PHP API => %d PHP Extension => %d Zend Extension => %d Zend Extension Build => API%s PHP Extension Build => API%s Debug Build => %s -Thread Safety => %s%A +Thread Safety => %r(.+?)%r Zend Signal Handling => %s Zend Memory Manager => %s Zend Multibyte Support => %s @@ -42,22 +42,22 @@ Registered Stream Socket Transports => %s Registered Stream Filters => %s -%a +%r(.+?)%r _______________________________________________________________________ Configuration -%A +%r(.*?)%r Core -%A +%r(.*?)%r Additional Modules -%A +%r(.*?)%r Environment -%A +%r(.*?)%r PHP Variables -%A +%r(.*?)%r PHP License -%A +%r(.*?)%r bool(true) -- phpinfo() @@ -66,5 +66,5 @@ phpinfo() PHP License -%a +%r(.+?)%r bool(true) diff -Nru php8.2-8.2.24/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt php8.2-8.2.26/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt --- php8.2-8.2.24/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/standard/tests/http/ghsa-c5f2-jwm7-mmq2.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,28 @@ +--TEST-- +GHSA-c5f2-jwm7-mmq2 (Configuring a proxy in a stream context might allow for CRLF injection in URIs) +--INI-- +allow_url_fopen=1 +--CONFLICTS-- +server +--FILE-- + ['proxy' => 'tcp://' . $host, 'request_fulluri' => true]]); +echo file_get_contents("http://$host/$userinput", false, $context); +?> +--EXPECTF-- +Warning: file_get_contents(http://localhost:%d/index.php HTTP/1.1 +Host: localhost:%d + +GET /index2.php HTTP/1.1 +Host: localhost:%d + +GET /index.php): Failed to open stream: HTTP wrapper full URI path does not allow CR or LF characters in %s on line %d diff -Nru php8.2-8.2.24/ext/standard/tests/streams/gh15908.phpt php8.2-8.2.26/ext/standard/tests/streams/gh15908.phpt --- php8.2-8.2.24/ext/standard/tests/streams/gh15908.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/standard/tests/streams/gh15908.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,38 @@ +--TEST-- +GH-15908 (leak / assertion failure in streams.c) +--CREDITS-- +YuanchengJiang +LuMingYinDetect +--FILE-- +s++ == 0) + return "a\nbb\ncc"; + return ""; + } + function stream_eof() { + return $this->s >= 2; + } +} +touch(__DIR__."/gh15908.tmp"); +stream_wrapper_register("test", "TestStream"); +$f = fopen("test://", "r"); +try { + file_put_contents(__DIR__."/gh15908.tmp", $f, FILE_USE_INCLUDE_PATH, $f); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +?> +--CLEAN-- + +--EXPECT-- +file_put_contents(): supplied resource is not a valid Stream-Context resource diff -Nru php8.2-8.2.24/ext/standard/tests/streams/gh15937.phpt php8.2-8.2.26/ext/standard/tests/streams/gh15937.phpt --- php8.2-8.2.24/ext/standard/tests/streams/gh15937.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/standard/tests/streams/gh15937.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,16 @@ +--TEST-- +GH-15937 (stream overflow on timeout setting) +--SKIPIF-- + +--FILE-- + [ + 'timeout' => PHP_INT_MAX, + ], +]; +$ctx = stream_context_create($config); +var_dump(fopen("http://www.example.com", "r", false, $ctx)); +?> +--EXPECTF-- +resource(%d) of type (stream) diff -Nru php8.2-8.2.24/ext/standard/tests/streams/gh15980.phpt php8.2-8.2.26/ext/standard/tests/streams/gh15980.phpt --- php8.2-8.2.24/ext/standard/tests/streams/gh15980.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/standard/tests/streams/gh15980.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,12 @@ +--TEST-- +GH-15980 (Signed integer overflow in main/streams/streams.c) +--FILE-- + 1); +?> +--EXPECT-- +bool(true) diff -Nru php8.2-8.2.24/ext/standard/tests/strings/gh15613.phpt php8.2-8.2.26/ext/standard/tests/strings/gh15613.phpt --- php8.2-8.2.24/ext/standard/tests/strings/gh15613.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/standard/tests/strings/gh15613.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,25 @@ +--TEST-- +GH-15613 overflow on hex strings repeater value +--SKIPIF-- + +--INI-- +memory_limit=-1 +--FILE-- +getMessage() . PHP_EOL; +} + +try { + unpack('H2147483647', str_repeat('X', 2**31 + 10)); +} catch (\ValueError $e) { + echo $e->getMessage(); +} +?> +--EXPECTF-- +unpack(): Argument #1 ($format) repeater must be less than or equal to %d +unpack(): Argument #1 ($format) repeater must be less than or equal to %d diff -Nru php8.2-8.2.24/ext/sysvmsg/sysvmsg.c php8.2-8.2.26/ext/sysvmsg/sysvmsg.c --- php8.2-8.2.24/ext/sysvmsg/sysvmsg.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/sysvmsg/sysvmsg.c 2024-11-19 17:11:09.000000000 +0000 @@ -371,11 +371,19 @@ php_var_serialize(&msg_var, message, &var_hash); PHP_VAR_SERIALIZE_DESTROY(var_hash); + if (UNEXPECTED(EG(exception))) { + smart_str_free(&msg_var); + RETURN_THROWS(); + } + + + zend_string *str = smart_str_extract(&msg_var); + message_len = ZSTR_LEN(str); /* NB: php_msgbuf is 1 char bigger than a long, so there is no need to * allocate the extra byte. */ - messagebuffer = safe_emalloc(ZSTR_LEN(msg_var.s), 1, sizeof(struct php_msgbuf)); - memcpy(messagebuffer->mtext, ZSTR_VAL(msg_var.s), ZSTR_LEN(msg_var.s) + 1); - message_len = ZSTR_LEN(msg_var.s); + messagebuffer = safe_emalloc(message_len, 1, sizeof(struct php_msgbuf)); + memcpy(messagebuffer->mtext, ZSTR_VAL(str), message_len + 1); + zend_string_release_ex(str, false); smart_str_free(&msg_var); } else { char *p; diff -Nru php8.2-8.2.24/ext/sysvmsg/tests/gh16592.phpt php8.2-8.2.26/ext/sysvmsg/tests/gh16592.phpt --- php8.2-8.2.24/ext/sysvmsg/tests/gh16592.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/sysvmsg/tests/gh16592.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,19 @@ +--TEST-- +msg_send() segfault when the type does not serialize as expected +--EXTENSIONS-- +sysvmsg +--FILE-- +getMessage(); +} +?> +--EXPECT-- +Test::__serialize() must return an array diff -Nru php8.2-8.2.24/ext/sysvshm/sysvshm.c php8.2-8.2.26/ext/sysvshm/sysvshm.c --- php8.2-8.2.24/ext/sysvshm/sysvshm.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/sysvshm/sysvshm.c 2024-11-19 17:11:09.000000000 +0000 @@ -257,6 +257,12 @@ php_var_serialize(&shm_var, arg_var, &var_hash); PHP_VAR_SERIALIZE_DESTROY(var_hash); + if (UNEXPECTED(!shm_list_ptr->ptr)) { + smart_str_free(&shm_var); + zend_throw_error(NULL, "Shared memory block has been destroyed by the serialization function"); + RETURN_THROWS(); + } + /* insert serialized variable into shared memory */ ret = php_put_shm_data(shm_list_ptr->ptr, shm_key, shm_var.s? ZSTR_VAL(shm_var.s) : NULL, shm_var.s? ZSTR_LEN(shm_var.s) : 0); diff -Nru php8.2-8.2.24/ext/sysvshm/tests/gh16591.phpt php8.2-8.2.26/ext/sysvshm/tests/gh16591.phpt --- php8.2-8.2.24/ext/sysvshm/tests/gh16591.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/sysvshm/tests/gh16591.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,25 @@ +--TEST-- +GH-16591 (Assertion error in shm_put_var) +--EXTENSIONS-- +sysvshm +--FILE-- + 'b']; + } +} + +$mem = shm_attach(1); +try { + shm_put_var($mem, 1, new C); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Shared memory block has been destroyed by the serialization function diff -Nru php8.2-8.2.24/ext/xml/tests/gh15868.phpt php8.2-8.2.26/ext/xml/tests/gh15868.phpt --- php8.2-8.2.24/ext/xml/tests/gh15868.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/xml/tests/gh15868.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,46 @@ +--TEST-- +GH-15868 (Assertion failure in xml_parse_into_struct after exception) +--EXTENSIONS-- +xml +--FILE-- +", $values, $tags); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +$parser = xml_parser_create(); +xml_set_element_handler($parser, + function ($parser, $name, $attrs) { + }, function ($parser, $name) { + throw new Error('stop 2'); + } +); +try { + xml_parse_into_struct($parser, "", $values, $tags); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +$parser = xml_parser_create(); +xml_set_character_data_handler($parser, function() { + throw new Error('stop 3'); +}); +try { + xml_parse_into_struct($parser, "", $values, $tags); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +stop 1 +stop 2 +stop 3 diff -Nru php8.2-8.2.24/ext/xml/xml.c php8.2-8.2.26/ext/xml/xml.c --- php8.2-8.2.24/ext/xml/xml.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/xml/xml.c 2024-11-19 17:11:09.000000000 +0000 @@ -628,7 +628,7 @@ zval_ptr_dtor(&retval); } - if (!Z_ISUNDEF(parser->data)) { + if (!Z_ISUNDEF(parser->data) && !EG(exception)) { if (parser->level <= XML_MAXLEVEL) { zval tag, atr; int atcnt = 0; @@ -699,7 +699,7 @@ zval_ptr_dtor(&retval); } - if (!Z_ISUNDEF(parser->data)) { + if (!Z_ISUNDEF(parser->data) && !EG(exception)) { zval tag; if (parser->lastwasopen) { @@ -747,7 +747,7 @@ zval_ptr_dtor(&retval); } - if (Z_ISUNDEF(parser->data)) { + if (Z_ISUNDEF(parser->data) || EG(exception)) { return; } diff -Nru php8.2-8.2.24/ext/xmlreader/php_xmlreader.c php8.2-8.2.26/ext/xmlreader/php_xmlreader.c --- php8.2-8.2.24/ext/xmlreader/php_xmlreader.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/xmlreader/php_xmlreader.c 2024-11-19 17:11:09.000000000 +0000 @@ -1122,7 +1122,13 @@ } if (basenode != NULL) { - NODE_GET_OBJ(node, basenode, xmlNodePtr, domobj); + /* Note: cannot use NODE_GET_OBJ here because of the wrong return type */ + domobj = Z_LIBXML_NODE_P(basenode); + if (UNEXPECTED(domobj->node == NULL || domobj->node->node == NULL)) { + php_error_docref(NULL, E_WARNING, "Couldn't fetch %s", ZSTR_VAL(Z_OBJCE_P(basenode)->name)); + RETURN_FALSE; + } + node = domobj->node->node; docp = node->doc; } diff -Nru php8.2-8.2.24/ext/xmlreader/tests/gh16292.phpt php8.2-8.2.26/ext/xmlreader/tests/gh16292.phpt --- php8.2-8.2.24/ext/xmlreader/tests/gh16292.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/xmlreader/tests/gh16292.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,26 @@ +--TEST-- +GH-16292 (Segmentation fault in ext/xmlreader/php_xmlreader.c:1282) +--EXTENSIONS-- +dom +xmlreader +--FILE-- + +new book'; +$reader = new XMLReader(); +$reader->XML($xmlstring); +while ($reader->read()) { + if ($reader->localName == "book") { + var_dump($reader->expand($character_data)); + } +} + +?> +--EXPECTF-- +Warning: XMLReader::expand(): Couldn't fetch DOMCharacterData in %s on line %d +bool(false) + +Warning: XMLReader::expand(): Couldn't fetch DOMCharacterData in %s on line %d +bool(false) diff -Nru php8.2-8.2.24/ext/zend_test/fiber.c php8.2-8.2.26/ext/zend_test/fiber.c --- php8.2-8.2.24/ext/zend_test/fiber.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/fiber.c 2024-11-19 17:11:09.000000000 +0000 @@ -91,6 +91,7 @@ execute_data = (zend_execute_data *) stack->top; memset(execute_data, 0, sizeof(zend_execute_data)); + execute_data->func = (zend_function *) &zend_pass_function; EG(current_execute_data) = execute_data; EG(jit_trace_num) = 0; @@ -348,4 +349,5 @@ zend_test_fiber_handlers = std_object_handlers; zend_test_fiber_handlers.dtor_obj = zend_test_fiber_object_destroy; zend_test_fiber_handlers.free_obj = zend_test_fiber_object_free; + zend_test_fiber_handlers.clone_obj = NULL; } diff -Nru php8.2-8.2.24/ext/zend_test/observer.c php8.2-8.2.26/ext/zend_test/observer.c --- php8.2-8.2.24/ext/zend_test/observer.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/observer.c 2024-11-19 17:11:09.000000000 +0000 @@ -20,6 +20,7 @@ #include "zend_observer.h" #include "zend_smart_str.h" #include "ext/standard/php_var.h" +#include "zend_generators.h" static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execute_data); @@ -163,6 +164,11 @@ zend_execute_data *ex = execute_data; php_printf("%*s\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(fbc->common.function_name)); } - } else { + } else if (ZEND_USER_CODE(fbc->type)) { php_printf("%*s\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(fbc->op_array.filename)); } diff -Nru php8.2-8.2.24/ext/zend_test/test.c php8.2-8.2.26/ext/zend_test/test.c --- php8.2-8.2.24/ext/zend_test/test.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/test.c 2024-11-19 17:11:09.000000000 +0000 @@ -639,6 +639,17 @@ RETURN_BOOL(is_zend_ptr((void*)addr)); } +static ZEND_FUNCTION(zend_test_log_err_debug) +{ + zend_string *str; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(str); + ZEND_PARSE_PARAMETERS_END(); + + php_log_err_with_severity(ZSTR_VAL(str), LOG_DEBUG); +} + static zend_object *zend_test_class_new(zend_class_entry *class_type) { zend_object *obj = zend_objects_new(class_type); @@ -659,7 +670,7 @@ } memset(fptr, 0, sizeof(zend_internal_function)); fptr->type = ZEND_INTERNAL_FUNCTION; - fptr->num_args = 1; + fptr->num_args = 0; fptr->scope = (*object)->ce; fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER; fptr->function_name = zend_string_copy(name); @@ -682,7 +693,7 @@ } memset(fptr, 0, sizeof(zend_internal_function)); fptr->type = ZEND_INTERNAL_FUNCTION; - fptr->num_args = 1; + fptr->num_args = 0; fptr->scope = ce; fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC; fptr->function_name = zend_string_copy(name); @@ -879,6 +890,23 @@ RETURN_ARR(zend_new_pair(&name_zv, arguments)); } +static ZEND_METHOD(_ZendTestMagicCallForward, __call) +{ + zend_string *name; + zval *arguments; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(name) + Z_PARAM_ARRAY(arguments) + ZEND_PARSE_PARAMETERS_END(); + + ZEND_IGNORE_VALUE(arguments); + + zval func; + ZVAL_STR(&func, name); + call_user_function(NULL, NULL, &func, return_value, 0, NULL); +} + PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals) @@ -993,6 +1021,8 @@ zend_test_magic_call = register_class__ZendTestMagicCall(); + register_class__ZendTestMagicCallForward(); + zend_register_functions(NULL, ext_function_legacy, NULL, EG(current_module)->type); // Loading via dl() not supported with the observer API diff -Nru php8.2-8.2.24/ext/zend_test/test.stub.php php8.2-8.2.26/ext/zend_test/test.stub.php --- php8.2-8.2.24/ext/zend_test/test.stub.php 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/test.stub.php 2024-11-19 17:11:09.000000000 +0000 @@ -52,6 +52,11 @@ public function __call(string $name, array $args): mixed {} } + class _ZendTestMagicCallForward + { + public function __call(string $name, array $args): mixed {} + } + class _ZendTestChildClass extends _ZendTestClass { public function returnsThrowable(): Exception {} @@ -191,6 +196,8 @@ function zend_test_cast_fread($stream): void {} function zend_test_is_zend_ptr(int $addr): bool {} + + function zend_test_log_err_debug(string $str): void {} } namespace ZendTestNS { diff -Nru php8.2-8.2.24/ext/zend_test/test_arginfo.h php8.2-8.2.26/ext/zend_test/test_arginfo.h --- php8.2-8.2.24/ext/zend_test/test_arginfo.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/test_arginfo.h 2024-11-19 17:11:09.000000000 +0000 @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 07ce28cd75080118509ac0d30d8ce5ef54110747 */ + * Stub hash: 1c6384894b21ff02bbc3d6088440de6616878a7d */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -126,6 +126,10 @@ ZEND_ARG_TYPE_INFO(0, addr, IS_LONG, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_log_err_debug, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) +ZEND_END_ARG_INFO() + #define arginfo_ZendTestNS2_namespaced_func arginfo_zend_test_is_pcre_bundled #define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return @@ -161,6 +165,8 @@ ZEND_ARG_TYPE_INFO(0, args, IS_ARRAY, 0) ZEND_END_ARG_INFO() +#define arginfo_class__ZendTestMagicCallForward___call arginfo_class__ZendTestMagicCall___call + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class__ZendTestChildClass_returnsThrowable, 0, 0, Exception, 0) ZEND_END_ARG_INFO() @@ -235,6 +241,7 @@ #endif static ZEND_FUNCTION(zend_test_cast_fread); static ZEND_FUNCTION(zend_test_is_zend_ptr); +static ZEND_FUNCTION(zend_test_log_err_debug); static ZEND_FUNCTION(ZendTestNS2_namespaced_func); static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func); static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func); @@ -245,6 +252,7 @@ static ZEND_METHOD(_ZendTestClass, returnsThrowable); static ZEND_METHOD(_ZendTestClass, variadicTest); static ZEND_METHOD(_ZendTestMagicCall, __call); +static ZEND_METHOD(_ZendTestMagicCallForward, __call); static ZEND_METHOD(_ZendTestChildClass, returnsThrowable); static ZEND_METHOD(_ZendTestTrait, testMethod); static ZEND_METHOD(ZendTestParameterAttribute, __construct); @@ -299,6 +307,7 @@ #endif ZEND_FE(zend_test_cast_fread, arginfo_zend_test_cast_fread) ZEND_FE(zend_test_is_zend_ptr, arginfo_zend_test_is_zend_ptr) + ZEND_FE(zend_test_log_err_debug, arginfo_zend_test_log_err_debug) ZEND_NS_FALIAS("ZendTestNS2", namespaced_func, ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func) ZEND_NS_DEP_FALIAS("ZendTestNS2", namespaced_deprecated_func, ZendTestNS2_namespaced_deprecated_func, arginfo_ZendTestNS2_namespaced_deprecated_func) ZEND_NS_FALIAS("ZendTestNS2", namespaced_aliased_func, zend_test_void_return, arginfo_ZendTestNS2_namespaced_aliased_func) @@ -332,6 +341,12 @@ }; +static const zend_function_entry class__ZendTestMagicCallForward_methods[] = { + ZEND_ME(_ZendTestMagicCallForward, __call, arginfo_class__ZendTestMagicCallForward___call, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + + static const zend_function_entry class__ZendTestChildClass_methods[] = { ZEND_ME(_ZendTestChildClass, returnsThrowable, arginfo_class__ZendTestChildClass_returnsThrowable, ZEND_ACC_PUBLIC) ZEND_FE_END @@ -530,6 +545,16 @@ class_entry = zend_register_internal_class_ex(&ce, NULL); return class_entry; +} + +static zend_class_entry *register_class__ZendTestMagicCallForward(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "_ZendTestMagicCallForward", class__ZendTestMagicCallForward_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + return class_entry; } static zend_class_entry *register_class__ZendTestChildClass(zend_class_entry *class_entry__ZendTestClass) diff -Nru php8.2-8.2.24/ext/zend_test/tests/gh16230.phpt php8.2-8.2.26/ext/zend_test/tests/gh16230.phpt --- php8.2-8.2.24/ext/zend_test/tests/gh16230.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/tests/gh16230.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,22 @@ +--TEST-- +GH-16230: Segfault on debug_backtrace() inside _ZendTestFiber +--EXTENSIONS-- +zend_test +--FILE-- +start(); +?> +--EXPECT-- +array(1) { + [0]=> + array(2) { + ["function"]=> + string(9) "{closure}" + ["args"]=> + array(0) { + } + } +} diff -Nru php8.2-8.2.24/ext/zend_test/tests/gh16233.phpt php8.2-8.2.26/ext/zend_test/tests/gh16233.phpt --- php8.2-8.2.24/ext/zend_test/tests/gh16233.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/tests/gh16233.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,32 @@ +--TEST-- +GH-16233 (Observer segfault when calling user function in internal function via trampoline) +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.show_output=1 +zend_test.observer.observe_all=1 +--FILE-- +callee(); +echo "done\n"; + +?> +--EXPECTF-- + + + + <_ZendTestMagicCallForward::__call> + + +in callee + + +done + diff -Nru php8.2-8.2.24/ext/zend_test/tests/gh16266.phpt php8.2-8.2.26/ext/zend_test/tests/gh16266.phpt --- php8.2-8.2.24/ext/zend_test/tests/gh16266.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/tests/gh16266.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,21 @@ +--TEST-- +GH-16266 (_ZendTestClass::test() segfaults on named parameter) +--EXTENSIONS-- +zend_test +--FILE-- +test('a', 'b', c: 'c'); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + _ZendTestClass::test('a', 'b', c: 'c'); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +Unknown named parameter $c +Unknown named parameter $c diff -Nru php8.2-8.2.24/ext/zend_test/tests/gh16294.phpt php8.2-8.2.26/ext/zend_test/tests/gh16294.phpt --- php8.2-8.2.24/ext/zend_test/tests/gh16294.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/tests/gh16294.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,16 @@ +--TEST-- +GH-16294: Segfault in test observer on zend_pass_function +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.execute_internal=1 +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff -Nru php8.2-8.2.24/ext/zend_test/tests/gh16388.phpt php8.2-8.2.26/ext/zend_test/tests/gh16388.phpt --- php8.2-8.2.24/ext/zend_test/tests/gh16388.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/tests/gh16388.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,12 @@ +--TEST-- +GH-16388 (UB when freeing a cloned _ZendTestFiber) +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Trying to clone an uncloneable object of class _ZendTestFiber in %s:%d +%A diff -Nru php8.2-8.2.24/ext/zend_test/tests/gh16514.phpt php8.2-8.2.26/ext/zend_test/tests/gh16514.phpt --- php8.2-8.2.24/ext/zend_test/tests/gh16514.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/tests/gh16514.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,58 @@ +--TEST-- +GH-16514: Nested generator in zend_test observer +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.show_output=1 +zend_test.observer.show_init_backtrace=1 +--FILE-- + +--EXPECTF-- + + + + + + + + + + +#0 %s(%d): Foo->__destruct() +#1 %s(%d): bar() diff -Nru php8.2-8.2.24/ext/zend_test/tests/observer_error_04.phpt php8.2-8.2.26/ext/zend_test/tests/observer_error_04.phpt --- php8.2-8.2.24/ext/zend_test/tests/observer_error_04.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/tests/observer_error_04.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -47,9 +47,9 @@ - -SOAP-ERROR: Parsing WSDL: Couldn't load from 'foo' : failed to load external entity "foo" +SOAP-ERROR: Parsing WSDL: %s Done. diff -Nru php8.2-8.2.24/ext/zend_test/tests/observer_fiber_functions_03.phpt php8.2-8.2.26/ext/zend_test/tests/observer_fiber_functions_03.phpt --- php8.2-8.2.24/ext/zend_test/tests/observer_fiber_functions_03.phpt 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/zend_test/tests/observer_fiber_functions_03.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -10,6 +10,10 @@ zend_test.observer.fiber_switch=1 zend_test.observer.fiber_destroy=1 memory_limit=100M +--SKIPIF-- + --FILE-- [" ", ""]]); +} catch (ValueError $ex) { + echo $ex->getMessage(), "\n"; +} +try { + deflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => ["hello", "wor\0ld"]]); +} catch (ValueError $ex) { + echo $ex->getMessage(), "\n"; +} +try { + deflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => [" ", new stdClass]]); +} catch (Error $ex) { + echo $ex->getMessage(), "\n"; +} +?> +--EXPECT-- +deflate_init(): Argument #2 ($options) must not contain empty strings +deflate_init(): Argument #2 ($options) must not contain strings with null bytes +Object of class stdClass could not be converted to string diff -Nru php8.2-8.2.24/ext/zlib/zlib.c php8.2-8.2.26/ext/zlib/zlib.c --- php8.2-8.2.24/ext/zlib/zlib.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/ext/zlib/zlib.c 2024-11-19 17:11:09.000000000 +0000 @@ -807,35 +807,29 @@ if (zend_hash_num_elements(dictionary) > 0) { char *dictptr; zval *cur; - zend_string **strings = emalloc(sizeof(zend_string *) * zend_hash_num_elements(dictionary)); + zend_string **strings = safe_emalloc(zend_hash_num_elements(dictionary), sizeof(zend_string *), 0); zend_string **end, **ptr = strings - 1; ZEND_HASH_FOREACH_VAL(dictionary, cur) { - size_t i; - *++ptr = zval_get_string(cur); - if (!*ptr || ZSTR_LEN(*ptr) == 0 || EG(exception)) { - if (*ptr) { - efree(*ptr); - } - while (--ptr >= strings) { - efree(ptr); - } + ZEND_ASSERT(*ptr); + if (ZSTR_LEN(*ptr) == 0 || EG(exception)) { + do { + zend_string_release(*ptr); + } while (--ptr >= strings); efree(strings); if (!EG(exception)) { zend_argument_value_error(2, "must not contain empty strings"); } return 0; } - for (i = 0; i < ZSTR_LEN(*ptr); i++) { - if (ZSTR_VAL(*ptr)[i] == 0) { - do { - efree(ptr); - } while (--ptr >= strings); - efree(strings); - zend_argument_value_error(2, "must not contain strings with null bytes"); - return 0; - } + if (zend_str_has_nul_byte(*ptr)) { + do { + zend_string_release(*ptr); + } while (--ptr >= strings); + efree(strings); + zend_argument_value_error(2, "must not contain strings with null bytes"); + return 0; } *dictlen += ZSTR_LEN(*ptr) + 1; diff -Nru php8.2-8.2.24/main/SAPI.c php8.2-8.2.26/main/SAPI.c --- php8.2-8.2.24/main/SAPI.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/main/SAPI.c 2024-11-19 17:11:09.000000000 +0000 @@ -507,12 +507,15 @@ } if (SG(request_info).auth_user) { efree(SG(request_info).auth_user); + SG(request_info).auth_user = NULL; } if (SG(request_info).auth_password) { efree(SG(request_info).auth_password); + SG(request_info).auth_password = NULL; } if (SG(request_info).auth_digest) { efree(SG(request_info).auth_digest); + SG(request_info).auth_digest = NULL; } if (SG(request_info).content_type_dup) { efree(SG(request_info).content_type_dup); diff -Nru php8.2-8.2.24/main/main.c php8.2-8.2.26/main/main.c --- php8.2-8.2.24/main/main.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/main/main.c 2024-11-19 17:11:09.000000000 +0000 @@ -2672,7 +2672,9 @@ if (pass) { *pass++ = '\0'; SG(request_info).auth_user = estrndup(ZSTR_VAL(user), ZSTR_LEN(user)); - SG(request_info).auth_password = estrdup(pass); + if (strlen(pass) > 0) { + SG(request_info).auth_password = estrdup(pass); + } ret = 0; } zend_string_free(user); diff -Nru php8.2-8.2.24/main/php_network.h php8.2-8.2.26/main/php_network.h --- php8.2-8.2.24/main/php_network.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/main/php_network.h 2024-11-19 17:11:09.000000000 +0000 @@ -162,7 +162,7 @@ /* timeval-to-timeout (for poll(2)) */ static inline int php_tvtoto(struct timeval *timeouttv) { - if (timeouttv) { + if (timeouttv && timeouttv->tv_sec >= 0 && timeouttv->tv_sec <= ((INT_MAX - 1000) / 1000)) { return (timeouttv->tv_sec * 1000) + (timeouttv->tv_usec / 1000); } return -1; diff -Nru php8.2-8.2.24/main/php_variables.c php8.2-8.2.26/main/php_variables.c --- php8.2-8.2.24/main/php_variables.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/main/php_variables.c 2024-11-19 17:11:09.000000000 +0000 @@ -897,6 +897,7 @@ } else { zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_SERVER]); array_init(&PG(http_globals)[TRACK_VARS_SERVER]); + zend_hash_real_init_mixed(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER])); } check_http_proxy(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER])); diff -Nru php8.2-8.2.24/main/php_version.h php8.2-8.2.26/main/php_version.h --- php8.2-8.2.24/main/php_version.h 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/main/php_version.h 2024-11-19 17:11:09.000000000 +0000 @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 2 -#define PHP_RELEASE_VERSION 24 +#define PHP_RELEASE_VERSION 26 #define PHP_EXTRA_VERSION "" -#define PHP_VERSION "8.2.24" -#define PHP_VERSION_ID 80224 +#define PHP_VERSION "8.2.26" +#define PHP_VERSION_ID 80226 diff -Nru php8.2-8.2.24/main/streams/streams.c php8.2-8.2.26/main/streams/streams.c --- php8.2-8.2.24/main/streams/streams.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/main/streams/streams.c 2024-11-19 17:11:09.000000000 +0000 @@ -1354,8 +1354,13 @@ switch(whence) { case SEEK_CUR: - offset = stream->position + offset; - whence = SEEK_SET; + ZEND_ASSERT(stream->position >= 0); + if (UNEXPECTED(offset > ZEND_LONG_MAX - stream->position)) { + offset = ZEND_LONG_MAX; + } else { + offset = stream->position + offset; + } + whence = SEEK_SET; break; } ret = stream->ops->seek(stream, offset, whence, &stream->position); @@ -2175,6 +2180,9 @@ options &= ~USE_PATH; } if (EG(exception)) { + if (resolved_path) { + zend_string_release_ex(resolved_path, false); + } return NULL; } } diff -Nru php8.2-8.2.24/run-tests.php php8.2-8.2.26/run-tests.php --- php8.2-8.2.24/run-tests.php 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/run-tests.php 2024-11-19 17:11:09.000000000 +0000 @@ -23,7 +23,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: bb422e41c0fe4303a4efb3f3657568b74c20cf96 $ */ +/* $Id: 5add428aaddc5c974be0ec4111efe187d846717d $ */ /* Temporary variables while this file is being refactored. */ /** @var ?JUnit */ @@ -612,7 +612,7 @@ $show_progress = false; break; case '--version': - echo '$Id: bb422e41c0fe4303a4efb3f3657568b74c20cf96 $' . "\n"; + echo '$Id: 5add428aaddc5c974be0ec4111efe187d846717d $' . "\n"; exit(1); default: @@ -2159,6 +2159,9 @@ } elseif (!strncasecmp('xfail', $output, 5)) { // Pretend we have an XFAIL section $test->setSection('XFAIL', ltrim(substr($output, 5))); + } elseif (!strncasecmp('flaky', $output, 5)) { + // Pretend we have a FLAKY section + $test->setSection('FLAKY', ltrim(substr($output, 5))); } elseif ($output !== '') { show_result("BORK", $output, $tested_file, 'reason: invalid output from SKIPIF', $temp_filenames); $PHP_FAILED_TESTS['BORKED'][] = [ diff -Nru php8.2-8.2.24/sapi/cli/php_cli.c php8.2-8.2.26/sapi/cli/php_cli.c --- php8.2-8.2.24/sapi/cli/php_cli.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/sapi/cli/php_cli.c 2024-11-19 17:11:09.000000000 +0000 @@ -1075,6 +1075,7 @@ object_init_ex(&ref, pce); memset(&execute_data, 0, sizeof(zend_execute_data)); + execute_data.func = (zend_function *) &zend_pass_function; EG(current_execute_data) = &execute_data; zend_call_known_instance_method_with_1_params( pce->constructor, Z_OBJ(ref), NULL, &arg); diff -Nru php8.2-8.2.24/sapi/cli/php_cli_server.c php8.2-8.2.26/sapi/cli/php_cli_server.c --- php8.2-8.2.24/sapi/cli/php_cli_server.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/sapi/cli/php_cli_server.c 2024-11-19 17:11:09.000000000 +0000 @@ -1680,14 +1680,33 @@ { /* Wrap header value in a zval to add is to the HashTable which acts as an array */ zval tmp; - ZVAL_STR(&tmp, client->current_header_value); /* strip off the colon */ zend_string *lc_header_name = zend_string_tolower_ex(client->current_header_name, /* persistent */ true); GC_MAKE_PERSISTENT_LOCAL(lc_header_name); - /* Add the wrapped zend_string to the HashTable */ - zend_hash_add(&client->request.headers, lc_header_name, &tmp); - zend_hash_add(&client->request.headers_original_case, client->current_header_name, &tmp); + zval *entry = zend_hash_find(&client->request.headers, lc_header_name); + bool with_comma = !zend_string_equals_literal(lc_header_name, "set-cookie"); + + /** + * `Set-Cookie` HTTP header being the exception, they can have 1 or more values separated + * by a comma while still possibly be set separately by the client. + **/ + if (!with_comma || entry == NULL) { + ZVAL_STR(&tmp, client->current_header_value); + } else { + zend_string *curval = Z_STR_P(entry); + zend_string *newval = zend_string_safe_alloc(1, ZSTR_LEN(curval), ZSTR_LEN(client->current_header_value) + 2, /* persistent */true); + + memcpy(ZSTR_VAL(newval), ZSTR_VAL(curval), ZSTR_LEN(curval)); + memcpy(ZSTR_VAL(newval) + ZSTR_LEN(curval), ", ", 2); + memcpy(ZSTR_VAL(newval) + ZSTR_LEN(curval) + 2, ZSTR_VAL(client->current_header_value), ZSTR_LEN(client->current_header_value) + 1); + + ZVAL_STR(&tmp, newval); + } + + /* Add/Update the wrapped zend_string to the HashTable */ + zend_hash_update(&client->request.headers, lc_header_name, &tmp); + zend_hash_update(&client->request.headers_original_case, client->current_header_name, &tmp); zend_string_release_ex(lc_header_name, /* persistent */ true); zend_string_release_ex(client->current_header_name, /* persistent */ true); @@ -1925,6 +1944,8 @@ request_info->auth_user = request_info->auth_password = request_info->auth_digest = NULL; if (NULL != (val = zend_hash_str_find(&client->request.headers, "content-type", sizeof("content-type")-1))) { request_info->content_type = Z_STRVAL_P(val); + } else { + request_info->content_type = NULL; } } /* }}} */ @@ -2252,6 +2273,7 @@ } ZVAL_UNDEF(&retval); + CG(skip_shebang) = true; if (SUCCESS == zend_execute_scripts(ZEND_REQUIRE, &retval, 1, &zfd)) { if (Z_TYPE(retval) != IS_UNDEF) { decline = Z_TYPE(retval) == IS_FALSE; diff -Nru php8.2-8.2.24/sapi/cli/tests/gh16137.phpt php8.2-8.2.26/sapi/cli/tests/gh16137.phpt --- php8.2-8.2.24/sapi/cli/tests/gh16137.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/sapi/cli/tests/gh16137.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,20 @@ +--TEST-- +Bug GH-16137 duplicate *Forwarded* HTTP headers values. +--INI-- +allow_url_fopen=1 +--SKIPIF-- + +--FILE-- + array ( + 'method' => 'POST', + 'header' => array('x-forwarded-for: 127.0.0.1', 'x-forwarded-for: 192.168.1.254') +))); +var_dump(file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS, true, $ctx)); +?> +--EXPECT-- +string(24) "127.0.0.1, 192.168.1.254" diff -Nru php8.2-8.2.24/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt php8.2-8.2.26/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt --- php8.2-8.2.24/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/sapi/cli/tests/ghsa-4w77-75f9-2c8w.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,41 @@ +--TEST-- +GHSA-4w77-75f9-2c8w (Heap-Use-After-Free in sapi_read_post_data Processing in CLI SAPI Interface) +--INI-- +allow_url_fopen=1 +--SKIPIF-- + +--FILE-- + [ + "method" => "POST", + "header" => "Content-Type: application/x-www-form-urlencoded", + "content" => "AAAAA", + ], +]; +$context = stream_context_create($options); + +echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . "/", context: $context); + +$options = [ + "http" => [ + "method" => "POST", + ], +]; +$context = stream_context_create($options); + +echo file_get_contents("http://" . PHP_CLI_SERVER_ADDRESS . "/", context: $context); +?> +--EXPECT-- +string(5) "AAAAA" +string(0) "" diff -Nru php8.2-8.2.24/sapi/fpm/fpm/zlog.c php8.2-8.2.26/sapi/fpm/fpm/zlog.c --- php8.2-8.2.24/sapi/fpm/fpm/zlog.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/sapi/fpm/fpm/zlog.c 2024-11-19 17:11:09.000000000 +0000 @@ -150,6 +150,7 @@ } /* }}} */ +/* Returns the length if the print were complete, this can be larger than buf_size. */ static size_t zlog_buf_prefix( const char *function, int line, int flags, char *buf, size_t buf_size, int use_syslog) /* {{{ */ @@ -186,6 +187,7 @@ } } + /* Important: snprintf returns the number of bytes if the print were complete. */ return len; } /* }}} */ @@ -408,6 +410,7 @@ static inline ssize_t zlog_stream_buf_copy_cstr( struct zlog_stream *stream, const char *str, size_t str_len) /* {{{ */ { + ZEND_ASSERT(stream->len <= stream->buf.size); if (stream->buf.size - stream->len <= str_len && !zlog_stream_buf_alloc_ex(stream, str_len + stream->len)) { return -1; @@ -422,6 +425,7 @@ static inline ssize_t zlog_stream_buf_copy_char(struct zlog_stream *stream, char c) /* {{{ */ { + ZEND_ASSERT(stream->len <= stream->buf.size); if (stream->buf.size - stream->len < 1 && !zlog_stream_buf_alloc_ex(stream, 1)) { return -1; } @@ -678,6 +682,17 @@ len = zlog_buf_prefix( function, line, stream->flags, stream->buf.data, stream->buf.size, stream->use_syslog); + if (!EXPECTED(len + 1 <= stream->buf.size)) { + /* If the buffer was not large enough, try with a larger buffer. + * Note that this may still truncate if the zlog_limit is reached. */ + len = MIN(len + 1, zlog_limit); + if (!zlog_stream_buf_alloc_ex(stream, len)) { + return -1; + } + zlog_buf_prefix( + function, line, stream->flags, + stream->buf.data, stream->buf.size, stream->use_syslog); + } stream->len = stream->prefix_len = len; if (stream->msg_prefix != NULL) { zlog_stream_buf_copy_cstr(stream, stream->msg_prefix, stream->msg_prefix_len); @@ -689,8 +704,8 @@ } else { char sbuf[1024]; ssize_t written; - len = zlog_buf_prefix(function, line, stream->flags, sbuf, 1024, stream->use_syslog); - written = zlog_stream_direct_write(stream, sbuf, len); + len = zlog_buf_prefix(function, line, stream->flags, sbuf, sizeof(sbuf), stream->use_syslog); + written = zlog_stream_direct_write(stream, sbuf, MIN(len, sizeof(sbuf))); if (stream->msg_prefix != NULL) { written += zlog_stream_direct_write( stream, stream->msg_prefix, stream->msg_prefix_len); diff -Nru php8.2-8.2.24/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt php8.2-8.2.26/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt --- php8.2-8.2.24/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,61 @@ +--TEST-- +FPM: GH-15335 - PHP_AUTH shutdown use after free +--SKIPIF-- + +--FILE-- +createSourceFileAndScriptName(); +$tester->start(); +$tester->expectLogStartNotices(); +$tester + ->request( + headers: [ "HTTP_AUTHORIZATION" => "Basic Zm9vOg==", "REQUEST_METHOD" => "GET"], + uri: $scriptName, + address: '{{ADDR}}', + scriptFilename: __DIR__ . "/__unknown.php", + scriptName: "/", + ) + ->expectStatus('404 Not Found'); +$tester + ->request( + uri: $scriptName, + address: '{{ADDR}}', + params: [], + ); +$tester->expectNoLogPattern("/zend_mm_heap corrupted/"); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff -Nru php8.2-8.2.24/sapi/fpm/tests/gh16628.phpt php8.2-8.2.26/sapi/fpm/tests/gh16628.phpt --- php8.2-8.2.24/sapi/fpm/tests/gh16628.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/sapi/fpm/tests/gh16628.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,53 @@ +--TEST-- +GH-16628 (FPM logs are getting corrupted with this log statement) +--EXTENSIONS-- +zend_test +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->request()->expectEmptyBody(); +for ($i = 1; $i < 100; $i++) { + $tester->expectLogNotice("%sPHP message: " . str_repeat("a", $i)); +} +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff -Nru php8.2-8.2.24/sapi/fpm/tests/tester.inc php8.2-8.2.26/sapi/fpm/tests/tester.inc --- php8.2-8.2.24/sapi/fpm/tests/tester.inc 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/sapi/fpm/tests/tester.inc 2024-11-19 17:11:09.000000000 +0000 @@ -762,6 +762,7 @@ string|array $stdin = null, bool $expectError = false, int $readLimit = -1, + array $params = null, ): Response { if ($this->hasError()) { return $this->createResponse(expectInvalid: true); @@ -771,7 +772,7 @@ $stdin = $this->parseStdin($stdin, $headers); } - $params = $this->getRequestParams($query, $headers, $uri, $scriptFilename, $scriptName, $stdin); + $params = $params ?? $this->getRequestParams($query, $headers, $uri, $scriptFilename, $scriptName, $stdin); $this->trace('Request params', $params); try { diff -Nru php8.2-8.2.24/sapi/phpdbg/phpdbg_info.c php8.2-8.2.26/sapi/phpdbg/phpdbg_info.c --- php8.2-8.2.24/sapi/phpdbg/phpdbg_info.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/sapi/phpdbg/phpdbg_info.c 2024-11-19 17:11:09.000000000 +0000 @@ -399,27 +399,29 @@ phpdbg_notice("User Classes (%d)", zend_hash_num_elements(&classes)); /* once added, assume that classes are stable... until shutdown. */ - ZEND_HASH_PACKED_FOREACH_PTR(&classes, ce) { - phpdbg_print_class_name(ce); + if (HT_IS_INITIALIZED(&classes)) { + ZEND_HASH_PACKED_FOREACH_PTR(&classes, ce) { + phpdbg_print_class_name(ce); + + if (ce->parent) { + if (ce->ce_flags & ZEND_ACC_LINKED) { + zend_class_entry *pce = ce->parent; + do { + phpdbg_out("|-------- "); + phpdbg_print_class_name(pce); + } while ((pce = pce->parent)); + } else { + phpdbg_writeln("|-------- User Class %s (not yet linked because declaration for parent was not encountered when declaring the class)", ZSTR_VAL(ce->parent_name)); + } + } - if (ce->parent) { - if (ce->ce_flags & ZEND_ACC_LINKED) { - zend_class_entry *pce = ce->parent; - do { - phpdbg_out("|-------- "); - phpdbg_print_class_name(pce); - } while ((pce = pce->parent)); + if (ce->info.user.filename) { + phpdbg_writeln("|---- in %s on line %u", ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start); } else { - phpdbg_writeln("|-------- User Class %s (not yet linked because declaration for parent was not encountered when declaring the class)", ZSTR_VAL(ce->parent_name)); + phpdbg_writeln("|---- no source code"); } - } - - if (ce->info.user.filename) { - phpdbg_writeln("|---- in %s on line %u", ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start); - } else { - phpdbg_writeln("|---- no source code"); - } - } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } zend_hash_destroy(&classes); @@ -445,17 +447,19 @@ phpdbg_notice("User Functions (%d)", zend_hash_num_elements(&functions)); - ZEND_HASH_PACKED_FOREACH_PTR(&functions, zf) { - zend_op_array *op_array = &zf->op_array; + if (HT_IS_INITIALIZED(&functions)) { + ZEND_HASH_PACKED_FOREACH_PTR(&functions, zf) { + zend_op_array *op_array = &zf->op_array; - phpdbg_write("|-------- %s", op_array->function_name ? ZSTR_VAL(op_array->function_name) : "{main}"); + phpdbg_write("|-------- %s", op_array->function_name ? ZSTR_VAL(op_array->function_name) : "{main}"); - if (op_array->filename) { - phpdbg_writeln(" in %s on line %d", ZSTR_VAL(op_array->filename), op_array->line_start); - } else { - phpdbg_writeln(" (no source code)"); - } - } ZEND_HASH_FOREACH_END(); + if (op_array->filename) { + phpdbg_writeln(" in %s on line %d", ZSTR_VAL(op_array->filename), op_array->line_start); + } else { + phpdbg_writeln(" (no source code)"); + } + } ZEND_HASH_FOREACH_END(); + } zend_hash_destroy(&functions); diff -Nru php8.2-8.2.24/sapi/phpdbg/phpdbg_lexer.c php8.2-8.2.26/sapi/phpdbg/phpdbg_lexer.c --- php8.2-8.2.24/sapi/phpdbg/phpdbg_lexer.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/sapi/phpdbg/phpdbg_lexer.c 2024-11-19 17:11:09.000000000 +0000 @@ -1361,50 +1361,50 @@ yyc_RAW: { static const unsigned char yybm[] = { - 0, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 0, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 64, 224, 232, 232, 232, 32, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 16, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, - 232, 232, 232, 232, 232, 232, 232, 232, + 0, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 0, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 148, 70, 247, 247, 247, 162, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 8, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 247, 247, 247, 247, 247, }; YYDEBUG(136, *YYCURSOR); YYFILL(1); yych = *YYCURSOR; - if (yybm[0+yych] & 8) { + if (yybm[0+yych] & 1) { goto yy140; } if (yych <= '\n') goto yy138; if (yych <= '"') goto yy143; - if (yych <= '#') goto yy145; - if (yych <= '\'') goto yy147; - goto yy148; + if (yych <= '#') goto yy146; + if (yych <= '\'') goto yy148; + goto yy150; yy138: YYDEBUG(138, *YYCURSOR); ++YYCURSOR; @@ -1419,14 +1419,14 @@ YYFILL(1); yych = *YYCURSOR; YYDEBUG(141, *YYCURSOR); - if (yybm[0+yych] & 8) { + if (yybm[0+yych] & 1) { goto yy140; } if (yych <= '\n') goto yy142; if (yych <= '"') goto yy143; if (yych <= '#') goto yy142; - if (yych <= '\'') goto yy147; - goto yy148; + if (yych <= '\'') goto yy148; + goto yy150; yy142: YYDEBUG(142, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; @@ -1441,73 +1441,67 @@ ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - if (yybm[0+yych] & 32) { - goto yy150; - } - if (yych >= '#') goto yy152; -yy144: YYDEBUG(144, *YYCURSOR); - YYCURSOR = YYMARKER; - goto yy142; + if (yybm[0+yych] & 2) { + goto yy143; + } + if (yych <= '\n') goto yy145; + if (yych <= '"') goto yy140; + goto yy152; yy145: YYDEBUG(145, *YYCURSOR); - ++YYCURSOR; + YYCURSOR = YYMARKER; + goto yy142; +yy146: YYDEBUG(146, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(147, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; { YYSETCONDITION(INITIAL); return T_SEPARATOR; } -yy147: - YYDEBUG(147, *YYCURSOR); - ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - if (yybm[0+yych] & 64) { - goto yy154; - } - if (yych <= '\'') goto yy144; - goto yy156; yy148: YYDEBUG(148, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; YYDEBUG(149, *YYCURSOR); - if (yybm[0+yych] & 16) { + if (yybm[0+yych] & 4) { goto yy148; } - if (yych <= '!') { - if (yych <= 0x00) goto yy142; - if (yych == '\n') goto yy142; - goto yy140; - } else { - if (yych <= '"') goto yy158; - if (yych == '\'') goto yy159; - goto yy140; - } + if (yych <= '\n') goto yy145; + if (yych <= '\'') goto yy140; + goto yy154; yy150: YYDEBUG(150, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; YYDEBUG(151, *YYCURSOR); - if (yybm[0+yych] & 32) { + if (yybm[0+yych] & 8) { goto yy150; } - if (yych <= '\n') goto yy144; - if (yych <= '"') goto yy140; + if (yych <= '!') { + if (yych <= 0x00) goto yy142; + if (yych == '\n') goto yy142; + goto yy140; + } else { + if (yych <= '"') goto yy156; + if (yych == '\'') goto yy158; + goto yy140; + } yy152: YYDEBUG(152, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; YYDEBUG(153, *YYCURSOR); - if (yybm[0+yych] & 32) { - goto yy150; + if (yybm[0+yych] & 2) { + goto yy143; } - if (yych <= '\n') goto yy144; - if (yych <= '"') goto yy160; + if (yych <= '\n') goto yy145; + if (yych <= '"') goto yy156; goto yy152; yy154: YYDEBUG(154, *YYCURSOR); @@ -1515,279 +1509,116 @@ YYFILL(1); yych = *YYCURSOR; YYDEBUG(155, *YYCURSOR); - if (yybm[0+yych] & 64) { - goto yy154; + if (yybm[0+yych] & 4) { + goto yy148; } - if (yych <= '\n') goto yy144; - if (yych <= '\'') goto yy140; + if (yych <= '\n') goto yy145; + if (yych <= '\'') goto yy158; + goto yy154; yy156: YYDEBUG(156, *YYCURSOR); - ++YYCURSOR; + YYMARKER = ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; YYDEBUG(157, *YYCURSOR); - if (yybm[0+yych] & 64) { - goto yy154; + if (yybm[0+yych] & 16) { + goto yy156; } - if (yych <= '\n') goto yy144; - if (yych <= '\'') goto yy162; - goto yy156; + if (yych <= '\n') goto yy142; + if (yych <= '#') goto yy143; + if (yych <= '\'') goto yy160; + goto yy162; yy158: YYDEBUG(158, *YYCURSOR); YYMARKER = ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - if (yych <= '"') { - if (yych <= '\t') { - if (yych <= 0x00) goto yy142; - goto yy160; - } else { - if (yych <= '\n') goto yy142; - if (yych <= '!') goto yy160; - goto yy143; - } - } else { - if (yych <= '\'') { - if (yych <= '#') goto yy150; - if (yych <= '&') goto yy160; - goto yy164; - } else { - if (yych == '\\') goto yy165; - goto yy160; - } - } -yy159: YYDEBUG(159, *YYCURSOR); - YYMARKER = ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - if (yych <= '"') { - if (yych <= '\t') { - if (yych <= 0x00) goto yy142; - goto yy162; - } else { - if (yych <= '\n') goto yy142; - if (yych <= '!') goto yy162; - goto yy167; - } - } else { - if (yych <= '\'') { - if (yych <= '#') goto yy154; - if (yych <= '&') goto yy162; - goto yy147; - } else { - if (yych == '\\') goto yy168; - goto yy162; - } + if (yybm[0+yych] & 32) { + goto yy158; } + if (yych <= '\n') goto yy142; + if (yych <= '"') goto yy160; + if (yych <= '#') goto yy148; + goto yy164; yy160: YYDEBUG(160, *YYCURSOR); - YYMARKER = ++YYCURSOR; + ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; YYDEBUG(161, *YYCURSOR); - if (yych <= '"') { - if (yych <= '\t') { - if (yych <= 0x00) goto yy142; - goto yy160; - } else { - if (yych <= '\n') goto yy142; - if (yych <= '!') goto yy160; - goto yy158; - } - } else { - if (yych <= '\'') { - if (yych <= '#') goto yy150; - if (yych <= '&') goto yy160; - goto yy164; - } else { - if (yych == '\\') goto yy165; - goto yy160; - } + if (yybm[0+yych] & 64) { + goto yy160; } + if (yych <= '\n') goto yy145; + if (yych <= '"') goto yy158; + if (yych <= '\'') goto yy156; + goto yy166; yy162: YYDEBUG(162, *YYCURSOR); - YYMARKER = ++YYCURSOR; + ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; YYDEBUG(163, *YYCURSOR); - if (yych <= '"') { - if (yych <= '\t') { - if (yych <= 0x00) goto yy142; - goto yy162; - } else { - if (yych <= '\n') goto yy142; - if (yych <= '!') goto yy162; - goto yy167; - } + if (yych <= '&') { + if (yych <= 0x00) goto yy142; + if (yych == '\n') goto yy142; + goto yy156; } else { - if (yych <= '\'') { - if (yych <= '#') goto yy154; - if (yych <= '&') goto yy162; - goto yy159; - } else { - if (yych == '\\') goto yy168; - goto yy162; - } + if (yych <= '\'') goto yy168; + if (yych == '\\') goto yy162; + goto yy156; } yy164: YYDEBUG(164, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - if (yybm[0+yych] & 128) { - goto yy170; - } - if (yych <= '\n') goto yy144; - if (yych <= '"') goto yy162; - if (yych <= '\'') goto yy150; - goto yy172; -yy165: YYDEBUG(165, *YYCURSOR); - ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - YYDEBUG(166, *YYCURSOR); - if (yych <= '&') { + if (yych <= '!') { if (yych <= 0x00) goto yy142; if (yych == '\n') goto yy142; - goto yy160; + goto yy158; } else { - if (yych <= '\'') goto yy174; - if (yych == '\\') goto yy165; - goto yy160; + if (yych <= '"') goto yy168; + if (yych == '\\') goto yy164; + goto yy158; } -yy167: - YYDEBUG(167, *YYCURSOR); +yy166: + YYDEBUG(166, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - if (yybm[0+yych] & 128) { - goto yy170; + YYDEBUG(167, *YYCURSOR); + if (yybm[0+yych] & 64) { + goto yy160; } - if (yych <= '\n') goto yy144; - if (yych <= '"') goto yy154; - if (yych <= '\'') goto yy160; - goto yy172; + if (yych <= '\n') goto yy145; + if (yych >= '(') goto yy166; yy168: YYDEBUG(168, *YYCURSOR); - ++YYCURSOR; + YYMARKER = ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; YYDEBUG(169, *YYCURSOR); - if (yych <= '!') { - if (yych <= 0x00) goto yy142; - if (yych == '\n') goto yy142; - goto yy162; - } else { - if (yych <= '"') goto yy175; - if (yych == '\\') goto yy168; - goto yy162; + if (yybm[0+yych] & 128) { + goto yy168; } + if (yych <= '\n') goto yy142; + if (yych <= '#') goto yy160; yy170: YYDEBUG(170, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; YYDEBUG(171, *YYCURSOR); - if (yybm[0+yych] & 128) { - goto yy170; - } - if (yych <= '\n') goto yy144; - if (yych <= '"') goto yy162; - if (yych <= '\'') goto yy160; -yy172: - YYDEBUG(172, *YYCURSOR); - ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - YYDEBUG(173, *YYCURSOR); - if (yybm[0+yych] & 128) { - goto yy170; - } - if (yych <= '\n') goto yy144; - if (yych <= '\'') goto yy176; - goto yy172; -yy174: - YYDEBUG(174, *YYCURSOR); - YYMARKER = ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - if (yych <= '"') { - if (yych <= '\t') { - if (yych <= 0x00) goto yy142; - goto yy176; - } else { - if (yych <= '\n') goto yy142; - if (yych <= '!') goto yy176; - } - } else { - if (yych <= '\'') { - if (yych <= '#') goto yy170; - if (yych <= '&') goto yy176; - goto yy164; - } else { - if (yych == '\\') goto yy178; - goto yy176; - } - } -yy175: - YYDEBUG(175, *YYCURSOR); - YYMARKER = ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - if (yych <= '"') { - if (yych <= '\t') { - if (yych <= 0x00) goto yy142; - } else { - if (yych <= '\n') goto yy142; - if (yych >= '"') goto yy167; - } - } else { - if (yych <= '\'') { - if (yych <= '#') goto yy170; - if (yych >= '\'') goto yy174; - } else { - if (yych == '\\') goto yy178; - } - } -yy176: - YYDEBUG(176, *YYCURSOR); - YYMARKER = ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - YYDEBUG(177, *YYCURSOR); - if (yych <= '"') { - if (yych <= '\t') { - if (yych <= 0x00) goto yy142; - goto yy176; - } else { - if (yych <= '\n') goto yy142; - if (yych <= '!') goto yy176; - goto yy175; - } - } else { - if (yych <= '\'') { - if (yych <= '#') goto yy170; - if (yych <= '&') goto yy176; - goto yy174; - } else { - if (yych != '\\') goto yy176; - } - } -yy178: - YYDEBUG(178, *YYCURSOR); - ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - YYDEBUG(179, *YYCURSOR); if (yych <= '\n') { if (yych <= 0x00) goto yy142; - if (yych <= '\t') goto yy176; + if (yych <= '\t') goto yy168; goto yy142; } else { - if (yych == '\\') goto yy178; - goto yy176; + if (yych == '\\') goto yy170; + goto yy168; } } /* *********************************** */ @@ -1827,36 +1658,36 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; - YYDEBUG(180, *YYCURSOR); + YYDEBUG(172, *YYCURSOR); YYFILL(4); yych = *YYCURSOR; if (yych <= 'E') { if (yych <= '\r') { - if (yych == '\t') goto yy184; - if (yych >= '\r') goto yy184; + if (yych == '\t') goto yy176; + if (yych >= '\r') goto yy176; } else { - if (yych == ' ') goto yy185; - if (yych >= 'E') goto yy188; + if (yych == ' ') goto yy177; + if (yych >= 'E') goto yy180; } } else { if (yych <= 'd') { - if (yych <= 'Q') goto yy182; - if (yych <= 'R') goto yy189; - if (yych <= 'S') goto yy190; + if (yych <= 'Q') goto yy174; + if (yych <= 'R') goto yy181; + if (yych <= 'S') goto yy182; } else { if (yych <= 'q') { - if (yych <= 'e') goto yy188; + if (yych <= 'e') goto yy180; } else { - if (yych <= 'r') goto yy191; - if (yych <= 's') goto yy190; + if (yych <= 'r') goto yy183; + if (yych <= 's') goto yy182; } } } -yy182: - YYDEBUG(182, *YYCURSOR); +yy174: + YYDEBUG(174, *YYCURSOR); ++YYCURSOR; -yy183: - YYDEBUG(183, *YYCURSOR); +yy175: + YYDEBUG(175, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; { YYSETCONDITION(NORMAL); @@ -1864,160 +1695,160 @@ YYCURSOR = LEX(text); goto restart; } -yy184: - YYDEBUG(184, *YYCURSOR); +yy176: + YYDEBUG(176, *YYCURSOR); yych = *++YYCURSOR; if (yybm[0+yych] & 128) { - goto yy185; + goto yy177; } - goto yy183; -yy185: - YYDEBUG(185, *YYCURSOR); + goto yy175; +yy177: + YYDEBUG(177, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(186, *YYCURSOR); + YYDEBUG(178, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy185; + goto yy177; } - YYDEBUG(187, *YYCURSOR); + YYDEBUG(179, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; { /* ignore whitespace */ goto restart; } -yy188: - YYDEBUG(188, *YYCURSOR); +yy180: + YYDEBUG(180, *YYCURSOR); yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'V') goto yy192; - if (yych == 'v') goto yy192; - goto yy183; -yy189: - YYDEBUG(189, *YYCURSOR); + if (yych == 'V') goto yy184; + if (yych == 'v') goto yy184; + goto yy175; +yy181: + YYDEBUG(181, *YYCURSOR); yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'U') goto yy194; - if (yych == 'u') goto yy194; - goto yy183; -yy190: - YYDEBUG(190, *YYCURSOR); + if (yych == 'U') goto yy186; + if (yych == 'u') goto yy186; + goto yy175; +yy182: + YYDEBUG(182, *YYCURSOR); yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'H') goto yy195; - if (yych == 'h') goto yy195; - goto yy183; -yy191: - YYDEBUG(191, *YYCURSOR); + if (yych == 'H') goto yy187; + if (yych == 'h') goto yy187; + goto yy175; +yy183: + YYDEBUG(183, *YYCURSOR); yych = *(YYMARKER = ++YYCURSOR); if (yych <= 0x1F) { if (yych <= '\t') { - if (yych <= 0x08) goto yy183; - goto yy196; + if (yych <= 0x08) goto yy175; + goto yy188; } else { - if (yych == '\r') goto yy196; - goto yy183; + if (yych == '\r') goto yy188; + goto yy175; } } else { if (yych <= 'U') { - if (yych <= ' ') goto yy196; - if (yych <= 'T') goto yy183; - goto yy194; + if (yych <= ' ') goto yy188; + if (yych <= 'T') goto yy175; + goto yy186; } else { - if (yych == 'u') goto yy194; - goto yy183; + if (yych == 'u') goto yy186; + goto yy175; } } -yy192: - YYDEBUG(192, *YYCURSOR); +yy184: + YYDEBUG(184, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '\f') { - if (yych == '\t') goto yy199; + if (yych == '\t') goto yy191; } else { - if (yych <= '\r') goto yy199; - if (yych == ' ') goto yy199; + if (yych <= '\r') goto yy191; + if (yych == ' ') goto yy191; } -yy193: - YYDEBUG(193, *YYCURSOR); +yy185: + YYDEBUG(185, *YYCURSOR); YYCURSOR = YYMARKER; - goto yy183; -yy194: - YYDEBUG(194, *YYCURSOR); + goto yy175; +yy186: + YYDEBUG(186, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy202; - if (yych == 'n') goto yy202; - goto yy193; -yy195: - YYDEBUG(195, *YYCURSOR); + if (yych == 'N') goto yy194; + if (yych == 'n') goto yy194; + goto yy185; +yy187: + YYDEBUG(187, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '\f') { - if (yych == '\t') goto yy203; - goto yy193; + if (yych == '\t') goto yy195; + goto yy185; } else { - if (yych <= '\r') goto yy203; - if (yych == ' ') goto yy203; - goto yy193; + if (yych <= '\r') goto yy195; + if (yych == ' ') goto yy195; + goto yy185; } -yy196: - YYDEBUG(196, *YYCURSOR); +yy188: + YYDEBUG(188, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(197, *YYCURSOR); + YYDEBUG(189, *YYCURSOR); if (yych <= '\f') { - if (yych == '\t') goto yy196; + if (yych == '\t') goto yy188; } else { - if (yych <= '\r') goto yy196; - if (yych == ' ') goto yy196; + if (yych <= '\r') goto yy188; + if (yych == ' ') goto yy188; } - YYDEBUG(198, *YYCURSOR); + YYDEBUG(190, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; { YYSETCONDITION(PRE_RAW); phpdbg_init_param(yylval, EMPTY_PARAM); return T_RUN; } -yy199: - YYDEBUG(199, *YYCURSOR); +yy191: + YYDEBUG(191, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(200, *YYCURSOR); + YYDEBUG(192, *YYCURSOR); if (yych <= '\f') { - if (yych == '\t') goto yy199; + if (yych == '\t') goto yy191; } else { - if (yych <= '\r') goto yy199; - if (yych == ' ') goto yy199; + if (yych <= '\r') goto yy191; + if (yych == ' ') goto yy191; } - YYDEBUG(201, *YYCURSOR); + YYDEBUG(193, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; { YYSETCONDITION(PRE_RAW); phpdbg_init_param(yylval, EMPTY_PARAM); return T_EVAL; } -yy202: - YYDEBUG(202, *YYCURSOR); +yy194: + YYDEBUG(194, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '\f') { - if (yych == '\t') goto yy196; - goto yy193; + if (yych == '\t') goto yy188; + goto yy185; } else { - if (yych <= '\r') goto yy196; - if (yych == ' ') goto yy196; - goto yy193; + if (yych <= '\r') goto yy188; + if (yych == ' ') goto yy188; + goto yy185; } -yy203: - YYDEBUG(203, *YYCURSOR); +yy195: + YYDEBUG(195, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(204, *YYCURSOR); + YYDEBUG(196, *YYCURSOR); if (yych <= '\f') { - if (yych == '\t') goto yy203; + if (yych == '\t') goto yy195; } else { - if (yych <= '\r') goto yy203; - if (yych == ' ') goto yy203; + if (yych <= '\r') goto yy195; + if (yych == ' ') goto yy195; } - YYDEBUG(205, *YYCURSOR); + YYDEBUG(197, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; { YYSETCONDITION(PRE_RAW); diff -Nru php8.2-8.2.24/sapi/phpdbg/phpdbg_lexer.l php8.2-8.2.26/sapi/phpdbg/phpdbg_lexer.l --- php8.2-8.2.24/sapi/phpdbg/phpdbg_lexer.l 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/sapi/phpdbg/phpdbg_lexer.l 2024-11-19 17:11:09.000000000 +0000 @@ -82,7 +82,7 @@ GENERIC_ID ([^ \r\n\t:#\000"']|":\\")+|["]([^\n\000"\\]|"\\\\"|"\\"["])+["]|[']([^\n\000'\\]|"\\\\"|"\\"['])+['] ADDR [0][x][a-fA-F0-9]+ OPCODE (ZEND_|zend_)([A-Z_a-z])+ -INPUT ("\\"[#"']|["]("\\\\"|"\\"["]|[^\n\000"])+["]|[']("\\"[']|"\\\\"|[^\n\000'])+[']|[^\n\000#"'])+ +INPUT ("\\"[#"']|["]("\\\\"|"\\"["]|[^\n\000"])*["]|[']("\\"[']|"\\\\"|[^\n\000'])*[']|[^\n\000#"'])+ := yyleng = (size_t) YYCURSOR - (size_t) yytext; diff -Nru php8.2-8.2.24/sapi/phpdbg/phpdbg_prompt.c php8.2-8.2.26/sapi/phpdbg/phpdbg_prompt.c --- php8.2-8.2.24/sapi/phpdbg/phpdbg_prompt.c 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/sapi/phpdbg/phpdbg_prompt.c 2024-11-19 17:11:09.000000000 +0000 @@ -907,7 +907,7 @@ } } zend_end_try(); - if (EG(exception)) { + if (EG(exception) && !zend_is_unwind_exit(EG(exception))) { phpdbg_handle_exception(); } } diff -Nru php8.2-8.2.24/sapi/phpdbg/tests/gh15901.phpt php8.2-8.2.26/sapi/phpdbg/tests/gh15901.phpt --- php8.2-8.2.24/sapi/phpdbg/tests/gh15901.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/sapi/phpdbg/tests/gh15901.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,10 @@ +--TEST-- +GH-15901 (phpdbg: Assertion failure on `i funcs`) +--PHPDBG-- +i funcs +i classes +--EXPECT-- +prompt> [User Functions (0)] +prompt> [User Classes (0)] +prompt> [User Classes (0)] +prompt> diff -Nru php8.2-8.2.24/sapi/phpdbg/tests/gh16174.phpt php8.2-8.2.26/sapi/phpdbg/tests/gh16174.phpt --- php8.2-8.2.24/sapi/phpdbg/tests/gh16174.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/sapi/phpdbg/tests/gh16174.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,10 @@ +--TEST-- +GH-16174 (Empty string is an invalid expression for phpdbg-ev) +--PHPDBG-- +ev $e = "" +ev $f = '' +--EXPECT-- +prompt> +prompt> +prompt> +prompt> diff -Nru php8.2-8.2.24/sapi/phpdbg/tests/gh16181.phpt php8.2-8.2.26/sapi/phpdbg/tests/gh16181.phpt --- php8.2-8.2.24/sapi/phpdbg/tests/gh16181.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/sapi/phpdbg/tests/gh16181.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,26 @@ +--TEST-- +GH-16181 (phpdbg: exit in exception handler reports fatal error) +--PHPDBG-- +r +c +q +--FILE-- + +--EXPECTF-- +[Successful compilation of %s] +prompt> throwing exception +[Uncaught Exception in %s on line %d: oh noes] +>00008: throw new \Exception("oh noes"); + 00009: ?> + 00010: +prompt> exception caught +[Script ended normally] +prompt> diff -Nru php8.2-8.2.24/scripts/phpize.m4 php8.2-8.2.26/scripts/phpize.m4 --- php8.2-8.2.24/scripts/phpize.m4 2024-09-24 22:12:40.000000000 +0000 +++ php8.2-8.2.26/scripts/phpize.m4 2024-11-19 17:11:09.000000000 +0000 @@ -115,10 +115,7 @@ if test "$PHP_DEBUG" = "yes"; then PHP_DEBUG=1 ZEND_DEBUG=yes - changequote({,}) - CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9s]*//g'` - CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O[0-9s]*//g'` - changequote([,]) + PHP_REMOVE_OPTIMIZATION_FLAGS dnl Add -O0 only if GCC or ICC is used. if test "$GCC" = "yes" || test "$ICC" = "yes"; then CFLAGS="$CFLAGS -O0" diff -Nru php8.2-8.2.24/tests/basic/gh15905.phpt php8.2-8.2.26/tests/basic/gh15905.phpt --- php8.2-8.2.24/tests/basic/gh15905.phpt 1970-01-01 00:00:00.000000000 +0000 +++ php8.2-8.2.26/tests/basic/gh15905.phpt 2024-11-19 17:11:09.000000000 +0000 @@ -0,0 +1,12 @@ +--TEST-- +GH-15905 (Assertion failure for TRACK_VARS_SERVER) +--INI-- +variables_order=E +auto_globals_jit=0 +register_argc_argv=1 +--FILE-- + +--EXPECT-- +okay