From 7e722e3ba4e376a5540c107e2c21be8d891e36fd Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Tue, 10 Sep 2024 15:26:28 -0400 Subject: [PATCH 01/94] PHP-8.2 is now for PHP 8.2.25-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 0f20c3548c4a8..3fc03d28552bc 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.24 +?? ??? ????, PHP 8.2.25 + + +26 Sep 2024, PHP 8.2.24 - Core: . Fixed bug GH-15408 (MSan false-positve on zend_max_execution_timer). diff --git a/Zend/zend.h b/Zend/zend.h index a01354a48aeab..8210737da9218 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.24-dev" +#define ZEND_VERSION "4.2.25-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index fb59a81700f4b..db355bbd6c5b2 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.2.24-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.25-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 44f5ed7ccc5d1..e2f9e04ada6af 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -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 25 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.24-dev" -#define PHP_VERSION_ID 80224 +#define PHP_VERSION "8.2.25-dev" +#define PHP_VERSION_ID 80225 From 7a67fb0315c553394b898d979f09499d4312d09f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 10 Sep 2024 22:44:56 +0200 Subject: [PATCH 02/94] Fix bug #62900: Wrong namespace on xsd import error message The one error message indeed had a wrong namespace, and in general they weren't very descriptive, this also makes them more descriptive. Furthermore, two additional bugs were fixed: - Persistent memory leak of `location`. - UAF issues when printing the error message. Closes GH-15830. --- NEWS | 2 + ext/soap/php_schema.c | 27 ++++++++- ext/soap/tests/bugs/bug62900.phpt | 95 +++++++++++++++++++++++++++++++ ext/soap/tests/bugs/bug62900_run | 2 + 4 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 ext/soap/tests/bugs/bug62900.phpt create mode 100644 ext/soap/tests/bugs/bug62900_run diff --git a/NEWS b/NEWS index 3fc03d28552bc..f09ad6dc62233 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.25 +- SOAP: + . Fixed bug #62900 (Wrong namespace on xsd import error message). (nielsdos) 26 Sep 2024, PHP 8.2.24 diff --git a/ext/soap/php_schema.c b/ext/soap/php_schema.c index 17ece4fe770f8..423714545ae30 100644 --- a/ext/soap/php_schema.c +++ b/ext/soap/php_schema.c @@ -92,6 +92,13 @@ static encodePtr get_create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const xmlCh 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 @@ static void schema_load_file(sdlCtx *ctx, xmlAttrPtr ns, xmlChar *location, xmlA 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 @@ static void schema_load_file(sdlCtx *ctx, xmlAttrPtr ns, xmlChar *location, xmlA 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 --git a/ext/soap/tests/bugs/bug62900.phpt b/ext/soap/tests/bugs/bug62900.phpt new file mode 100644 index 0000000000000..c78afda5304af --- /dev/null +++ b/ext/soap/tests/bugs/bug62900.phpt @@ -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 --git a/ext/soap/tests/bugs/bug62900_run b/ext/soap/tests/bugs/bug62900_run new file mode 100644 index 0000000000000..0b7f7a0f33a98 --- /dev/null +++ b/ext/soap/tests/bugs/bug62900_run @@ -0,0 +1,2 @@ + Date: Wed, 11 Sep 2024 15:46:02 +0100 Subject: [PATCH 03/94] Fix GH-15582: Crash when not calling parent constructor of DateTimeZone --- NEWS | 4 ++++ ext/date/php_date.c | 8 +++++++- ext/date/tests/bug-gh15582.phpt | 21 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 ext/date/tests/bug-gh15582.phpt diff --git a/NEWS b/NEWS index f09ad6dc62233..593ec18294882 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.25 +- Date: + . Fixed bug GH-15582: Crash when not calling parent constructor of + DateTimeZone. (Derick) + - SOAP: . Fixed bug #62900 (Wrong namespace on xsd import error message). (nielsdos) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 87dd917749187..5f21fea80432f 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -687,8 +687,11 @@ static zend_string *date_format(const char *format, size_t format_len, timelib_t (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(); } } @@ -2418,6 +2421,9 @@ PHPAPI bool php_date_initialize(php_date_obj *dateobj, const char *time_str, siz 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) { diff --git a/ext/date/tests/bug-gh15582.phpt b/ext/date/tests/bug-gh15582.phpt new file mode 100644 index 0000000000000..ab03e190e4bc3 --- /dev/null +++ b/ext/date/tests/bug-gh15582.phpt @@ -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 From 40d06fb645b42409ecb242a6ea4a4fd7207d7a0c Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 11 Sep 2024 17:30:57 +0100 Subject: [PATCH 04/94] Import timelib 2022.12 --- ext/date/lib/parse_date.c | 226 +++++---- ext/date/lib/parse_date.re | 18 +- ext/date/lib/parse_iso_intervals.c | 789 +++++++++++++++-------------- ext/date/lib/timelib.h | 8 +- ext/date/lib/timelib_private.h | 9 + 5 files changed, 552 insertions(+), 498 deletions(-) diff --git a/ext/date/lib/parse_date.c b/ext/date/lib/parse_date.c index a53fdc215472c..ea1602ef13b4e 100644 --- a/ext/date/lib/parse_date.c +++ b/ext/date/lib/parse_date.c @@ -1,4 +1,4 @@ -/* Generated by re2c 1.0.3 on Thu Nov 23 16:02:28 2023 */ +/* Generated by re2c 1.0.3 on Wed Sep 11 17:29:29 2024 */ #line 1 "ext/date/lib/parse_date.re" /* * The MIT License (MIT) @@ -549,22 +549,26 @@ static timelib_ull timelib_get_signed_nr(Scanner *s, const char **ptr, int max_l 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; } + + /* 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; - if ((**ptr == '+') || (**ptr == '-')) { - *str_ptr = **ptr; + while ((**ptr == '+') || (**ptr == '-')) { + if (**ptr == '-') { + str[0] = str[0] == '+' ? '-' : '+'; + } ++*ptr; - ++str_ptr; } while (((**ptr < '0') || (**ptr > '9'))) { @@ -715,7 +719,7 @@ static const timelib_relunit* timelib_lookup_relunit(const char **ptr) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIMEZONE; } -#line 1791 "" +#line 1795 "" yy21: YYDEBUG(21, *YYCURSOR); yych = *++YYCURSOR; @@ -3592,7 +3596,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 3607 "" +#line 3611 "" yy82: YYDEBUG(82, *YYCURSOR); yych = *++YYCURSOR; @@ -4118,7 +4122,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 4147 "" +#line 4151 "" yy115: YYDEBUG(115, *YYCURSOR); ++YYCURSOR; @@ -5869,7 +5873,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 5900 "" +#line 5904 "" yy178: YYDEBUG(178, *YYCURSOR); yyaccept = 4; @@ -6925,7 +6929,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_AMERICAN; } -#line 6944 "" +#line 6948 "" yy225: YYDEBUG(225, *YYCURSOR); yyaccept = 5; @@ -7183,7 +7187,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL; } -#line 7201 "" +#line 7205 "" yy252: YYDEBUG(252, *YYCURSOR); yyaccept = 3; @@ -7311,7 +7315,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 7330 "" +#line 7334 "" yy261: YYDEBUG(261, *YYCURSOR); yych = *++YYCURSOR; @@ -7772,7 +7776,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 7815 "" +#line 7819 "" yy291: YYDEBUG(291, *YYCURSOR); yych = *++YYCURSOR; @@ -7836,7 +7840,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_AGO; } -#line 7860 "" +#line 7864 "" yy294: YYDEBUG(294, *YYCURSOR); yyaccept = 7; @@ -7895,7 +7899,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 7908 "" +#line 7912 "" yy296: YYDEBUG(296, *YYCURSOR); yyaccept = 7; @@ -8479,7 +8483,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_WEEKDAY; } -#line 8500 "" +#line 8504 "" yy316: YYDEBUG(316, *YYCURSOR); yych = *++YYCURSOR; @@ -8764,7 +8768,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 8781 "" +#line 8785 "" yy326: YYDEBUG(326, *YYCURSOR); yyaccept = 10; @@ -9471,7 +9475,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 9483 "" +#line 9487 "" yy352: YYDEBUG(352, *YYCURSOR); yyaccept = 2; @@ -10982,7 +10986,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_GNU_NOCOLON; } -#line 11008 "" +#line 11012 "" yy421: YYDEBUG(421, *YYCURSOR); yyaccept = 13; @@ -11085,7 +11089,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 11097 "" +#line 11101 "" yy423: YYDEBUG(423, *YYCURSOR); yyaccept = 3; @@ -11700,7 +11704,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME12; } -#line 11721 "" +#line 11725 "" yy458: YYDEBUG(458, *YYCURSOR); yych = *++YYCURSOR; @@ -13044,7 +13048,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 13059 "" +#line 13063 "" yy527: YYDEBUG(527, *YYCURSOR); yyaccept = 2; @@ -14101,7 +14105,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 14118 "" +#line 14122 "" yy568: YYDEBUG(568, *YYCURSOR); yyaccept = 15; @@ -14565,7 +14569,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 14582 "" +#line 14586 "" yy601: YYDEBUG(601, *YYCURSOR); yych = *++YYCURSOR; @@ -15953,7 +15957,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 15970 "" +#line 15974 "" yy698: YYDEBUG(698, *YYCURSOR); yych = *++YYCURSOR; @@ -16527,7 +16531,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 16540 "" +#line 16544 "" yy723: YYDEBUG(723, *YYCURSOR); yych = *++YYCURSOR; @@ -16846,7 +16850,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 16863 "" +#line 16867 "" yy740: YYDEBUG(740, *YYCURSOR); yyaccept = 15; @@ -16971,7 +16975,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 16988 "" +#line 16992 "" yy753: YYDEBUG(753, *YYCURSOR); yyaccept = 18; @@ -17233,7 +17237,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_NOCOLON; } -#line 17256 "" +#line 17260 "" yy778: YYDEBUG(778, *YYCURSOR); yyaccept = 19; @@ -18480,7 +18484,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 18513 "" +#line 18517 "" yy850: YYDEBUG(850, *YYCURSOR); yyaccept = 20; @@ -19553,7 +19557,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_YEARDAY; } -#line 19570 "" +#line 19574 "" yy927: YYDEBUG(927, *YYCURSOR); yyaccept = 21; @@ -19820,7 +19824,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 19842 "" +#line 19846 "" yy943: YYDEBUG(943, *YYCURSOR); yych = *++YYCURSOR; @@ -20314,7 +20318,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 20334 "" +#line 20338 "" yy983: YYDEBUG(983, *YYCURSOR); yych = *++YYCURSOR; @@ -20677,7 +20681,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 20692 "" +#line 20696 "" yy1022: YYDEBUG(1022, *YYCURSOR); ++YYCURSOR; @@ -20717,7 +20721,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 20734 "" +#line 20738 "" yy1026: YYDEBUG(1026, *YYCURSOR); yyaccept = 15; @@ -20950,7 +20954,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 20965 "" +#line 20969 "" yy1044: YYDEBUG(1044, *YYCURSOR); yyaccept = 26; @@ -21076,7 +21080,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NOCOLON; } -#line 21091 "" +#line 21095 "" yy1049: YYDEBUG(1049, *YYCURSOR); yych = *++YYCURSOR; @@ -21157,7 +21161,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 21179 "" +#line 21183 "" yy1061: YYDEBUG(1061, *YYCURSOR); yych = *++YYCURSOR; @@ -21238,7 +21242,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 21255 "" +#line 21259 "" yy1071: YYDEBUG(1071, *YYCURSOR); yych = *++YYCURSOR; @@ -21724,7 +21728,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) ++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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 21739 "" +#line 21743 "" yy1108: YYDEBUG(1108, *YYCURSOR); yyaccept = 28; @@ -22072,7 +22076,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 22089 "" +#line 22093 "" yy1142: YYDEBUG(1142, *YYCURSOR); ++YYCURSOR; @@ -22129,7 +22133,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 22155 "" +#line 22159 "" yy1146: YYDEBUG(1146, *YYCURSOR); yyaccept = 29; @@ -22475,7 +22479,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22502 "" +#line 22506 "" yy1173: YYDEBUG(1173, *YYCURSOR); yych = *++YYCURSOR; @@ -22510,7 +22514,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) ++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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22525 "" +#line 22529 "" yy1176: YYDEBUG(1176, *YYCURSOR); yyaccept = 31; @@ -23014,7 +23018,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 23041 "" +#line 23045 "" yy1224: YYDEBUG(1224, *YYCURSOR); yych = *++YYCURSOR; @@ -23539,7 +23543,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_WEEK_DAY_OF_MONTH; } -#line 23564 "" +#line 23568 "" yy1270: YYDEBUG(1270, *YYCURSOR); yyaccept = 24; @@ -23607,7 +23611,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 23643 "" +#line 23647 "" yy1277: YYDEBUG(1277, *YYCURSOR); yych = *++YYCURSOR; @@ -23742,7 +23746,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 23765 "" +#line 23769 "" yy1292: YYDEBUG(1292, *YYCURSOR); yych = *++YYCURSOR; @@ -24185,7 +24189,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_XMLRPC_SOAP; } -#line 24214 "" +#line 24218 "" yy1330: YYDEBUG(1330, *YYCURSOR); yych = *++YYCURSOR; @@ -24580,7 +24584,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) 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 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 24607 "" +#line 24611 "" yy1376: YYDEBUG(1376, *YYCURSOR); yyaccept = 33; @@ -24835,7 +24839,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych == ':') goto yy1286; goto yy1329; } -#line 1990 "ext/date/lib/parse_date.re" +#line 1994 "ext/date/lib/parse_date.re" } diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re index 5d259ed4e2c75..d32be9bfe7be7 100644 --- a/ext/date/lib/parse_date.re +++ b/ext/date/lib/parse_date.re @@ -547,22 +547,26 @@ static timelib_ull timelib_get_signed_nr(Scanner *s, const char **ptr, int max_l 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; } + + /* 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; - if ((**ptr == '+') || (**ptr == '-')) { - *str_ptr = **ptr; + while ((**ptr == '+') || (**ptr == '-')) { + if (**ptr == '-') { + str[0] = str[0] == '+' ? '-' : '+'; + } ++*ptr; - ++str_ptr; } while (((**ptr < '0') || (**ptr > '9'))) { @@ -713,7 +717,7 @@ static const timelib_relunit* timelib_lookup_relunit(const char **ptr) 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 --git a/ext/date/lib/parse_iso_intervals.c b/ext/date/lib/parse_iso_intervals.c index 6715d5cee525f..cdc329431ec45 100644 --- a/ext/date/lib/parse_iso_intervals.c +++ b/ext/date/lib/parse_iso_intervals.c @@ -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 @@ static int scan(Scanner *s) yych = *YYCURSOR; if (yych <= ',') { if (yych <= '\n') { - if (yych <= 0x00) goto yy9; - if (yych <= 0x08) goto yy11; - if (yych <= '\t') goto yy7; - goto yy9; + if (yych <= 0x00) goto yy2; + if (yych <= 0x08) goto yy4; + if (yych <= '\t') goto yy6; } else { - if (yych == ' ') goto yy7; - if (yych <= '+') goto yy11; - goto yy7; + 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 @@ static int scan(Scanner *s) 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 @@ static int scan(Scanner *s) 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 @@ static int scan(Scanner *s) 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 @@ static int scan(Scanner *s) 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 @@ static int scan(Scanner *s) #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 --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index 4582fcfd46917..a2c976af7ed9c 100644 --- a/ext/date/lib/timelib.h +++ b/ext/date/lib/timelib.h @@ -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 --git a/ext/date/lib/timelib_private.h b/ext/date/lib/timelib_private.h index 65ec6b014b894..3c5f9b22147c0 100644 --- a/ext/date/lib/timelib_private.h +++ b/ext/date/lib/timelib_private.h @@ -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; From 8a8859bce7dd08813d3875ee84a48e4d3130d8b5 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 11 Sep 2024 17:36:48 +0100 Subject: [PATCH 05/94] Fixed regression: Using more than one sign is now OK again when using modify() --- NEWS | 2 ++ ext/date/tests/bug40861.phpt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 593ec18294882..b5454bffccdb5 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - 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) - SOAP: . Fixed bug #62900 (Wrong namespace on xsd import error message). (nielsdos) diff --git a/ext/date/tests/bug40861.phpt b/ext/date/tests/bug40861.phpt index 224d8eb0a71de..d4ef96198c7ff 100644 --- a/ext/date/tests/bug40861.phpt +++ b/ext/date/tests/bug40861.phpt @@ -28,6 +28,6 @@ echo $result . "\n"; ?> --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 From b5834c12d4cb06b9ba9ae9e2b62eea36862f1ba4 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 11 Sep 2024 19:02:07 +0200 Subject: [PATCH 06/94] Fix GH-15837: Segmentation fault in ext/simplexml/simplexml.c We should check if the iterator data is still valid, because if it isn't, then the type info is UNDEF, but the pointer value may be dangling. Closes GH-15841. --- NEWS | 4 ++++ ext/simplexml/simplexml.c | 5 +++++ ext/simplexml/tests/gh15837.phpt | 30 ++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 ext/simplexml/tests/gh15837.phpt diff --git a/NEWS b/NEWS index b5454bffccdb5..21ab2923e23f3 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ PHP NEWS . Fixed regression where signs after the first one were ignored while parsing a signed integer, with the DateTimeInterface::modify() function. (Derick) +- SimpleXML: + . Fixed bug GH-15837 (Segmentation fault in ext/simplexml/simplexml.c). + (nielsdos) + - SOAP: . Fixed bug #62900 (Wrong namespace on xsd import error message). (nielsdos) diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 6bcb9edcfface..21cd5cdb4c7bd 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -2547,6 +2547,11 @@ static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key) { 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 --git a/ext/simplexml/tests/gh15837.phpt b/ext/simplexml/tests/gh15837.phpt new file mode 100644 index 0000000000000..302db064ee0e7 --- /dev/null +++ b/ext/simplexml/tests/gh15837.phpt @@ -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 From 791a6ef19c72f735b1442596fc9d26fe6f3a0997 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 28 Aug 2024 12:55:29 +0100 Subject: [PATCH 07/94] Fix GH-15613: unpack on format hex strings repeater value. close GH-15615 --- NEWS | 4 ++++ ext/standard/pack.c | 7 +++++++ ext/standard/tests/strings/gh15613.phpt | 25 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 ext/standard/tests/strings/gh15613.phpt diff --git a/NEWS b/NEWS index 21ab2923e23f3..001f5ba9cca62 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,10 @@ PHP NEWS - SOAP: . Fixed bug #62900 (Wrong namespace on xsd import error message). (nielsdos) +- Standard: + . Fixed bug GH-15613 (overflow on unpack call hex string repeater). + (David Carlier) + 26 Sep 2024, PHP 8.2.24 - Core: diff --git a/ext/standard/pack.c b/ext/standard/pack.c index d12cd280a812f..24d116d302052 100644 --- a/ext/standard/pack.c +++ b/ext/standard/pack.c @@ -979,6 +979,13 @@ PHP_FUNCTION(unpack) 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 --git a/ext/standard/tests/strings/gh15613.phpt b/ext/standard/tests/strings/gh15613.phpt new file mode 100644 index 0000000000000..8f40ee820c9a2 --- /dev/null +++ b/ext/standard/tests/strings/gh15613.phpt @@ -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 From 503d9145e0b6343c45fd17132519dde478293c1a Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 2 Sep 2024 18:03:28 +0100 Subject: [PATCH 08/94] Fix GH-15712: overflow on float print with precision ini large value. When allocating enough room for floats, the allocator used overflows with large ndigits/EG(precision) value which used an signed integer to increase the size of thebuffer. Testing with the zend operator directly is enough to trigger the issue rather than higher level math interface. close GH-15715 --- NEWS | 4 ++++ Zend/tests/gh15712.phpt | 9 +++++++++ Zend/zend_strtod.c | 6 +++--- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/gh15712.phpt diff --git a/NEWS b/NEWS index 001f5ba9cca62..194e89b7e4b01 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.25 +- Core: + . Fixed bug GH-15712: zend_strtod overflow with precision INI set on + large value. (David Carlier) + - Date: . Fixed bug GH-15582: Crash when not calling parent constructor of DateTimeZone. (Derick) diff --git a/Zend/tests/gh15712.phpt b/Zend/tests/gh15712.phpt new file mode 100644 index 0000000000000..7c4bd0b22ac11 --- /dev/null +++ b/Zend/tests/gh15712.phpt @@ -0,0 +1,9 @@ +--TEST-- +GH-15712: overflow on real number printing +--FILE-- + +--EXPECTF-- +%s diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c index 3e7f90378ef5e..eb3a94332ae35 100644 --- a/Zend/zend_strtod.c +++ b/Zend/zend_strtod.c @@ -3613,11 +3613,11 @@ rv_alloc(i) int i; 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); From 60c26877123e63373d0ef2bdedd9671c013feb3a Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 22 May 2024 13:22:34 +0200 Subject: [PATCH 09/94] Fix removal of optimization cflags in debug builds (#9647) Discard known '-O' flags, including just '-O', but do not remove only '-O' in '-Ounknown' --- configure.ac | 10 ++++++---- scripts/phpize.m4 | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index db355bbd6c5b2..ad1f42cfbed7d 100644 --- a/configure.ac +++ b/configure.ac @@ -846,8 +846,9 @@ if test "$PHP_GCOV" = "yes"; then 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'` + dnl Discard known '-O...' flags, including just '-O', but do not remove only '-O' in '-Ounknown' + CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//g'` + CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//g'` changequote([,]) dnl Add the special gcc flags. @@ -866,8 +867,9 @@ 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'` + dnl Discard known '-O...' flags, including just '-O', but do not remove only '-O' in '-Ounknown' + CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//g'` + CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//g'` changequote([,]) dnl Add -O0 only if GCC or ICC is used. if test "$GCC" = "yes" || test "$ICC" = "yes"; then diff --git a/scripts/phpize.m4 b/scripts/phpize.m4 index 616d16420a5a1..14bcde45f03a3 100644 --- a/scripts/phpize.m4 +++ b/scripts/phpize.m4 @@ -116,8 +116,9 @@ 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'` + dnl Discard known '-O...' flags, including just '-O', but do not remove only '-O' in '-Ounknown' + CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//g'` + CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//g'` changequote([,]) dnl Add -O0 only if GCC or ICC is used. if test "$GCC" = "yes" || test "$ICC" = "yes"; then From c639614346ec08c0a2b62fb62e2db129ea4d6e39 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 10 Sep 2024 18:40:49 +0200 Subject: [PATCH 10/94] Do not remove -O0 in the middle of a flag Fixes GH-15826 Closes GH-15828 Co-authored-by: Peter Kokot --- build/php.m4 | 12 ++++++++++++ configure.ac | 12 ++---------- scripts/phpize.m4 | 6 +----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/build/php.m4 b/build/php.m4 index 32487e4b389ec..e13fc3367ea1e 100644 --- a/build/php.m4 +++ b/build/php.m4 @@ -2735,3 +2735,15 @@ AC_DEFUN([PHP_PATCH_CONFIG_HEADERS], [ $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 --git a/configure.ac b/configure.ac index ad1f42cfbed7d..9c71f6503311d 100644 --- a/configure.ac +++ b/configure.ac @@ -845,11 +845,7 @@ if test "$PHP_GCOV" = "yes"; then PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/build/Makefile.gcov, $abs_srcdir) dnl Remove all optimization flags from CFLAGS. - changequote({,}) - dnl Discard known '-O...' flags, including just '-O', but do not remove only '-O' in '-Ounknown' - CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//g'` - CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//g'` - changequote([,]) + PHP_REMOVE_OPTIMIZATION_FLAGS dnl Add the special gcc flags. CFLAGS="$CFLAGS -O0 -fprofile-arcs -ftest-coverage" @@ -866,11 +862,7 @@ PHP_ARG_ENABLE([debug], if test "$PHP_DEBUG" = "yes"; then PHP_DEBUG=1 ZEND_DEBUG=yes - changequote({,}) - dnl Discard known '-O...' flags, including just '-O', but do not remove only '-O' in '-Ounknown' - CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//g'` - CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//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 --git a/scripts/phpize.m4 b/scripts/phpize.m4 index 14bcde45f03a3..b713dcc650593 100644 --- a/scripts/phpize.m4 +++ b/scripts/phpize.m4 @@ -115,11 +115,7 @@ dnl Discard optimization flags when debugging is enabled. if test "$PHP_DEBUG" = "yes"; then PHP_DEBUG=1 ZEND_DEBUG=yes - changequote({,}) - dnl Discard known '-O...' flags, including just '-O', but do not remove only '-O' in '-Ounknown' - CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//g'` - CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O\([0-9gsz]\|fast\|\)\([\t ]\|$\)//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" From f74f9b073afa636ca74879bbb43e44f8a7fa8730 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:35:34 +0200 Subject: [PATCH 11/94] Update libxml test for the directory field behaviour change See https://gitlab.gnome.org/GNOME/libxml2/-/issues/753. The base directory for the entity is no longer set, follow the upstream behaviour. --- .../tests/libxml_set_external_entity_loader_variation1.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt b/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt index b480652209d53..e56e59c38698b 100644 --- a/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt +++ b/ext/libxml/tests/libxml_set_external_entity_loader_variation1.phpt @@ -61,7 +61,7 @@ string(13) "-//FOO/ENTITY" string(32) "http://example.com/fooentity.ent" array(4) { ["directory"]=> - string(%d) "%s" + %r(NULL|string\(%d\) "%s")%r ["intSubName"]=> string(3) "foo" ["extSubURI"]=> From 3ec5919e14897b47e914efddd17f01750ba3ba86 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:37:21 +0200 Subject: [PATCH 12/94] Update error message for libxml 2.13 External entity loading got its error level decreased in upstream, which means they now map to E_NOTICE. Also the error message format has changed. --- ext/libxml/tests/bug61367-read_2.phpt | 2 +- ext/libxml/tests/libxml_disable_entity_loader_2.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/libxml/tests/bug61367-read_2.phpt b/ext/libxml/tests/bug61367-read_2.phpt index bbcf696773bf0..f4b0f300293c8 100644 --- a/ext/libxml/tests/bug61367-read_2.phpt +++ b/ext/libxml/tests/bug61367-read_2.phpt @@ -58,6 +58,6 @@ bool(true) 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 --git a/ext/libxml/tests/libxml_disable_entity_loader_2.phpt b/ext/libxml/tests/libxml_disable_entity_loader_2.phpt index 182fe13cfda96..216792600bf0b 100644 --- a/ext/libxml/tests/libxml_disable_entity_loader_2.phpt +++ b/ext/libxml/tests/libxml_disable_entity_loader_2.phpt @@ -39,6 +39,6 @@ bool(true) 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 From 3354cc6e89df9f1c3c5c0b78506288f2928aa109 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:10:51 +0200 Subject: [PATCH 13/94] Update test for changed error message format in libxml 2.13 --- ext/zend_test/tests/observer_error_04.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/zend_test/tests/observer_error_04.phpt b/ext/zend_test/tests/observer_error_04.phpt index bb3ee1013ec47..2a45bfe78c48d 100644 --- a/ext/zend_test/tests/observer_error_04.phpt +++ b/ext/zend_test/tests/observer_error_04.phpt @@ -47,9 +47,9 @@ echo 'Done.' . PHP_EOL; - -SOAP-ERROR: Parsing WSDL: Couldn't load from 'foo' : failed to load external entity "foo" +SOAP-ERROR: Parsing WSDL: %s Done. From fecad54d74bbf703d0fb2c0b73d97614c9fb5f28 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Fri, 13 Sep 2024 11:04:45 +0100 Subject: [PATCH 14/94] Backport fix from PHP 8.3: The exception handler already takes care of destroying the return value --- ext/date/php_date.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 5f21fea80432f..dc9eb995b8f65 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -3822,7 +3822,6 @@ PHP_METHOD(DateTimeZone, __set_state) 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(); } } From 4e12189604d76396f8c3b9d5dda6e8757f1d8618 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 13 Sep 2024 15:29:21 +0200 Subject: [PATCH 15/94] Mark some phar tests as flaky on macOS Fixes GH-15748 Closes GH-15876 --- ext/phar/tests/033a.phpt | 6 ++++++ ext/phar/tests/phar_oo_002.phpt | 6 ++++++ ext/phar/tests/stat.phpt | 6 ++++++ ext/phar/tests/tar/033a.phpt | 6 ++++++ ext/phar/tests/zip/033a.phpt | 6 ++++++ run-tests.php | 3 +++ 6 files changed, 33 insertions(+) diff --git a/ext/phar/tests/033a.phpt b/ext/phar/tests/033a.phpt index c36c5c6853985..355617b29f93f 100644 --- a/ext/phar/tests/033a.phpt +++ b/ext/phar/tests/033a.phpt @@ -5,6 +5,12 @@ phar --INI-- phar.readonly=1 phar.require_hash=0 +--SKIPIF-- + --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- 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'][] = [ From ac8db365432103b2b7fe5f65919ab3ce300cc343 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 13 Sep 2024 18:22:38 +0200 Subject: [PATCH 16/94] Fix GH-15868: Assertion failure in xml_parse_into_struct after exception Upon unwinding from an exception, the parser state is not stable, we should not continue updating the values if an exception was thrown. Closes GH-15879. --- NEWS | 4 ++++ ext/xml/tests/gh15868.phpt | 46 ++++++++++++++++++++++++++++++++++++++ ext/xml/xml.c | 6 ++--- 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 ext/xml/tests/gh15868.phpt diff --git a/NEWS b/NEWS index 194e89b7e4b01..a9c4598e2fc82 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,10 @@ PHP NEWS . Fixed bug GH-15613 (overflow on unpack call hex string repeater). (David Carlier) +- XML: + . Fixed bug GH-15868 (Assertion failure in xml_parse_into_struct after + exception). (nielsdos) + 26 Sep 2024, PHP 8.2.24 - Core: diff --git a/ext/xml/tests/gh15868.phpt b/ext/xml/tests/gh15868.phpt new file mode 100644 index 0000000000000..17ed80558d786 --- /dev/null +++ b/ext/xml/tests/gh15868.phpt @@ -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 --git a/ext/xml/xml.c b/ext/xml/xml.c index 59d50faed111e..eef78474281bb 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -628,7 +628,7 @@ void _xml_startElementHandler(void *userData, const XML_Char *name, const XML_Ch 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 @@ void _xml_endElementHandler(void *userData, const XML_Char *name) 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 @@ void _xml_characterDataHandler(void *userData, const XML_Char *s, int len) zval_ptr_dtor(&retval); } - if (Z_ISUNDEF(parser->data)) { + if (Z_ISUNDEF(parser->data) || EG(exception)) { return; } From 664e03906928df75250ab5e6b1556a09adad149f Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 13 Sep 2024 16:22:04 +0200 Subject: [PATCH 17/94] Fix GA macOS brew warnings These pollute the job overview. Closes GH-15877 --- .github/actions/brew/action.yml | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/.github/actions/brew/action.yml b/.github/actions/brew/action.yml index 5868d3917b80c..360c0a85c99f7 100644 --- a/.github/actions/brew/action.yml +++ b/.github/actions/brew/action.yml @@ -12,31 +12,15 @@ runs: 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 From b26e610777a2560e1765448f8a597530ab22cd5d Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sun, 15 Sep 2024 19:08:04 +0200 Subject: [PATCH 18/94] Run snmp tests in Windows CI, again That was broken when CI was moved to GH, since `APPVEYOR_BUILD_FOLDER` is no longer set; instead we use `GITHUB_WORKSPACE` which has the same meaning. Closes GH-15896. --- .github/scripts/windows/test_task.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/windows/test_task.bat b/.github/scripts/windows/test_task.bat index f41b11d06f6db..4a180df27dfab 100644 --- a/.github/scripts/windows/test_task.bat +++ b/.github/scripts/windows/test_task.bat @@ -105,7 +105,7 @@ 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 From 422aa17b9b2e1948f07f468b30112adc657b7331 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 18 Sep 2024 18:51:35 +0200 Subject: [PATCH 19/94] Fix GH-15901: phpdbg: Assertion failure on `i funcs` New hash tables are not automatically packed, so we must not treat them as such. Therefore we guard the foreach appropriately. Closes GH-15929. --- NEWS | 3 ++ sapi/phpdbg/phpdbg_info.c | 60 ++++++++++++++++++---------------- sapi/phpdbg/tests/gh15901.phpt | 10 ++++++ 3 files changed, 45 insertions(+), 28 deletions(-) create mode 100644 sapi/phpdbg/tests/gh15901.phpt diff --git a/NEWS b/NEWS index a9c4598e2fc82..9c279d909688e 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,9 @@ PHP NEWS . Fixed regression where signs after the first one were ignored while parsing a signed integer, with the DateTimeInterface::modify() function. (Derick) +- PHPDBG: + . Fixed bug GH-15901 (phpdbg: Assertion failure on i funcs). (cmb) + - SimpleXML: . Fixed bug GH-15837 (Segmentation fault in ext/simplexml/simplexml.c). (nielsdos) diff --git a/sapi/phpdbg/phpdbg_info.c b/sapi/phpdbg/phpdbg_info.c index b6c48d548f1f0..d64703755cbe0 100644 --- a/sapi/phpdbg/phpdbg_info.c +++ b/sapi/phpdbg/phpdbg_info.c @@ -399,27 +399,29 @@ PHPDBG_INFO(classes) /* {{{ */ 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 (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 (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->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(); + 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_destroy(&classes); @@ -445,17 +447,19 @@ PHPDBG_INFO(funcs) /* {{{ */ 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 --git a/sapi/phpdbg/tests/gh15901.phpt b/sapi/phpdbg/tests/gh15901.phpt new file mode 100644 index 0000000000000..00783b71968a2 --- /dev/null +++ b/sapi/phpdbg/tests/gh15901.phpt @@ -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> From 170230f29b619165eef2724e817dd1c3f1481319 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sun, 1 Sep 2024 13:53:55 +0200 Subject: [PATCH 20/94] [ci skip] Add labels to PRs with potential ABI breaks ABI breaks are not supposed to happen after feature freeze, i.e. when the PHP API numbers have been bumped. To make it easier to notice inadvertent ABI breaks, we automatically add an "ABI break" label to all PRs which modify public (aka. installed) header files. Some of these modifications do not constitute an ABI break (e.g. adding a comment to a header file), but we rely on natural intelligence to sort that out. That means these labels should be removed manually, if they are not appropriate, but if they are, the PR should not be merged into any stable branch. For the master branch, where ABI breaks are permissible, the labels should still be removed if irrelevant, but kept when the PR is merged. Since tests are futile[1], we leave that to further (test) PRs. [1] Closes GH-15682. --- .github/labeler.yml | 92 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/.github/labeler.yml b/.github/labeler.yml index ddab485008955..14a6ed9610dab 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -241,3 +241,95 @@ "SAPI: phpdbg": - sapi/phpdbg/**/* + +"ABI break": + - changed-files: + - any-glob-to-any-file: + - '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' \ No newline at end of file From 18ab97b9c24e9f59916c9981d6a627462aa00291 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sat, 21 Sep 2024 20:02:19 +0200 Subject: [PATCH 21/94] [skip ci] Remove myself as CODEOWNER I'm subscribed to the pulls list, so I'm just receiving each notification three times (GitHub sends to e-mails for each PR, for some reason). --- .github/CODEOWNERS | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 24a656eac19e0..6b57831db9ff9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -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 @@ -55,26 +55,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 From 018c0b3d1460843a4e7bb0842dffd759a7ef5791 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 16 Sep 2024 20:23:52 +0200 Subject: [PATCH 22/94] Fix GH-15908 and GH-15026: leak / assertion failure in streams.c This was first reported as a leak in GH-15026, but was mistakingly believed to be a false positive. Then an assertion was added and it got triggered in GH-15908. This fixes the leak. Upon merging into master the assertion should be removed as well. Closes GH-15924. --- NEWS | 4 +++ ext/standard/tests/streams/gh15908.phpt | 38 +++++++++++++++++++++++++ main/streams/streams.c | 3 ++ 3 files changed, 45 insertions(+) create mode 100644 ext/standard/tests/streams/gh15908.phpt diff --git a/NEWS b/NEWS index 9c279d909688e..12dbbc7d3ae0c 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,10 @@ PHP NEWS . Fixed bug GH-15613 (overflow on unpack call hex string repeater). (David Carlier) +- Streams: + . Fixed bugs GH-15908 and GH-15026 (leak / assertion failure in streams.c). + (nielsdos) + - XML: . Fixed bug GH-15868 (Assertion failure in xml_parse_into_struct after exception). (nielsdos) diff --git a/ext/standard/tests/streams/gh15908.phpt b/ext/standard/tests/streams/gh15908.phpt new file mode 100644 index 0000000000000..31714b20530af --- /dev/null +++ b/ext/standard/tests/streams/gh15908.phpt @@ -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 --git a/main/streams/streams.c b/main/streams/streams.c index 33f8b7e7a80cd..e22d9e51d594a 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -2175,6 +2175,9 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(const char *path, const char *mod options &= ~USE_PATH; } if (EG(exception)) { + if (resolved_path) { + zend_string_release_ex(resolved_path, false); + } return NULL; } } From f303840a86234778e3e8f78e2248723e38b453b8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sun, 22 Sep 2024 15:28:40 +0200 Subject: [PATCH 23/94] Prevent closing of unrelated handles If our `shmget()` fails for certain reasons, the segment handle is closed. However, the handle might be reused by Windows, and as such we must not close it again when shutting down the TSRM. Closes GH-15984. --- NEWS | 3 +++ TSRM/tsrm_win32.c | 1 + 2 files changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 12dbbc7d3ae0c..f8e6f5ee82fa1 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,9 @@ PHP NEWS . Fixed bugs GH-15908 and GH-15026 (leak / assertion failure in streams.c). (nielsdos) +- TSRM: + . Prevent closing of unrelated handles. (cmb) + - XML: . Fixed bug GH-15868 (Assertion failure in xml_parse_into_struct after exception). (nielsdos) diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c index 0af03b6ed8985..5d48ea2678a6c 100644 --- a/TSRM/tsrm_win32.c +++ b/TSRM/tsrm_win32.c @@ -707,6 +707,7 @@ TSRM_API int shmget(key_t key, size_t size, int flags) 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; From 792a0e6decedf916c5606cc77b95cc12002c8877 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Sun, 22 Sep 2024 15:26:59 -0300 Subject: [PATCH 24/94] Cast big endian byte shuffling to uint This works, but UBSan running on a big endian platform (in this, ppc64) will complain that the ((uchar*)buffer)[n] is int, and shifting that could be weird. Since the value of PHAR_GET_32 et al are almost always unsigned, it makes sense to cast these as unsigned. Fixes phar tests on a big endian system with UBSan enabled. --- ext/phar/phar.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index b774f22e2d565..e3d6ea74c6182 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -457,14 +457,14 @@ void phar_entry_remove(phar_entry_data *idata, char **error) /* {{{ */ #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) \ From 6a04c79e41bcdb8f8a62270b7d25f82698b9c5f0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sun, 22 Sep 2024 20:35:56 +0200 Subject: [PATCH 25/94] Fix GH-15980: Signed integer overflow in main/streams/streams.c We need to avoid signed integer overflows which are undefined behavior. We catch that, and set `offset` to `ZEND_LONG_MAX` (which is also the largest value of `zend_off_t` on all platforms). Of course, after such a seek a stream is no longer readable, but that matches the current behavior for offsets near `ZEND_LONG_MAX`. Closes GH-15989. --- NEWS | 2 ++ ext/standard/tests/streams/gh15980.phpt | 11 +++++++++++ main/streams/streams.c | 9 +++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 ext/standard/tests/streams/gh15980.phpt diff --git a/NEWS b/NEWS index f8e6f5ee82fa1..f127cce068f96 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,8 @@ PHP NEWS - 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) diff --git a/ext/standard/tests/streams/gh15980.phpt b/ext/standard/tests/streams/gh15980.phpt new file mode 100644 index 0000000000000..125751648bfa0 --- /dev/null +++ b/ext/standard/tests/streams/gh15980.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-15980 (Signed integer overflow in main/streams/streams.c) +--FILE-- + 1); +?> +--EXPECT-- +bool(true) diff --git a/main/streams/streams.c b/main/streams/streams.c index e22d9e51d594a..4c66d8aadc39b 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1354,8 +1354,13 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence) 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); From ee95ee7216a90ea0b958869be901564f2cec0190 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 23 Sep 2024 01:31:05 +0200 Subject: [PATCH 26/94] Revert "Fix GH-15980: Signed integer overflow in main/streams/streams.c" This reverts commit 6a04c79e41bcdb8f8a62270b7d25f82698b9c5f0, since the new test case apparently fails on 64bit Linux, so this needs closer investigation. --- NEWS | 2 -- ext/standard/tests/streams/gh15980.phpt | 11 ----------- main/streams/streams.c | 9 ++------- 3 files changed, 2 insertions(+), 20 deletions(-) delete mode 100644 ext/standard/tests/streams/gh15980.phpt diff --git a/NEWS b/NEWS index f127cce068f96..f8e6f5ee82fa1 100644 --- a/NEWS +++ b/NEWS @@ -29,8 +29,6 @@ PHP NEWS - 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) diff --git a/ext/standard/tests/streams/gh15980.phpt b/ext/standard/tests/streams/gh15980.phpt deleted file mode 100644 index 125751648bfa0..0000000000000 --- a/ext/standard/tests/streams/gh15980.phpt +++ /dev/null @@ -1,11 +0,0 @@ ---TEST-- -GH-15980 (Signed integer overflow in main/streams/streams.c) ---FILE-- - 1); -?> ---EXPECT-- -bool(true) diff --git a/main/streams/streams.c b/main/streams/streams.c index 4c66d8aadc39b..e22d9e51d594a 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1354,13 +1354,8 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence) switch(whence) { case SEEK_CUR: - 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; + offset = stream->position + offset; + whence = SEEK_SET; break; } ret = stream->ops->seek(stream, offset, whence, &stream->position); From d65a1e6f9171e01ca81adc8d9dd1daf3125efc36 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 9 Sep 2024 15:22:07 +0200 Subject: [PATCH 27/94] Fix GHSA-9pqp-7h25-4f32 multipart/form-data boundaries larger than the read buffer result in erroneous parsing, which violates data integrity. Limit boundary size, as allowed by RFC 1521: Encapsulation boundaries [...] must be no longer than 70 characters, not counting the two leading hyphens. We correctly parse payloads with boundaries of length up to FILLUNIT-strlen("\r\n--") bytes, so allow this for BC. --- main/rfc1867.c | 7 ++ tests/basic/GHSA-9pqp-7h25-4f32.inc | 3 + tests/basic/GHSA-9pqp-7h25-4f32.phpt | 100 +++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 tests/basic/GHSA-9pqp-7h25-4f32.inc create mode 100644 tests/basic/GHSA-9pqp-7h25-4f32.phpt diff --git a/main/rfc1867.c b/main/rfc1867.c index 2ddad7950fdf0..83d141d38b112 100644 --- a/main/rfc1867.c +++ b/main/rfc1867.c @@ -751,6 +751,13 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ boundary_len = boundary_end-boundary; } + /* Boundaries larger than FILLUNIT-strlen("\r\n--") characters lead to + * erroneous parsing */ + if (boundary_len > FILLUNIT-strlen("\r\n--")) { + sapi_module.sapi_error(E_WARNING, "Boundary too large in multipart/form-data POST data"); + return; + } + /* Initialize the buffer */ if (!(mbuff = multipart_buffer_new(boundary, boundary_len))) { sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer"); diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.inc b/tests/basic/GHSA-9pqp-7h25-4f32.inc new file mode 100644 index 0000000000000..adf72a361a2cb --- /dev/null +++ b/tests/basic/GHSA-9pqp-7h25-4f32.inc @@ -0,0 +1,3 @@ + +--FILE-- + '1', + 'CONTENT_TYPE' => "multipart/form-data; boundary=$boundary", + 'CONTENT_LENGTH' => strlen($body), + 'REQUEST_METHOD' => 'POST', + 'SCRIPT_FILENAME' => __DIR__ . '/GHSA-9pqp-7h25-4f32.inc', + ]); + + $spec = [ + 0 => ['pipe', 'r'], + 1 => STDOUT, + 2 => STDOUT, + ]; + + $pipes = []; + + print "Starting...\n"; + + $handle = proc_open($cmd, $spec, $pipes, getcwd(), $env); + + fwrite($pipes[0], $body); + + $status = proc_close($handle); + + print "\n"; +} + +for ($offset = -1; $offset <= 1; $offset++) { + test(FILLUNIT - strlen("\r\n--") + $offset); +} + +?> +--EXPECTF-- +Boundary len: 5115 +Starting... +X-Powered-By: %s +Content-type: text/html; charset=UTF-8 + +Hello world +array(1) { + ["koko"]=> + string(5124) "BBB +--AAA%sCCC" +} + +Boundary len: 5116 +Starting... +X-Powered-By: %s +Content-type: text/html; charset=UTF-8 + +Hello world +array(1) { + ["koko"]=> + string(5125) "BBB +--AAA%sCCC" +} + +Boundary len: 5117 +Starting... +X-Powered-By: %s +Content-type: text/html; charset=UTF-8 + +
+Warning: Boundary too large in multipart/form-data POST data in Unknown on line 0
+Hello world +array(0) { +} + From 4b9cd27ff5c0177dcb160caeae1ea79e761ada58 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 14 Jun 2024 19:49:22 +0200 Subject: [PATCH 28/94] Fix GHSA-p99j-rfp4-xqvq It's no use trying to work around whatever the operating system and Apache do because we'll be fighting that until eternity. Change the skip_getopt condition such that when we're running in CGI or FastCGI mode we always skip the argument parsing. This is a BC break, but this seems to be the only way to get rid of this class of issues. --- sapi/cgi/cgi_main.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index 2c1fa9332dfbb..fba0563aa180e 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -1748,7 +1748,6 @@ int main(int argc, char *argv[]) int status = 0; #endif char *query_string; - char *decoded_query_string; int skip_getopt = 0; #if defined(SIGPIPE) && defined(SIG_IGN) @@ -1803,10 +1802,15 @@ int main(int argc, char *argv[]) * the executable. Ideally we skip argument parsing when we're in cgi or fastcgi mode, * but that breaks PHP scripts on Linux with a hashbang: `#!/php-cgi -d option=value`. * Therefore, this code only prevents passing arguments if the query string starts with a '-'. - * Similarly, scripts spawned in subprocesses on Windows may have the same issue. */ + * Similarly, scripts spawned in subprocesses on Windows may have the same issue. + * However, Windows has lots of conversion rules and command line parsing rules that + * are too difficult and dangerous to reliably emulate. */ if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) { +#ifdef PHP_WIN32 + skip_getopt = cgi || fastcgi; +#else unsigned char *p; - decoded_query_string = strdup(query_string); + char *decoded_query_string = strdup(query_string); php_url_decode(decoded_query_string, strlen(decoded_query_string)); for (p = (unsigned char *)decoded_query_string; *p && *p <= ' '; p++) { /* skip all leading spaces */ @@ -1815,22 +1819,8 @@ int main(int argc, char *argv[]) skip_getopt = 1; } - /* On Windows we have to take into account the "best fit" mapping behaviour. */ -#ifdef PHP_WIN32 - if (*p >= 0x80) { - wchar_t wide_buf[1]; - wide_buf[0] = *p; - char char_buf[4]; - size_t wide_buf_len = sizeof(wide_buf) / sizeof(wide_buf[0]); - size_t char_buf_len = sizeof(char_buf) / sizeof(char_buf[0]); - if (WideCharToMultiByte(CP_ACP, 0, wide_buf, wide_buf_len, char_buf, char_buf_len, NULL, NULL) == 0 - || char_buf[0] == '-') { - skip_getopt = 1; - } - } -#endif - free(decoded_query_string); +#endif } while (!skip_getopt && (c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { From c1c14c8a0f1067baac1b22474df19266afe21a4d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 18 Jun 2024 21:28:26 +0200 Subject: [PATCH 29/94] Fix GHSA-94p6-54jq-9mwp Apache only generates REDIRECT_STATUS, so explicitly check for that if the server name is Apache, don't allow other variable names. Furthermore, redirect.so and Netscape no longer exist, so remove those entries as we can't check their server name anymore. We now also check for the configuration override *first* such that it always take precedence. This would allow for a mitigation path if something like this happens in the future. --- sapi/cgi/cgi_main.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index fba0563aa180e..c7bb7ccabf95d 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -1910,18 +1910,17 @@ int main(int argc, char *argv[]) /* check force_cgi after startup, so we have proper output */ if (cgi && CGIG(force_redirect)) { - /* Apache will generate REDIRECT_STATUS, - * Netscape and redirect.so will generate HTTP_REDIRECT_STATUS. - * redirect.so and installation instructions available from - * http://www.koehntopp.de/php. - * -- kk@netuse.de - */ - if (!getenv("REDIRECT_STATUS") && - !getenv ("HTTP_REDIRECT_STATUS") && - /* this is to allow a different env var to be configured - * in case some server does something different than above */ - (!CGIG(redirect_status_env) || !getenv(CGIG(redirect_status_env))) - ) { + /* This is to allow a different environment variable to be configured + * in case the we cannot auto-detect which environment variable to use. + * Checking this first to allow user overrides in case the environment + * variable can be set by an untrusted party. */ + const char *redirect_status_env = CGIG(redirect_status_env); + if (!redirect_status_env) { + /* Apache will generate REDIRECT_STATUS. */ + redirect_status_env = "REDIRECT_STATUS"; + } + + if (!getenv(redirect_status_env)) { zend_try { SG(sapi_headers).http_response_code = 400; PUTS("Security Alert! The PHP CGI cannot be accessed directly.\n\n\ From 4580b8b3e1495df45a894ab928b23067159eedb8 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 12 Sep 2024 13:11:11 +0100 Subject: [PATCH 30/94] Fix GHSA-865w-9rf3-2wh5: FPM: Logs from childrens may be altered --- sapi/fpm/fpm/fpm_stdio.c | 2 +- .../log-bwp-msg-flush-split-sep-pos-end.phpt | 47 +++++++++++++++++++ ...log-bwp-msg-flush-split-sep-pos-start.phpt | 47 +++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 sapi/fpm/tests/log-bwp-msg-flush-split-sep-pos-end.phpt create mode 100644 sapi/fpm/tests/log-bwp-msg-flush-split-sep-pos-start.phpt diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c index 8f71e8cbfcd08..dec540d17aca8 100644 --- a/sapi/fpm/fpm/fpm_stdio.c +++ b/sapi/fpm/fpm/fpm_stdio.c @@ -229,7 +229,7 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg) if ((sizeof(FPM_STDIO_CMD_FLUSH) - cmd_pos) <= in_buf && !memcmp(buf, &FPM_STDIO_CMD_FLUSH[cmd_pos], sizeof(FPM_STDIO_CMD_FLUSH) - cmd_pos)) { zlog_stream_finish(log_stream); - start = cmd_pos; + start = sizeof(FPM_STDIO_CMD_FLUSH) - cmd_pos; } else { zlog_stream_str(log_stream, &FPM_STDIO_CMD_FLUSH[0], cmd_pos); } diff --git a/sapi/fpm/tests/log-bwp-msg-flush-split-sep-pos-end.phpt b/sapi/fpm/tests/log-bwp-msg-flush-split-sep-pos-end.phpt new file mode 100644 index 0000000000000..528263200803e --- /dev/null +++ b/sapi/fpm/tests/log-bwp-msg-flush-split-sep-pos-end.phpt @@ -0,0 +1,47 @@ +--TEST-- +FPM: Buffered worker output plain log with msg with flush split position towards separator end +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->request()->expectEmptyBody(); +$tester->expectLogLine(str_repeat('a', 1013) . "Quarkslab", decorated: false); +$tester->expectLogLine("Quarkslab", decorated: false); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/log-bwp-msg-flush-split-sep-pos-start.phpt b/sapi/fpm/tests/log-bwp-msg-flush-split-sep-pos-start.phpt new file mode 100644 index 0000000000000..3490593855328 --- /dev/null +++ b/sapi/fpm/tests/log-bwp-msg-flush-split-sep-pos-start.phpt @@ -0,0 +1,47 @@ +--TEST-- +FPM: Buffered worker output plain log with msg with flush split position towards separator start +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$tester->request()->expectEmptyBody(); +$tester->expectLogLine(str_repeat('a', 1009) . "Quarkslab", decorated: false); +$tester->expectLogLine("Quarkslab", decorated: false); +$tester->terminate(); +$tester->expectLogTerminatingNotices(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + From 8d87bc3e266d4848f74dd4b2b7ee5fe4d666bab7 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 23 Sep 2024 12:09:57 +0100 Subject: [PATCH 31/94] Update NEWS with security fixes info --- NEWS | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 3bc2c282ec0a3..1cd4bdd779df6 100644 --- a/NEWS +++ b/NEWS @@ -1,8 +1,21 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.30 +26 Sep 2024, PHP 8.1.30 +- CGI: + . Fixed bug GHSA-p99j-rfp4-xqvq (Bypass of CVE-2024-4577, Parameter Injection + Vulnerability). (CVE-2024-8926) (nielsdos) + . Fixed bug GHSA-94p6-54jq-9mwp (cgi.force_redirect configuration is + byppassible due to the environment variable collision). (CVE-2024-8927) + (nielsdos) +- FPM: + . Fixed bug GHSA-865w-9rf3-2wh5 (Logs from childrens may be altered). + (CVE-2024-9026) (Jakub Zelenka) + +- SAPI: + . Fixed bug GHSA-9pqp-7h25-4f32 (Erroneous parsing of multipart form data). + (CVE-2024-8925) (Arnaud) 06 Jun 2024, PHP 8.1.29 From fc06e0c0d8464219471b722b18a9a5bb7e5c3031 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 23 Sep 2024 12:48:35 +0200 Subject: [PATCH 32/94] Mark failing curl test on macOS x64 as xfail Exactly these tests are failing on all our macOS x64 CI runners for about a week. For now we mark them as xfail, to get back to a green CI pipeline. Closes GH-16002. --- ext/curl/tests/bug48203_multi.phpt | 6 ++++++ ext/curl/tests/bug71523.phpt | 6 ++++++ ext/curl/tests/curl_basic_018.phpt | 6 ++++++ ext/curl/tests/curl_multi_getcontent_basic3.phpt | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/ext/curl/tests/bug48203_multi.phpt b/ext/curl/tests/bug48203_multi.phpt index 19077147a611e..ed58f8540d9ef 100644 --- a/ext/curl/tests/bug48203_multi.phpt +++ b/ext/curl/tests/bug48203_multi.phpt @@ -2,6 +2,12 @@ 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-- --FILE-- Date: Mon, 23 Sep 2024 14:08:26 +0200 Subject: [PATCH 33/94] Adapt labeler.yml to v4 syntax --- .github/labeler.yml | 178 ++++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 90 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 14a6ed9610dab..94dda258ef557 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -243,93 +243,91 @@ - sapi/phpdbg/**/* "ABI break": - - changed-files: - - any-glob-to-any-file: - - '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' \ No newline at end of file +- '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' From dc0987d1540101be8d2ee436c88320f0ae500585 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 23 Sep 2024 17:09:00 +0300 Subject: [PATCH 34/94] Fix GH-15973: Segmentation fault in JIT mode 1135 (#16006) --- ext/opcache/jit/zend_jit_arm64.dasc | 4 +++- ext/opcache/jit/zend_jit_x86.dasc | 4 +++- ext/opcache/tests/jit/gh15973.phpt | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/jit/gh15973.phpt diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 05219b3cfae31..90e27fcf5165c 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -13829,7 +13829,9 @@ static int zend_jit_load_this(dasm_State **Dst, uint32_t var) 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 --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 999295ef01a94..c5622141f564f 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -14749,7 +14749,9 @@ static int zend_jit_load_this(dasm_State **Dst, uint32_t var) 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 --git a/ext/opcache/tests/jit/gh15973.phpt b/ext/opcache/tests/jit/gh15973.phpt new file mode 100644 index 0000000000000..fcf893bccf1b5 --- /dev/null +++ b/ext/opcache/tests/jit/gh15973.phpt @@ -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 From 0bdc4b8c24574cf42dfd0851e6dc8757b914ba9b Mon Sep 17 00:00:00 2001 From: Ayesh Karunaratne Date: Mon, 23 Sep 2024 20:10:37 +0700 Subject: [PATCH 35/94] ext/curl: mark certain tests as xfail on curl 8.10.0 Closes GH-16007. --- ext/curl/tests/bug48203_multi.phpt | 5 +++-- ext/curl/tests/bug71523.phpt | 5 +++-- ext/curl/tests/curl_basic_018.phpt | 5 +++-- ext/curl/tests/curl_multi_getcontent_basic3.phpt | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ext/curl/tests/bug48203_multi.phpt b/ext/curl/tests/bug48203_multi.phpt index ed58f8540d9ef..ec9748517ab85 100644 --- a/ext/curl/tests/bug48203_multi.phpt +++ b/ext/curl/tests/bug48203_multi.phpt @@ -4,8 +4,9 @@ Variation of bug #48203 with curl_multi_exec (Crash when file pointers passed to curl --SKIPIF-- --FILE-- diff --git a/ext/curl/tests/bug71523.phpt b/ext/curl/tests/bug71523.phpt index fa32ecdccd596..2cf2477409dae 100644 --- a/ext/curl/tests/bug71523.phpt +++ b/ext/curl/tests/bug71523.phpt @@ -4,8 +4,9 @@ Bug #71523 (Copied handle with new option CURLOPT_HTTPHEADER crashes while curl_ curl --SKIPIF-- --FILE-- diff --git a/ext/curl/tests/curl_basic_018.phpt b/ext/curl/tests/curl_basic_018.phpt index 72778c82e9ad2..1c907a05fb092 100644 --- a/ext/curl/tests/curl_basic_018.phpt +++ b/ext/curl/tests/curl_basic_018.phpt @@ -6,8 +6,9 @@ TestFest 2009 - AFUP - Thomas Rabaix curl --SKIPIF-- --FILE-- diff --git a/ext/curl/tests/curl_multi_getcontent_basic3.phpt b/ext/curl/tests/curl_multi_getcontent_basic3.phpt index 558440bfe20e5..79002a56430d2 100644 --- a/ext/curl/tests/curl_multi_getcontent_basic3.phpt +++ b/ext/curl/tests/curl_multi_getcontent_basic3.phpt @@ -7,8 +7,9 @@ Rein Velt (rein@velt.org) curl --SKIPIF-- --FILE-- From 4bcc7d5778e70858b4c54c07d21f40ffb09979e2 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 23 Sep 2024 18:54:31 +0100 Subject: [PATCH 36/94] Skip GHSA-9pqp-7h25-4f32 test on Windows --- tests/basic/GHSA-9pqp-7h25-4f32.phpt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/basic/GHSA-9pqp-7h25-4f32.phpt b/tests/basic/GHSA-9pqp-7h25-4f32.phpt index af81916370500..29bcb6557d5a2 100644 --- a/tests/basic/GHSA-9pqp-7h25-4f32.phpt +++ b/tests/basic/GHSA-9pqp-7h25-4f32.phpt @@ -5,6 +5,9 @@ GHSA-9pqp-7h25-4f32 if (!getenv('TEST_PHP_CGI_EXECUTABLE')) { die("skip php-cgi not available"); } +if (substr(PHP_OS, 0, 3) == 'WIN') { + die("skip not for Windows in CI - probably resource issue"); +} ?> --FILE-- Date: Mon, 23 Sep 2024 20:50:51 +0100 Subject: [PATCH 37/94] [skip ci] Fix typo in NEWS Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com> --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 1cd4bdd779df6..e3e7a5613be3a 100644 --- a/NEWS +++ b/NEWS @@ -6,7 +6,7 @@ PHP NEWS . Fixed bug GHSA-p99j-rfp4-xqvq (Bypass of CVE-2024-4577, Parameter Injection Vulnerability). (CVE-2024-8926) (nielsdos) . Fixed bug GHSA-94p6-54jq-9mwp (cgi.force_redirect configuration is - byppassible due to the environment variable collision). (CVE-2024-8927) + bypassable due to the environment variable collision). (CVE-2024-8927) (nielsdos) - FPM: From 81916758ec68c8b9a55fe9a7f1f22398198ca17b Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 23 Sep 2024 12:21:33 +0200 Subject: [PATCH 38/94] Fix GH-15980: Signed integer overflow in main/streams/streams.c We need to avoid signed integer overflows which are undefined behavior. We catch that, and set `offset` to `ZEND_LONG_MAX` (which is also the largest value of `zend_off_t` on all platforms). Of course, that seek may fail, but even if it succeeds, the stream is no longer readable, but that matches the current behavior for offsets near `ZEND_LONG_MAX`. Closes GH-15989. --- NEWS | 2 ++ ext/standard/tests/streams/gh15980.phpt | 12 ++++++++++++ main/streams/streams.c | 9 +++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 ext/standard/tests/streams/gh15980.phpt diff --git a/NEWS b/NEWS index f8e6f5ee82fa1..f127cce068f96 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,8 @@ PHP NEWS - 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) diff --git a/ext/standard/tests/streams/gh15980.phpt b/ext/standard/tests/streams/gh15980.phpt new file mode 100644 index 0000000000000..7a9d8364a90ae --- /dev/null +++ b/ext/standard/tests/streams/gh15980.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-15980 (Signed integer overflow in main/streams/streams.c) +--FILE-- + 1); +?> +--EXPECT-- +bool(true) diff --git a/main/streams/streams.c b/main/streams/streams.c index e22d9e51d594a..4c66d8aadc39b 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1354,8 +1354,13 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence) 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); From 50d5e96edb1df3f039cab611912a91081c151032 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 25 Sep 2024 00:25:01 +0200 Subject: [PATCH 39/94] Fix nightly for 8.2 Backport of af721c9c361643df13a8137d22de9acde82512e5 --- .github/actions/setup-mssql/action.yml | 2 +- .github/actions/setup-x64/action.yml | 9 +----- .github/workflows/nightly.yml | 42 ++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/.github/actions/setup-mssql/action.yml b/.github/actions/setup-mssql/action.yml index c069744a21b59..dd372a5637aac 100644 --- a/.github/actions/setup-mssql/action.yml +++ b/.github/actions/setup-mssql/action.yml @@ -11,4 +11,4 @@ runs: -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 --git a/.github/actions/setup-x64/action.yml b/.github/actions/setup-x64/action.yml index 6cec51d4c8079..9d49107fb3ca6 100644 --- a/.github/actions/setup-x64/action.yml +++ b/.github/actions/setup-x64/action.yml @@ -6,15 +6,8 @@ runs: 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 --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 4822721f2c675..0ebbc2bb1cb61 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -39,6 +39,20 @@ jobs: 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 strategy: fail-fast: false matrix: @@ -255,6 +269,20 @@ jobs: COVERAGE_DEBUG_NTS: if: github.repository_owner == 'php' || github.event_name == 'workflow_dispatch' 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 steps: - name: git checkout uses: actions/checkout@v4 @@ -414,6 +442,20 @@ jobs: OPCACHE_VARIATION: 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 strategy: fail-fast: false matrix: From b7ee484f2b6092ce9836b06de6c8840df05b6d27 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 25 Sep 2024 01:20:29 +0200 Subject: [PATCH 40/94] Add missing CI services for 8.2 --- .github/workflows/push.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 8027bcdc85547..8baa2a1108e16 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -43,6 +43,22 @@ env: 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: From 5feb29ea039e0f140cb4f07b81a0671d543c26f9 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 17 Sep 2024 07:51:34 +0100 Subject: [PATCH 41/94] Fix ubsan build on freebsd regarding float. due to the system header machine/ieeefp.h proceeding to a bitshift operation. close GH-15935 --- Zend/zend_operators.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index e98956239ec3b..ce8b7f5e0a2a7 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -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" From 043b9e1f13c4fd522b92e6a245a08278e14118ee Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 25 Sep 2024 17:36:39 +0200 Subject: [PATCH 42/94] Fix GH-16039: Segmentation fault (access null pointer) in ext/dom/parentnode/tree.c dom_object_get_node() can fail if we don't have a user object associated. Closes GH-16056. --- NEWS | 4 ++++ ext/dom/parentnode.c | 5 +++++ ext/dom/tests/gh16039.phpt | 31 +++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 ext/dom/tests/gh16039.phpt diff --git a/NEWS b/NEWS index f127cce068f96..90c4c40d53a64 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ PHP NEWS . 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) + - PHPDBG: . Fixed bug GH-15901 (phpdbg: Assertion failure on i funcs). (cmb) diff --git a/ext/dom/parentnode.c b/ext/dom/parentnode.c index c30db6fcd745f..ea4edb0774376 100644 --- a/ext/dom/parentnode.c +++ b/ext/dom/parentnode.c @@ -272,6 +272,11 @@ static zend_result dom_sanity_check_node_list_for_insertion(php_libxml_ref_obj * 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 --git a/ext/dom/tests/gh16039.phpt b/ext/dom/tests/gh16039.phpt new file mode 100644 index 0000000000000..48a862eda7b20 --- /dev/null +++ b/ext/dom/tests/gh16039.phpt @@ -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 + + From f4c45ee376c1d76390b4a4a8004672141fe06deb Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 25 Sep 2024 16:52:22 +0100 Subject: [PATCH 43/94] ext/ldap: Fix GH-16032 (Various NULL pointer dereferencements in ldap_modify_batch()) We check that the "attrib" and "modtype" keys are present in each array. If not we throw a ValueError, in line with what other validation failure cases do. Closes GH-16057 --- NEWS | 4 ++++ ext/ldap/ldap.c | 14 ++++++++++++++ ext/ldap/tests/gh16032-1.phpt | 26 ++++++++++++++++++++++++++ ext/ldap/tests/gh16032-2.phpt | 26 ++++++++++++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 ext/ldap/tests/gh16032-1.phpt create mode 100644 ext/ldap/tests/gh16032-2.phpt diff --git a/NEWS b/NEWS index 90c4c40d53a64..d41711a82e074 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,10 @@ PHP NEWS . Fixed bug GH-16039 (Segmentation fault (access null pointer) in ext/dom/parentnode/tree.c). (nielsdos) +- LDAP: + . Fixed bug GH-16032 (Various NULL pointer dereferencements in + ldap_modify_batch()). (Girgias) + - PHPDBG: . Fixed bug GH-15901 (phpdbg: Assertion failure on i funcs). (cmb) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 51eca3d7cc4de..ae65f0258c24b 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2544,8 +2544,11 @@ PHP_FUNCTION(ldap_modify_batch) /* 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 +2570,7 @@ PHP_FUNCTION(ldap_modify_batch) /* 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 +2582,7 @@ PHP_FUNCTION(ldap_modify_batch) } } 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 +2646,15 @@ PHP_FUNCTION(ldap_modify_batch) 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 */ diff --git a/ext/ldap/tests/gh16032-1.phpt b/ext/ldap/tests/gh16032-1.phpt new file mode 100644 index 0000000000000..dbaf8213933d7 --- /dev/null +++ b/ext/ldap/tests/gh16032-1.phpt @@ -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 --git a/ext/ldap/tests/gh16032-2.phpt b/ext/ldap/tests/gh16032-2.phpt new file mode 100644 index 0000000000000..531415807f674 --- /dev/null +++ b/ext/ldap/tests/gh16032-2.phpt @@ -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 From de51612ba593bbecabcb05ba06608a69d2c6f5d3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 25 Sep 2024 20:24:57 +0200 Subject: [PATCH 44/94] Fix bug71610.phpt Apparently example.org now rejects POST requests, so we would need to adjust the test expectation ("Method not allowed"). However, there is no need for an online test; instead we're just using the CLI test server. The serialization is a bit fiddly, but as long as there are no quotes in `PHP_CLI_SERVER_ADDRESS` we're fine. Closes GH-16063. --- ext/soap/tests/bug71610.phpt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ext/soap/tests/bug71610.phpt b/ext/soap/tests/bug71610.phpt index ef0803134fb42..13913cfde7396 100644 --- a/ext/soap/tests/bug71610.phpt +++ b/ext/soap/tests/bug71610.phpt @@ -4,11 +4,20 @@ SOAP Bug #71610 - Type Confusion Vulnerability - SOAP / make_http_soap_request() soap --SKIPIF-- --FILE-- blahblah(); } catch(SoapFault $e) { From 24d5912a3021dbd3110c9d9176dd3995f00cb672 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 26 Sep 2024 15:43:42 +0300 Subject: [PATCH 45/94] Fix possible NULL dereference --- ext/opcache/jit/zend_jit_trace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index e599c335b1b69..4602376b097d3 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -1247,7 +1247,8 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin } } 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 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par 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) || From 87d59d7fddf995410d70672e5a172a8be6479e5f Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 17 Sep 2024 01:16:54 +0200 Subject: [PATCH 46/94] Fix GH-15905: Assertion failure for TRACK_VARS_SERVER When the superglobals are eagerly initialized, but "S" is not contained in `variables_order`, `TRACK_VARS_SERVER` is created as empty array with refcount > 1. Since this hash table may later be modified, a flag is set which allows such COW violations for assertions. However, when `register_argc_argv` is on, the so far uninitialized hash table is updated with `argv`, what causes the hash table to be initialized, what drops the allow-COW-violations flag. The following update with `argc` then triggers a refcount violation assertion. Since we consider `HT_ALLOW_COW_VIOLATION` a hack, we do not want to keep the flag during hash table initialization, so we initialize the hash table right away after creation for this code path. Closes GH-15930. --- NEWS | 1 + main/php_variables.c | 1 + tests/basic/gh15905.phpt | 12 ++++++++++++ 3 files changed, 14 insertions(+) create mode 100644 tests/basic/gh15905.phpt diff --git a/NEWS b/NEWS index d41711a82e074..533617e799524 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ PHP NEWS - 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) - Date: . Fixed bug GH-15582: Crash when not calling parent constructor of diff --git a/main/php_variables.c b/main/php_variables.c index eb442c3d2f99f..bac5b1b673b61 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -897,6 +897,7 @@ static bool php_auto_globals_create_server(zend_string *name) } 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 --git a/tests/basic/gh15905.phpt b/tests/basic/gh15905.phpt new file mode 100644 index 0000000000000..6636b97024276 --- /dev/null +++ b/tests/basic/gh15905.phpt @@ -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 From fcbcf2f2810e3e72abd3b36a6401e3e9268d52ce Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Thu, 26 Sep 2024 12:52:41 -0500 Subject: [PATCH 47/94] PHP-8.1 is now for PHP 8.1.31-dev --- NEWS | 4 ++++ Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index e3e7a5613be3a..b9130ae18db2a 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +?? ??? ????, PHP 8.1.31 + + + 26 Sep 2024, PHP 8.1.30 - CGI: diff --git a/Zend/zend.h b/Zend/zend.h index 56ce93f685da9..dcf69979f952c 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.30-dev" +#define ZEND_VERSION "4.1.31-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 2c21f30ff2611..f6902707abb15 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.30-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.31-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 3327cdc332e04..bff6722583474 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 -#define PHP_RELEASE_VERSION 30 +#define PHP_RELEASE_VERSION 31 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.30-dev" -#define PHP_VERSION_ID 80130 +#define PHP_VERSION "8.1.31-dev" +#define PHP_VERSION_ID 80131 From 15a0c3a9d4cbe9e3b54002bae9383475bc722376 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 19 Sep 2024 00:44:44 +0200 Subject: [PATCH 48/94] Fix failed assertion when promoting Serialize deprecation to exception Fixes GH-15907 Closes GH-15951 --- NEWS | 2 ++ Zend/tests/gh15907.phpt | 18 ++++++++++++++++++ Zend/zend_interfaces.c | 4 ++++ 3 files changed, 24 insertions(+) create mode 100644 Zend/tests/gh15907.phpt diff --git a/NEWS b/NEWS index 172705ecb61fe..b09b1ea44bd28 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ PHP NEWS . 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) - Date: . Fixed bug GH-15582: Crash when not calling parent constructor of diff --git a/Zend/tests/gh15907.phpt b/Zend/tests/gh15907.phpt new file mode 100644 index 0000000000000..8d6dada36ad08 --- /dev/null +++ b/Zend/tests/gh15907.phpt @@ -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 --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index b8cc5e94caca8..39d647c7e29f3 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -473,6 +473,10 @@ static int zend_implement_serializable(zend_class_entry *interface, zend_class_e 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; } From c4c45da4b96889348d86828c26225d113af14d21 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 27 Sep 2024 15:01:23 +0200 Subject: [PATCH 49/94] Reduce regex backtracking in phpinfo.phpt On NixOS, the output of phpinfo() can get very large, causing us to run into the backtracking limit. Lazy matching for .*/.+ can help reduce backtracking. --- .../tests/general_functions/phpinfo.phpt | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ext/standard/tests/general_functions/phpinfo.phpt b/ext/standard/tests/general_functions/phpinfo.phpt index 57ba13bb7bf7c..a8c4f392a38f8 100644 --- a/ext/standard/tests/general_functions/phpinfo.phpt +++ b/ext/standard/tests/general_functions/phpinfo.phpt @@ -16,21 +16,21 @@ phpinfo() 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 PHP Streams => %s 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 @@ bool(true) phpinfo() PHP License -%a +%r(.+?)%r bool(true) From 706bcdbc1abd8b8d7668d9a9475edb498f0c6bef Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 19 Sep 2024 01:30:37 +0200 Subject: [PATCH 50/94] Fix printing backtrace of fake generator frame Fixes GH-15851 Closes GH-15952 --- NEWS | 2 ++ Zend/tests/generators/gh15851.phpt | 27 +++++++++++++++++++++++++++ Zend/zend_builtin_functions.c | 10 ++++++++++ sapi/cli/php_cli.c | 1 + 4 files changed, 40 insertions(+) create mode 100644 Zend/tests/generators/gh15851.phpt diff --git a/NEWS b/NEWS index b09b1ea44bd28..6279ae30feac5 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ PHP NEWS . 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) - Date: . Fixed bug GH-15582: Crash when not calling parent constructor of diff --git a/Zend/tests/generators/gh15851.phpt b/Zend/tests/generators/gh15851.phpt new file mode 100644 index 0000000000000..8a7fa6294e255 --- /dev/null +++ b/Zend/tests/generators/gh15851.phpt @@ -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 --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 72cb07decbd38..898318102c1df 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1725,6 +1725,16 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int } 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 --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index ff525438ebc03..34046466ae7ea 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -1075,6 +1075,7 @@ static int do_cli(int argc, char **argv) /* {{{ */ 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); From 5f3e6e346c574bdcd564119e19828ff3204e3ee5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 27 Sep 2024 19:08:13 +0200 Subject: [PATCH 51/94] Fix failing soap tests on Windows These failures are caused by the fix for GHSA-p99j-rfp4-xqvq. Since the two bug*.phpt tests don't need the "wsdl" query string, and don't even need php-cgi, we just remove the `--GET--` section. The two server*.phpt tests are harder to fix, since during evaluation of the `--SKIPIF--` section, the soap extension can be loaded, but it may not during evaluation of the `--FILE--` section. So for now, we skip these tests on Windows altogether. Co-authored-by: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Closes GH-16084. --- ext/soap/tests/bugs/bug27722.phpt | 2 -- ext/soap/tests/bugs/bug27742.phpt | 2 -- ext/soap/tests/server011.phpt | 6 ++++++ ext/soap/tests/server012.phpt | 6 ++++++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ext/soap/tests/bugs/bug27722.phpt b/ext/soap/tests/bugs/bug27722.phpt index 3315b71401840..1bfc2fe6ee3b4 100644 --- a/ext/soap/tests/bugs/bug27722.phpt +++ b/ext/soap/tests/bugs/bug27722.phpt @@ -2,8 +2,6 @@ Bug #27722 (Segfault on schema without targetNamespace) --EXTENSIONS-- soap ---GET-- -wsdl --INI-- soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/bugs/bug27742.phpt b/ext/soap/tests/bugs/bug27742.phpt index 02b27dc0144ec..1c7c8fc09f7e4 100644 --- a/ext/soap/tests/bugs/bug27742.phpt +++ b/ext/soap/tests/bugs/bug27742.phpt @@ -2,8 +2,6 @@ Bug #27742 (WDSL SOAP Parsing Schema bug) --EXTENSIONS-- soap ---GET-- -wsdl --INI-- soap.wsdl_cache_enabled=0 --FILE-- diff --git a/ext/soap/tests/server011.phpt b/ext/soap/tests/server011.phpt index ad4a626c79016..f236ec3affc59 100644 --- a/ext/soap/tests/server011.phpt +++ b/ext/soap/tests/server011.phpt @@ -1,5 +1,11 @@ --TEST-- SOAP Server 11: bind +--SKIPIF-- + --EXTENSIONS-- soap --GET-- diff --git a/ext/soap/tests/server012.phpt b/ext/soap/tests/server012.phpt index 230108e2b9202..703aefbaa7874 100644 --- a/ext/soap/tests/server012.phpt +++ b/ext/soap/tests/server012.phpt @@ -1,5 +1,11 @@ --TEST-- SOAP Server 12: WSDL generation +--SKIPIF-- + --EXTENSIONS-- soap --GET-- From dce0d9764084115eeec18ea0b88f509a9bab7857 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Wed, 25 Sep 2024 12:19:28 +0100 Subject: [PATCH 52/94] Fix stub for openssl_csr_new --- NEWS | 3 +++ ext/openssl/openssl.stub.php | 4 ++-- ext/openssl/openssl_arginfo.h | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 6279ae30feac5..937f987470cb5 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,9 @@ PHP NEWS . Fixed bug GH-16032 (Various NULL pointer dereferencements in ldap_modify_batch()). (Girgias) +- OpenSSL: + . Fixed stub for openssl_csr_new. (Jakub Zelenka) + - PHPDBG: . Fixed bug GH-15901 (phpdbg: Assertion failure on i funcs). (cmb) diff --git a/ext/openssl/openssl.stub.php b/ext/openssl/openssl.stub.php index a9fad2eaeae90..523640c825920 100644 --- a/ext/openssl/openssl.stub.php +++ b/ext/openssl/openssl.stub.php @@ -433,9 +433,9 @@ function openssl_csr_export(OpenSSLCertificateSigningRequest|string $csr, &$outp 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 --git a/ext/openssl/openssl_arginfo.h b/ext/openssl/openssl_arginfo.h index 3e1b4a778a967..bfdf674b07d6a 100644 --- a/ext/openssl/openssl_arginfo.h +++ b/ext/openssl/openssl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 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_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_openssl_csr_sign, 0, 4, Open 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") From 19bba8371548d71a7b9a3c9ce932b978eea99970 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 28 Sep 2024 16:07:22 +0100 Subject: [PATCH 53/94] ext/ldap: Fix GH-16101 (Segfaults in php_ldap_do_search() when LDAPs is not a list) Closes GH-16102 --- NEWS | 2 ++ ext/ldap/ldap.c | 5 +++++ ext/ldap/tests/gh16101.phpt | 25 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 ext/ldap/tests/gh16101.phpt diff --git a/NEWS b/NEWS index 937f987470cb5..594b766a940ee 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,8 @@ PHP NEWS - 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) - OpenSSL: . Fixed stub for openssl_csr_new. (Jakub Zelenka) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index ae65f0258c24b..f0dd3ccb4c47d 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -1429,6 +1429,11 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) 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); diff --git a/ext/ldap/tests/gh16101.phpt b/ext/ldap/tests/gh16101.phpt new file mode 100644 index 0000000000000..1e9d57334378b --- /dev/null +++ b/ext/ldap/tests/gh16101.phpt @@ -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 From f5649556eaae9a23d5f7ad0dc0a361aa1c84a23e Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 28 Sep 2024 20:19:55 +0200 Subject: [PATCH 54/94] Fix potential parallel test conflicts Both tests call `create_files()` with the same `$name_prefix` what might clash. Co-authored-by: Gina Peter Banyard Closes GH-16103. --- ext/standard/tests/file/file_get_contents_basic.phpt | 12 ++++++------ ext/standard/tests/file/file_get_contents_error.phpt | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/standard/tests/file/file_get_contents_basic.phpt b/ext/standard/tests/file/file_get_contents_basic.phpt index 5c060fdae1ba5..e4b8173e7a144 100644 --- a/ext/standard/tests/file/file_get_contents_basic.phpt +++ b/ext/standard/tests/file/file_get_contents_basic.phpt @@ -13,15 +13,15 @@ echo "*** Testing the basic functionality of the file_get_contents() function ** 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 --git a/ext/standard/tests/file/file_get_contents_error.phpt b/ext/standard/tests/file/file_get_contents_error.phpt index 12ddfc73f5787..5ac352123b309 100644 --- a/ext/standard/tests/file/file_get_contents_error.phpt +++ b/ext/standard/tests/file/file_get_contents_error.phpt @@ -13,17 +13,17 @@ include($file_path."/file.inc"); 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"); From 332b067c5ee7d6d406180afc5eca50762fe6fc06 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 17 Sep 2024 19:43:42 +0100 Subject: [PATCH 55/94] Fix GH-15937: stream timeout option overflow. close GH-15942 --- NEWS | 2 ++ ext/standard/tests/streams/gh15937.phpt | 16 ++++++++++++++++ main/php_network.h | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/streams/gh15937.phpt diff --git a/NEWS b/NEWS index 594b766a940ee..81f87a742895d 100644 --- a/NEWS +++ b/NEWS @@ -43,6 +43,8 @@ PHP NEWS - 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) - Streams: . Fixed bugs GH-15908 and GH-15026 (leak / assertion failure in streams.c). diff --git a/ext/standard/tests/streams/gh15937.phpt b/ext/standard/tests/streams/gh15937.phpt new file mode 100644 index 0000000000000..db0564342b13b --- /dev/null +++ b/ext/standard/tests/streams/gh15937.phpt @@ -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 --git a/main/php_network.h b/main/php_network.h index a3b7ba7ab3180..fda61b87cb4c9 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -162,7 +162,7 @@ PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout); /* 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; From c910e78c392e2c56c6a7f0ebcc22023f4d40d620 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 30 Sep 2024 17:36:23 +0100 Subject: [PATCH 56/94] ext/ldap: Fix GH-16132 (Freeing pointer not allocated by ZMM) Closes GH-16134 --- ext/ldap/ldap.c | 4 ++++ ext/ldap/tests/gh16132-1.phpt | 28 ++++++++++++++++++++++++++++ ext/ldap/tests/gh16132-2.phpt | 28 ++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 ext/ldap/tests/gh16132-1.phpt create mode 100644 ext/ldap/tests/gh16132-2.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index f0dd3ccb4c47d..ede60a298468c 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2181,6 +2181,8 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) 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)); @@ -2197,6 +2199,8 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) } convert_to_string(ivalue); if (EG(exception)) { + num_berval[i] = j; + num_attribs = i + 1; RETVAL_FALSE; goto cleanup; } diff --git a/ext/ldap/tests/gh16132-1.phpt b/ext/ldap/tests/gh16132-1.phpt new file mode 100644 index 0000000000000..1979796446daa --- /dev/null +++ b/ext/ldap/tests/gh16132-1.phpt @@ -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 --git a/ext/ldap/tests/gh16132-2.phpt b/ext/ldap/tests/gh16132-2.phpt new file mode 100644 index 0000000000000..eaf3bd67dfcb3 --- /dev/null +++ b/ext/ldap/tests/gh16132-2.phpt @@ -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 From 21260318c6fef56c0227768b94b14f3727bce333 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 30 Sep 2024 17:58:22 +0100 Subject: [PATCH 57/94] ext/ldap: Fix GH-16136 (Memory leak in php_ldap_do_modify()) --- ext/ldap/ldap.c | 16 +++++----------- ext/ldap/tests/gh16136.phpt | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 ext/ldap/tests/gh16136.phpt diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index ede60a298468c..e33201f10d154 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2150,17 +2150,11 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) 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)); diff --git a/ext/ldap/tests/gh16136.phpt b/ext/ldap/tests/gh16136.phpt new file mode 100644 index 0000000000000..14f21e3e757f2 --- /dev/null +++ b/ext/ldap/tests/gh16136.phpt @@ -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) From f8b925b61721e171ff558a6635da9f4167a0f884 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 30 Sep 2024 22:23:27 +0100 Subject: [PATCH 58/94] NEWS entries for LDAP bug fixes --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 81f87a742895d..0acebdf586585 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,10 @@ PHP NEWS 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) - OpenSSL: . Fixed stub for openssl_csr_new. (Jakub Zelenka) From 066d18f2e8ff01371ed8afb3e00b92a08ff39bd1 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 1 Oct 2024 20:50:56 +0200 Subject: [PATCH 59/94] Fix GH-16151: Assertion failure in ext/dom/parentnode/tree.c Unfortunately, old DOM allows attributes to be used as parent nodes. Only text nodes and entities are allowed as children for these types of nodes, because that's the constraint DOM and libxml give us. Closes GH-16156. --- NEWS | 2 ++ ext/dom/node.c | 73 ++++++++++++++++++-------------------- ext/dom/tests/gh16151.phpt | 35 ++++++++++++++++++ 3 files changed, 72 insertions(+), 38 deletions(-) create mode 100644 ext/dom/tests/gh16151.phpt diff --git a/NEWS b/NEWS index 0acebdf586585..13e5f49ae7cd8 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,8 @@ PHP NEWS - 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) - LDAP: . Fixed bug GH-16032 (Various NULL pointer dereferencements in diff --git a/ext/dom/node.c b/ext/dom/node.c index c80f9c3333c6c..bb80408f2689f 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -843,6 +843,39 @@ static xmlNodePtr _php_dom_insert_fragment(xmlNodePtr nodep, xmlNodePtr prevsib, } /* }}} */ +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; + } + + return true; +} + /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-952280727 Since: */ @@ -870,25 +903,7 @@ PHP_METHOD(DOMNode, insertBefore) 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); - 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"); + if (!dom_node_check_legacy_insertion_validity(parentp, child, stricterror)) { RETURN_FALSE; } @@ -1170,25 +1185,7 @@ PHP_METHOD(DOMNode, appendChild) 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 --git a/ext/dom/tests/gh16151.phpt b/ext/dom/tests/gh16151.phpt new file mode 100644 index 0000000000000..e11d3df4a56bb --- /dev/null +++ b/ext/dom/tests/gh16151.phpt @@ -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 From 6e55f4df23956aaff8ff0d5296994357594d6357 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 2 Oct 2024 12:29:19 +0200 Subject: [PATCH 60/94] Fix assertion failure in generator dtor (#16025) --- Zend/tests/gh15866.phpt | 53 +++++++++++++++++++++++++++++++++++++++++ Zend/zend_generators.c | 25 +++++-------------- Zend/zend_generators.h | 1 - 3 files changed, 59 insertions(+), 20 deletions(-) create mode 100644 Zend/tests/gh15866.phpt diff --git a/Zend/tests/gh15866.phpt b/Zend/tests/gh15866.phpt new file mode 100644 index 0000000000000..99a3a6e6a9524 --- /dev/null +++ b/Zend/tests/gh15866.phpt @@ -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 --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 4ac45949bd34a..9089d821f3016 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -218,43 +218,30 @@ static zend_always_inline void clear_link_to_root(zend_generator *generator) { } } -/* 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 --git a/Zend/zend_generators.h b/Zend/zend_generators.h index a41fb7699d842..00d38a9d28d3f 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -93,7 +93,6 @@ static const zend_uchar ZEND_GENERATOR_FORCED_CLOSE = 0x2; 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); From 36945ecb711b428945ceb55743f58d4b5338d9d7 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 2 Oct 2024 12:30:27 +0200 Subject: [PATCH 61/94] [ci skip] NEWS for GH-16025 --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 13e5f49ae7cd8..7ef01952a6e59 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,7 @@ PHP NEWS 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) - Date: . Fixed bug GH-15582: Crash when not calling parent constructor of From 545bef8ae6d31302b14614570e0eed91dbc8635e Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 2 Oct 2024 12:37:04 +0200 Subject: [PATCH 62/94] Fix array_merge_recursive(): convert_to_array() may need separation (#16061) --- ext/standard/array.c | 3 ++- ext/standard/tests/array/gh16053.phpt | 28 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/array/gh16053.phpt diff --git a/ext/standard/array.c b/ext/standard/array.c index 4d1dca5002c1d..6c1975b121749 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -3700,7 +3700,6 @@ PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */ } 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 @@ PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */ } 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 --git a/ext/standard/tests/array/gh16053.phpt b/ext/standard/tests/array/gh16053.phpt new file mode 100644 index 0000000000000..7106fb989abae --- /dev/null +++ b/ext/standard/tests/array/gh16053.phpt @@ -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" + } +} From 2bcf3f9e23a8eab865186c0d9572df60f9be69c4 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 2 Oct 2024 12:38:24 +0200 Subject: [PATCH 63/94] [ci skip] NEWS for GH-16061 --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 7ef01952a6e59..c7457b839e8b4 100644 --- a/NEWS +++ b/NEWS @@ -52,6 +52,7 @@ PHP NEWS (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). From f14e5cfaaa0c56fe38d8f8cce72cfdcaa5bd7dba Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 3 Oct 2024 00:44:16 +0200 Subject: [PATCH 64/94] Fix GH-16181: phpdbg: exit in exception handler reports fatal error When running PHP code, we must not handle `UnwindExit` exceptions, but rather have to ignore them. Closes GH-16182. --- NEWS | 2 ++ sapi/phpdbg/phpdbg_prompt.c | 2 +- sapi/phpdbg/tests/gh16181.phpt | 26 ++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 sapi/phpdbg/tests/gh16181.phpt diff --git a/NEWS b/NEWS index c7457b839e8b4..f2c17a4536513 100644 --- a/NEWS +++ b/NEWS @@ -39,6 +39,8 @@ PHP NEWS - 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) - SimpleXML: . Fixed bug GH-15837 (Segmentation fault in ext/simplexml/simplexml.c). diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 887064cf2e70b..448194f13d261 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -907,7 +907,7 @@ PHPDBG_COMMAND(run) /* {{{ */ } } zend_end_try(); - if (EG(exception)) { + if (EG(exception) && !zend_is_unwind_exit(EG(exception))) { phpdbg_handle_exception(); } } diff --git a/sapi/phpdbg/tests/gh16181.phpt b/sapi/phpdbg/tests/gh16181.phpt new file mode 100644 index 0000000000000..478bbb98ca0d9 --- /dev/null +++ b/sapi/phpdbg/tests/gh16181.phpt @@ -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> From f453d1ae2a032f8e367a0139cd29debdfeb6fc71 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 3 Oct 2024 05:15:42 +0100 Subject: [PATCH 65/94] Fix GH-16189: underflow on preg_match/preg_match_all start_offset. close GH-16191 --- NEWS | 3 +++ ext/pcre/php_pcre.c | 5 +++++ ext/pcre/tests/gh16189.phpt | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 ext/pcre/tests/gh16189.phpt diff --git a/NEWS b/NEWS index f2c17a4536513..1fa196547d7c5 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,9 @@ PHP NEWS - OpenSSL: . Fixed stub for openssl_csr_new. (Jakub Zelenka) +- PCRE: + . Fixed GH-16189 (underflow on offset argument). (David Carlier) + - PHPDBG: . Fixed bug GH-15901 (phpdbg: Assertion failure on i funcs). (cmb) . Fixed bug GH-16181 (phpdbg: exit in exception handler reports fatal error). diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index ea5e6a01ff065..4511d611d7a44 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -1135,6 +1135,11 @@ static void php_do_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) /* {{{ * 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); diff --git a/ext/pcre/tests/gh16189.phpt b/ext/pcre/tests/gh16189.phpt new file mode 100644 index 0000000000000..c77ab7699eed1 --- /dev/null +++ b/ext/pcre/tests/gh16189.phpt @@ -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 From c4bb07552e642f8e3b3a766935e94934ab136310 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 3 Oct 2024 20:16:01 +0200 Subject: [PATCH 66/94] Fix GH-16184: UBSan address overflowed in ext/pcre/php_pcre.c libpcre2 can return the special value -1 for a non-match. In this case we get pointer overflow, although it doesn't matter in practice because the pointer will be in bounds and the copy length will be 0. Still, we should fix the UBSAN warning. Closes GH-16205. --- NEWS | 4 +++- ext/pcre/php_pcre.c | 8 +++++--- ext/pcre/tests/gh16184.phpt | 13 +++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 ext/pcre/tests/gh16184.phpt diff --git a/NEWS b/NEWS index 1fa196547d7c5..19b6642ca1a2a 100644 --- a/NEWS +++ b/NEWS @@ -38,7 +38,9 @@ PHP NEWS . Fixed stub for openssl_csr_new. (Jakub Zelenka) - PCRE: - . Fixed GH-16189 (underflow on offset argument). (David Carlier) + . 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) diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 4511d611d7a44..4c1d8db47c11b 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -1747,9 +1747,11 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su } 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 --git a/ext/pcre/tests/gh16184.phpt b/ext/pcre/tests/gh16184.phpt new file mode 100644 index 0000000000000..ba915d19af74b --- /dev/null +++ b/ext/pcre/tests/gh16184.phpt @@ -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* From 3d80d98a1071e8007ae9f5b6840019c403f15437 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 1 Oct 2024 18:28:24 +0100 Subject: [PATCH 67/94] Fix GH-16137: "Deduplicate" http headers values but Set-Cookie. Those are meant to have 1 or plus values separated by a comma even if the client set them separately. close GH-16154 --- NEWS | 4 ++++ sapi/cli/php_cli_server.c | 27 +++++++++++++++++++++++---- sapi/cli/tests/gh16137.phpt | 20 ++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 sapi/cli/tests/gh16137.phpt diff --git a/NEWS b/NEWS index 19b6642ca1a2a..de78eabdadb08 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.25 +- 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) diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 379ee70974d8e..732ac27c9a207 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -1680,14 +1680,33 @@ static void php_cli_server_client_save_header(php_cli_server_client *client) { /* 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); diff --git a/sapi/cli/tests/gh16137.phpt b/sapi/cli/tests/gh16137.phpt new file mode 100644 index 0000000000000..165b8b1afd300 --- /dev/null +++ b/sapi/cli/tests/gh16137.phpt @@ -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" From 331da7e8693ffb028c6678b5182f3436444d1c3b Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Wed, 2 Oct 2024 22:35:53 -0700 Subject: [PATCH 68/94] Fix GH-16187: ReflectionClass::__toString() with packed properties hash table Closes GH-16192. --- NEWS | 4 ++++ ext/reflection/php_reflection.c | 2 +- ext/reflection/tests/gh16187.phpt | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 ext/reflection/tests/gh16187.phpt diff --git a/NEWS b/NEWS index de78eabdadb08..d492c9761842e 100644 --- a/NEWS +++ b/NEWS @@ -51,6 +51,10 @@ PHP NEWS . 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) + - SimpleXML: . Fixed bug GH-15837 (Segmentation fault in ext/simplexml/simplexml.c). (nielsdos) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index f24b00a2857f9..3faf8ed78681e 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -477,7 +477,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char 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++; diff --git a/ext/reflection/tests/gh16187.phpt b/ext/reflection/tests/gh16187.phpt new file mode 100644 index 0000000000000..64aec52de93ba --- /dev/null +++ b/ext/reflection/tests/gh16187.phpt @@ -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 From d840200cea34e4fa04371694a17b55c6335aab89 Mon Sep 17 00:00:00 2001 From: Yuya Hamada Date: Sat, 5 Oct 2024 16:59:07 +0900 Subject: [PATCH 69/94] Fix GH-16229: Address overflowed in mb_send_mail when empty string --- ext/mbstring/mbstring.c | 3 ++- ext/mbstring/tests/gh16229.phpt | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 ext/mbstring/tests/gh16229.phpt diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 5aa25b57f01a2..0b362309ca438 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -4179,7 +4179,8 @@ PHP_FUNCTION(mb_send_mail) #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 --git a/ext/mbstring/tests/gh16229.phpt b/ext/mbstring/tests/gh16229.phpt new file mode 100644 index 0000000000000..1fe558d9b1025 --- /dev/null +++ b/ext/mbstring/tests/gh16229.phpt @@ -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-- From f4d2dd038b5f926f98d03c4c974b3c7cb06c8532 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 5 Oct 2024 07:13:40 +0100 Subject: [PATCH 70/94] Fix GH-16231 jdtounix overflow on argument value. Close GH-16240 --- NEWS | 3 +++ ext/calendar/cal_unix.c | 6 +++--- ext/calendar/tests/gh16231.phpt | 21 +++++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 ext/calendar/tests/gh16231.phpt diff --git a/NEWS b/NEWS index d492c9761842e..b005320f61d0d 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.25 +- Calendar: + . Fixed GH-16240: jdtounix overflow on argument value. (David Carlier) + - CLI: . Fixed bug GH-16137: duplicate http headers when set several times by the client. (David Carlier) diff --git a/ext/calendar/cal_unix.c b/ext/calendar/cal_unix.c index 78a08fdef0aa5..c3fe5557d244e 100644 --- a/ext/calendar/cal_unix.c +++ b/ext/calendar/cal_unix.c @@ -60,13 +60,13 @@ PHP_FUNCTION(jdtounix) 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 --git a/ext/calendar/tests/gh16231.phpt b/ext/calendar/tests/gh16231.phpt new file mode 100644 index 0000000000000..89b09dd3f63ae --- /dev/null +++ b/ext/calendar/tests/gh16231.phpt @@ -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 From 54973c9366b3aff148d58d7f3eeb136624fdb267 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 5 Oct 2024 06:27:19 +0100 Subject: [PATCH 71/94] Fix GH-16232: bitshift overflow on wbmp file content reading. backport from https://github.com/libgd/libgd/commit/a8f1d5cab0cad2bca2ed88a49c3f3de8585ff19b close GH-16239 --- NEWS | 4 ++++ ext/gd/libgd/wbmp.c | 3 ++- ext/gd/tests/gh16232.phpt | 27 +++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 ext/gd/tests/gh16232.phpt diff --git a/NEWS b/NEWS index b005320f61d0d..c175cd37371ab 100644 --- a/NEWS +++ b/NEWS @@ -31,6 +31,10 @@ PHP NEWS . Fixed bug GH-16151 (Assertion failure in ext/dom/parentnode/tree.c). (nielsdos) +- GD: + . Fixed bug 16232 (bitshift overflow on wbmp file content reading / + fix backport from upstream). (David Carlier) + - LDAP: . Fixed bug GH-16032 (Various NULL pointer dereferencements in ldap_modify_batch()). (Girgias) diff --git a/ext/gd/libgd/wbmp.c b/ext/gd/libgd/wbmp.c index 4c3eeee7df8cb..dbca0f0178c68 100644 --- a/ext/gd/libgd/wbmp.c +++ b/ext/gd/libgd/wbmp.c @@ -37,7 +37,8 @@ int getmbi (int (*getin) (void *in), void *in) { - int i, mbi = 0; + unsigned int mbi = 0; + int i; do { diff --git a/ext/gd/tests/gh16232.phpt b/ext/gd/tests/gh16232.phpt new file mode 100644 index 0000000000000..7f839d737bb5b --- /dev/null +++ b/ext/gd/tests/gh16232.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-16232 (Overflow on reading wbmp content) +--EXTENSIONS-- +gd +--FILE-- + Date: Sat, 5 Oct 2024 07:43:30 +0100 Subject: [PATCH 72/94] Fix GH-16228 overflow on easter_days/easter_date year argument. close GH-16241 --- NEWS | 2 ++ ext/calendar/easter.c | 6 ++++++ ext/calendar/tests/gh16228.phpt | 26 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 ext/calendar/tests/gh16228.phpt diff --git a/NEWS b/NEWS index c175cd37371ab..cfd3912bbbe89 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,8 @@ PHP NEWS - Calendar: . Fixed GH-16240: jdtounix overflow on argument value. (David Carlier) + . Fixed GH-16241: easter_days/easter_date overflow on year argument. + (David Carlier) - CLI: . Fixed bug GH-16137: duplicate http headers when set several times by diff --git a/ext/calendar/easter.c b/ext/calendar/easter.c index c319abd17fef0..2832d0bdefe00 100644 --- a/ext/calendar/easter.c +++ b/ext/calendar/easter.c @@ -28,6 +28,7 @@ static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm) 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_MAX / 1.25; bool year_is_null = 1; if (zend_parse_parameters(ZEND_NUM_ARGS(), @@ -48,6 +49,11 @@ static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm) } } + 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 --git a/ext/calendar/tests/gh16228.phpt b/ext/calendar/tests/gh16228.phpt new file mode 100644 index 0000000000000..9ce80688195ba --- /dev/null +++ b/ext/calendar/tests/gh16228.phpt @@ -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 From 809a58bc1bc93b7db94a14080dcf3233b013fc0a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 5 Oct 2024 12:40:08 +0200 Subject: [PATCH 73/94] Fix GH-16237: Segmentation fault when cloning SoapServer Bisect points to 94ee4f9, however this only reveals the problem. Cloning an object on a lower branch and trying to call its methods crashes as well. Cloning the object shouldn't be possible in the first place because there's an engine constraint that when we have a new object handler we should also have a clone handler. This constraint is not fulfilled here. Closes GH-16245. --- NEWS | 1 + ext/soap/soap.c | 1 + ext/soap/tests/bugs/gh16237.phpt | 17 +++++++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 ext/soap/tests/bugs/gh16237.phpt diff --git a/NEWS b/NEWS index cfd3912bbbe89..7fcbacc037e03 100644 --- a/NEWS +++ b/NEWS @@ -70,6 +70,7 @@ PHP NEWS - SOAP: . Fixed bug #62900 (Wrong namespace on xsd import error message). (nielsdos) + . Fixed bug GH-16237 (Segmentation fault when cloning SoapServer). (nielsdos) - Standard: . Fixed bug GH-15613 (overflow on unpack call hex string repeater). diff --git a/ext/soap/soap.c b/ext/soap/soap.c index e98820c630eda..924e60deaa40d 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -412,6 +412,7 @@ PHP_MINIT_FUNCTION(soap) 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); diff --git a/ext/soap/tests/bugs/gh16237.phpt b/ext/soap/tests/bugs/gh16237.phpt new file mode 100644 index 0000000000000..468f2794399e8 --- /dev/null +++ b/ext/soap/tests/bugs/gh16237.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-16237 (Segmentation fault when cloning SoapServer) +--EXTENSIONS-- +soap +--FILE-- +"http://testuri.org/"]); +try { + clone $server; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Trying to clone an uncloneable object of class SoapServer From 4b855eba15c06e9ed7a6b1068aa87ea32b54044d Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 3 Oct 2024 18:02:15 +0100 Subject: [PATCH 74/94] [skip ci] Cirrus CI: Skip on doc changes Closes GH-16203 --- .cirrus.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.cirrus.yml b/.cirrus.yml index a5209930b6e44..7d3db43a8a7e2 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,6 +3,7 @@ env: 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: From 6d9903f3e62dcee870582fa60634eec84fe7b643 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 5 Oct 2024 15:46:10 +0100 Subject: [PATCH 75/94] fix build warning for GH-16228 close GH-16250 --- ext/calendar/easter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/calendar/easter.c b/ext/calendar/easter.c index 2832d0bdefe00..00df5dcf1d592 100644 --- a/ext/calendar/easter.c +++ b/ext/calendar/easter.c @@ -28,7 +28,7 @@ static void _cal_easter(INTERNAL_FUNCTION_PARAMETERS, bool gm) 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_MAX / 1.25; + const zend_long max_year = (zend_long)(ZEND_LONG_MAX / 5) * 4; bool year_is_null = 1; if (zend_parse_parameters(ZEND_NUM_ARGS(), From 2d05da2e94882b1715d607f650dbd5524a9386ff Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 6 Oct 2024 06:30:32 +0100 Subject: [PATCH 76/94] Fix GH-16260: overflow/underflow on imagerotate degrees argument. close GH-16264 --- NEWS | 4 +++- ext/gd/gd.c | 5 +++++ ext/gd/tests/gh16260.phpt | 22 ++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 ext/gd/tests/gh16260.phpt diff --git a/NEWS b/NEWS index 7fcbacc037e03..f4ad67f2f0e19 100644 --- a/NEWS +++ b/NEWS @@ -34,8 +34,10 @@ PHP NEWS (nielsdos) - GD: - . Fixed bug 16232 (bitshift overflow on wbmp file content reading / + . 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) - LDAP: . Fixed bug GH-16032 (Various NULL pointer dereferencements in diff --git a/ext/gd/gd.c b/ext/gd/gd.c index ef5bc9a03a342..3b824430597b6 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -1195,6 +1195,11 @@ PHP_FUNCTION(imagerotate) 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); diff --git a/ext/gd/tests/gh16260.phpt b/ext/gd/tests/gh16260.phpt new file mode 100644 index 0000000000000..563fc8d162786 --- /dev/null +++ b/ext/gd/tests/gh16260.phpt @@ -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 From a5e8ac62d9bdb101f6cd42beb63aec0a21daaf11 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 6 Oct 2024 05:46:33 +0100 Subject: [PATCH 77/94] Fix GH-16258 overflow on jddayofweek argument. close GH-16263 --- NEWS | 1 + ext/calendar/dow.c | 9 +-------- ext/calendar/tests/gh16258.phpt | 12 ++++++++++++ 3 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 ext/calendar/tests/gh16258.phpt diff --git a/NEWS b/NEWS index f4ad67f2f0e19..bb9ef61cd6e09 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ PHP NEWS . 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) - CLI: . Fixed bug GH-16137: duplicate http headers when set several times by diff --git a/ext/calendar/dow.c b/ext/calendar/dow.c index 38da7e157c279..079dd6c15ada4 100644 --- a/ext/calendar/dow.c +++ b/ext/calendar/dow.c @@ -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 --git a/ext/calendar/tests/gh16258.phpt b/ext/calendar/tests/gh16258.phpt new file mode 100644 index 0000000000000..9f2b70fac542b --- /dev/null +++ b/ext/calendar/tests/gh16258.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-16258 (jddayofweek overflow on argument) +--EXTENSIONS-- +calendar +--FILE-- + +--EXPECT-- +DONE From a9dada29e7da675db17db7a217e08002f7b98dde Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 5 Oct 2024 23:51:35 +0200 Subject: [PATCH 78/94] Fix Soap leaking http_msg on error Testing all cases is not so easy to do as we would need a server that redirects from e.g. http to https while SSL is not available. Closes GH-16254. --- NEWS | 1 + ext/soap/php_http.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/NEWS b/NEWS index bb9ef61cd6e09..8392392cb97b7 100644 --- a/NEWS +++ b/NEWS @@ -74,6 +74,7 @@ PHP NEWS - 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) - Standard: . Fixed bug GH-15613 (overflow on unpack call hex string repeater). diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 0c71c4f963166..00aa54c83efdb 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -461,6 +461,7 @@ int make_http_soap_request(zval *this_ptr, } 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 @@ int make_http_soap_request(zval *this_ptr, } 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 @@ int make_http_soap_request(zval *this_ptr, 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 @@ int make_http_soap_request(zval *this_ptr, 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 @@ int make_http_soap_request(zval *this_ptr, 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 @@ int make_http_soap_request(zval *this_ptr, 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 @@ int make_http_soap_request(zval *this_ptr, 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 @@ int make_http_soap_request(zval *this_ptr, 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 @@ int make_http_soap_request(zval *this_ptr, 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; } From fbb1001d842bff6e2388c89276991ad0a2c965c7 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 5 Oct 2024 23:32:12 +0200 Subject: [PATCH 79/94] Add SKIPIF for ZendMM for observer_fiber_functions_03.phpt This test uses memory_limit, so it fails when using USE_ZEND_ALLOC=0. --- ext/zend_test/tests/observer_fiber_functions_03.phpt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/zend_test/tests/observer_fiber_functions_03.phpt b/ext/zend_test/tests/observer_fiber_functions_03.phpt index 3468120ef4b58..147e6f7229d49 100644 --- a/ext/zend_test/tests/observer_fiber_functions_03.phpt +++ b/ext/zend_test/tests/observer_fiber_functions_03.phpt @@ -10,6 +10,10 @@ zend_test.observer.fiber_init=1 zend_test.observer.fiber_switch=1 zend_test.observer.fiber_destroy=1 memory_limit=100M +--SKIPIF-- + --FILE-- Date: Sun, 6 Oct 2024 17:10:12 +0200 Subject: [PATCH 80/94] Fix GH-16256: Assertion failure in ext/soap/php_encoding.c:460 The class map must be an associative array, not a packed array. Closes GH-16269. --- NEWS | 2 ++ ext/soap/soap.c | 6 ++++++ ext/soap/tests/bugs/gh16256.phpt | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 ext/soap/tests/bugs/gh16256.phpt diff --git a/NEWS b/NEWS index 8392392cb97b7..cec98047e9930 100644 --- a/NEWS +++ b/NEWS @@ -75,6 +75,8 @@ PHP NEWS . 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) - Standard: . Fixed bug GH-15613 (overflow on unpack call hex string repeater). diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 924e60deaa40d..0996927cee092 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -838,6 +838,9 @@ PHP_METHOD(SoapServer, __construct) 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)); } @@ -2004,6 +2007,9 @@ PHP_METHOD(SoapClient, __construct) } 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 --git a/ext/soap/tests/bugs/gh16256.phpt b/ext/soap/tests/bugs/gh16256.phpt new file mode 100644 index 0000000000000..ca8c00af5bbfb --- /dev/null +++ b/ext/soap/tests/bugs/gh16256.phpt @@ -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 From e3015de741dd204dd21c0f28aa8e17ee731962b4 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 5 Oct 2024 08:47:44 +0100 Subject: [PATCH 81/94] Fix GH-16234 jewishtojd overflow on year argument. close GH-16243 --- NEWS | 1 + ext/calendar/jewish.c | 19 +++++++++++++++++-- ext/calendar/tests/gh16234.phpt | 11 +++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 ext/calendar/tests/gh16234.phpt diff --git a/NEWS b/NEWS index cec98047e9930..b083174c1b146 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ PHP NEWS . 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 diff --git a/ext/calendar/jewish.c b/ext/calendar/jewish.c index 11318bd5bc619..bdfc9b4f91016 100644 --- a/ext/calendar/jewish.c +++ b/ext/calendar/jewish.c @@ -433,16 +433,31 @@ static void MoladOfMetonicCycle( 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 --git a/ext/calendar/tests/gh16234.phpt b/ext/calendar/tests/gh16234.phpt new file mode 100644 index 0000000000000..03777986dc8c3 --- /dev/null +++ b/ext/calendar/tests/gh16234.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-16234 jewishtojd overflow on year argument +--EXTENSIONS-- +calendar +--FILE-- + +--EXPECT-- +DONE From 8537aa687e8da4938fd1ac4570e8065f6f98d938 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 6 Oct 2024 16:09:47 +0100 Subject: [PATCH 82/94] Fix GH-16267 socket_strerror overflow on argument value. only socket_strerror provides user-supplied value to sockets_strerror handler. close GH-16270 --- NEWS | 4 ++++ ext/sockets/sockets.c | 5 +++++ ext/sockets/tests/gh16267.phpt | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 ext/sockets/tests/gh16267.phpt diff --git a/NEWS b/NEWS index b083174c1b146..68f6fa4203612 100644 --- a/NEWS +++ b/NEWS @@ -72,6 +72,10 @@ PHP NEWS . 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) diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 8183398a8d322..f1a62c719291a 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -1211,6 +1211,11 @@ PHP_FUNCTION(socket_strerror) 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)); } /* }}} */ diff --git a/ext/sockets/tests/gh16267.phpt b/ext/sockets/tests/gh16267.phpt new file mode 100644 index 0000000000000..d2462b3164530 --- /dev/null +++ b/ext/sockets/tests/gh16267.phpt @@ -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 From 5a47f2702171d30f3e3ba4d3a2e2f33d499a7c11 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 4 Oct 2024 23:00:45 +0100 Subject: [PATCH 83/94] Fix GH-15395: php-fpm: zend_mm_heap corrupted with cgi-fcgi request Closes GH-16227 Co-authored-by: David Carlier --- NEWS | 6 +- main/SAPI.c | 3 + main/main.c | 4 +- sapi/fpm/tests/gh15395-php-auth-shutdown.phpt | 61 +++++++++++++++++++ sapi/fpm/tests/tester.inc | 3 +- 5 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 sapi/fpm/tests/gh15395-php-auth-shutdown.phpt diff --git a/NEWS b/NEWS index 68f6fa4203612..b5173a5f6688d 100644 --- a/NEWS +++ b/NEWS @@ -34,7 +34,7 @@ PHP NEWS 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) @@ -68,6 +68,10 @@ PHP NEWS . 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) diff --git a/main/SAPI.c b/main/SAPI.c index 09b028e55166e..d0226ded65bec 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -507,12 +507,15 @@ SAPI_API void sapi_deactivate_module(void) } 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 --git a/main/main.c b/main/main.c index 0adecd10ffcca..3e03951e87755 100644 --- a/main/main.c +++ b/main/main.c @@ -2672,7 +2672,9 @@ PHPAPI int php_handle_auth_data(const char *auth) 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 --git a/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt b/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt new file mode 100644 index 0000000000000..b9875dd10ef5e --- /dev/null +++ b/sapi/fpm/tests/gh15395-php-auth-shutdown.phpt @@ -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 --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index ed0988f883ac1..bf4f3d918131c 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -762,6 +762,7 @@ class Tester 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 @@ class Tester $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 { From 4c76509f82e62cd32957821a6985ec01735f1814 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 6 Oct 2024 21:23:45 +0100 Subject: [PATCH 84/94] Fix extra spaces in NEWS [skip ci] --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index b5173a5f6688d..598cd949b47de 100644 --- a/NEWS +++ b/NEWS @@ -34,7 +34,7 @@ PHP NEWS 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) From d9d82377ccdffcacd4da719fe496791430f26f31 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Sat, 28 Sep 2024 20:51:05 +0200 Subject: [PATCH 85/94] Update Windows CI to use php-sdk-2.3.0 php-sdk-2.2.0 still fetches dependencies from the no longer up to date , and as such won't be tested with any security updates we provide for Windows. Given that PHP 8.1 is going to receive security updates for further 15 months, we should should not ignore these dependency updates. Closes GH-16097. --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index ddb4ee0aaf172..966bdea59371f 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -135,7 +135,7 @@ jobs: PHP_BUILD_CACHE_BASE_DIR: C:\build-cache PHP_BUILD_OBJ_DIR: C:\obj PHP_BUILD_CACHE_SDK_DIR: C:\build-cache\sdk - PHP_BUILD_SDK_BRANCH: php-sdk-2.2.0 + PHP_BUILD_SDK_BRANCH: php-sdk-2.3.0 PHP_BUILD_CRT: vs16 PLATFORM: x64 THREAD_SAFE: "1" From 53cc92c85c17e5178b27bae51ca7d146d40468c1 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 10 Mar 2024 20:51:22 +0000 Subject: [PATCH 86/94] Fix failing openssl_private_decrypt tests We backport 11caf094f1af6b47ea2138c5fa907838911ebe01[1] as a step to get back to a green CI. [1] --- ext/openssl/tests/openssl_error_string_basic.phpt | 8 ++++---- .../tests/openssl_error_string_basic_openssl3.phpt | 8 ++++---- ext/openssl/tests/openssl_private_decrypt_basic.phpt | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ext/openssl/tests/openssl_error_string_basic.phpt b/ext/openssl/tests/openssl_error_string_basic.phpt index e4ea264b3bf1f..4b5ca9fd9c042 100644 --- a/ext/openssl/tests/openssl_error_string_basic.phpt +++ b/ext/openssl/tests/openssl_error_string_basic.phpt @@ -118,12 +118,12 @@ expect_openssl_errors('openssl_pkey_get_public', [$err_pem_no_start_line]); @openssl_private_encrypt("data", $crypted, $private_key_file, 1000); expect_openssl_errors('openssl_private_encrypt', ['0408F090']); // private decrypt with failed padding check -@openssl_private_decrypt("data", $crypted, $private_key_file); -expect_openssl_errors('openssl_private_decrypt', ['04065072']); +@openssl_private_decrypt("data", $crypted, $private_key_file, OPENSSL_PKCS1_OAEP_PADDING); +expect_openssl_errors('openssl_private_decrypt', ['04099079']); // public encrypt and decrypt with failed padding check and padding @openssl_public_encrypt("data", $crypted, $public_key_file, 1000); -@openssl_public_decrypt("data", $crypted, $public_key_file); -expect_openssl_errors('openssl_private_(en|de)crypt padding', [$err_pem_no_start_line, '0408F090', '04067072']); +@openssl_public_decrypt("data", $crypted, $public_key_file, OPENSSL_PKCS1_OAEP_PADDING); +expect_openssl_errors('openssl_private_(en|de)crypt padding', [$err_pem_no_start_line, '0408F090', '06089093']); // X509 echo "X509 errors\n"; diff --git a/ext/openssl/tests/openssl_error_string_basic_openssl3.phpt b/ext/openssl/tests/openssl_error_string_basic_openssl3.phpt index d435a53e3047f..2de36d6af0606 100644 --- a/ext/openssl/tests/openssl_error_string_basic_openssl3.phpt +++ b/ext/openssl/tests/openssl_error_string_basic_openssl3.phpt @@ -121,12 +121,12 @@ expect_openssl_errors('openssl_pkey_get_public', [$err_pem_no_start_line]); @openssl_private_encrypt("data", $crypted, $private_key_file, 1000); expect_openssl_errors('openssl_private_encrypt', ['1C8000A5']); // private decrypt with failed padding check -@openssl_private_decrypt("data", $crypted, $private_key_file); -expect_openssl_errors('openssl_private_decrypt', ['0200009F', '02000072']); +@openssl_private_decrypt("data", $crypted, $private_key_file, OPENSSL_PKCS1_OAEP_PADDING); +expect_openssl_errors('openssl_private_decrypt', ['02000079']); // public encrypt and decrypt with failed padding check and padding @openssl_public_encrypt("data", $crypted, $public_key_file, 1000); -@openssl_public_decrypt("data", $crypted, $public_key_file); -expect_openssl_errors('openssl_private_(en|de)crypt padding', [$err_pem_no_start_line, '02000076', '0200008A', '02000072', '1C880004']); +@openssl_public_decrypt("data", $crypted, $public_key_file, OPENSSL_PKCS1_OAEP_PADDING); +expect_openssl_errors('openssl_private_(en|de)crypt padding', [$err_pem_no_start_line, '1C8000A5']); // X509 echo "X509 errors\n"; diff --git a/ext/openssl/tests/openssl_private_decrypt_basic.phpt b/ext/openssl/tests/openssl_private_decrypt_basic.phpt index ec37aea1614b3..44101d580c02f 100644 --- a/ext/openssl/tests/openssl_private_decrypt_basic.phpt +++ b/ext/openssl/tests/openssl_private_decrypt_basic.phpt @@ -9,22 +9,22 @@ $privkey = "file://" . __DIR__ . "/private_rsa_1024.key"; $pubkey = "file://" . __DIR__ . "/public.key"; $wrong = "wrong"; -openssl_public_encrypt($data, $encrypted, $pubkey); -var_dump(openssl_private_decrypt($encrypted, $output, $privkey)); +openssl_public_encrypt($data, $encrypted, $pubkey, OPENSSL_PKCS1_OAEP_PADDING); +var_dump(openssl_private_decrypt($encrypted, $output, $privkey, OPENSSL_PKCS1_OAEP_PADDING)); var_dump($output); -var_dump(openssl_private_decrypt($encrypted, $output2, $wrong)); +var_dump(openssl_private_decrypt($encrypted, $output2, $wrong, OPENSSL_PKCS1_OAEP_PADDING)); var_dump($output2); -var_dump(openssl_private_decrypt($wrong, $output3, $privkey)); +var_dump(openssl_private_decrypt($wrong, $output3, $privkey, OPENSSL_PKCS1_OAEP_PADDING)); var_dump($output3); try { - var_dump(openssl_private_decrypt($encrypted, $output4, array($privkey))); + var_dump(openssl_private_decrypt($encrypted, $output4, array($privkey), OPENSSL_PKCS1_OAEP_PADDING)); var_dump($output4); } catch (\ValueError $e) { echo $e->getMessage() . \PHP_EOL; } -var_dump(openssl_private_decrypt($encrypted, $output5, array($privkey, ""))); +var_dump(openssl_private_decrypt($encrypted, $output5, array($privkey, ""), OPENSSL_PKCS1_OAEP_PADDING)); var_dump($output5); ?> --EXPECTF-- From c3434091debb8ac2116835e5f3fd960be7c0bb55 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 4 Oct 2024 23:46:24 +0200 Subject: [PATCH 87/94] Install 32bit Firebird server on x86 php_pdo_firebird.dll depends on fbclient.dll, which is shipped with the server. However, a 64bit Firebird server ships a 64bit fbclient.dll, which is not compatible with a 32bit php_pdo_firebird.dll. Closes GH-16223. --- .github/scripts/windows/test_task.bat | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/scripts/windows/test_task.bat b/.github/scripts/windows/test_task.bat index 4a180df27dfab..7856eb0fb0fe2 100644 --- a/.github/scripts/windows/test_task.bat +++ b/.github/scripts/windows/test_task.bat @@ -52,7 +52,12 @@ set ODBC_TEST_DSN=Driver={ODBC Driver 17 for SQL Server};Server=^(local^)\SQLEXP 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% From a2bdfeff4f7625ec0e4a979702cf75f3aa4b0720 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 6 Oct 2024 21:55:58 +0100 Subject: [PATCH 88/94] Fix GH-16257 imagescale underflow on RGB channels. backport of https://github.com/libgd/libgd/commit/948bb0a5c2010a24227e4b44a90e8b8aa9bda8ce close GH-16257 --- NEWS | 2 ++ ext/gd/libgd/gd_interpolation.c | 52 ++++++++++++++++++++++----------- ext/gd/tests/gh16257.phpt | 12 ++++++++ 3 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 ext/gd/tests/gh16257.phpt diff --git a/NEWS b/NEWS index 598cd949b47de..83b36ef3f032e 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,8 @@ PHP NEWS 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 diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c index cf8821372d923..2fde78be19895 100644 --- a/ext/gd/libgd/gd_interpolation.c +++ b/ext/gd/libgd/gd_interpolation.c @@ -929,6 +929,24 @@ static inline LineContribType *_gdContributionsCalc(unsigned int line_size, unsi return res; } +static inline unsigned char +uchar_clamp(double clr) { + 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 > 255) { + result = (clr < 0) ? 0 : 255; + }/* 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 +954,20 @@ static inline void _gdScaleRow(gdImagePtr pSrc, unsigned int src_width, gdImage 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), uchar_clamp(g), uchar_clamp(b), uchar_clamp(a)); } } @@ -982,7 +1000,7 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag { 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 +1009,12 @@ static inline void _gdScaleCol (gdImagePtr pSrc, unsigned int src_width, gdImag 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), uchar_clamp(g), uchar_clamp(b), uchar_clamp(a)); } } diff --git a/ext/gd/tests/gh16257.phpt b/ext/gd/tests/gh16257.phpt new file mode 100644 index 0000000000000..01f4d4fbd61f8 --- /dev/null +++ b/ext/gd/tests/gh16257.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-16257 (underflow on RBG channels handling with imagescale) +--EXTENSIONS-- +gd +--FILE-- + +--EXPECT-- +DONE From c2115a43e37e2a0998fbfd10d2541cd2789c22e3 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Thu, 3 Oct 2024 13:18:16 +0200 Subject: [PATCH 89/94] Handle references properties of the Exception class Fixes GH-16188 Closes GH-16196 --- Zend/tests/gh16188.phpt | 34 ++++++++++++++++++++++++++++++++++ Zend/zend_exceptions.c | 12 +++++++++--- 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 Zend/tests/gh16188.phpt diff --git a/Zend/tests/gh16188.phpt b/Zend/tests/gh16188.phpt new file mode 100644 index 0000000000000..4516f7cade90b --- /dev/null +++ b/Zend/tests/gh16188.phpt @@ -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 --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 8ad603e51e71c..d2547ced6f7f5 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -115,15 +115,18 @@ void zend_exception_set_previous(zend_object *exception, zend_object *add_previo 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 @@ ZEND_METHOD(Exception, getTraceAsString) 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_METHOD(Exception, getPrevious) 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 @@ ZEND_METHOD(Exception, __toString) 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 @@ ZEND_METHOD(Exception, __toString) 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; From df4db5c1b4786dbcb36c2a413bbb99c5f62db7e6 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 7 Oct 2024 15:02:44 +0200 Subject: [PATCH 90/94] NEWS for GH-16196 --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 83b36ef3f032e..9267af608b4e9 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,7 @@ PHP NEWS . 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) - Date: . Fixed bug GH-15582: Crash when not calling parent constructor of From e715dd0afb1babc122efd4142c95623a12e14cfd Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 5 Oct 2024 22:55:09 +0200 Subject: [PATCH 91/94] Fixed GH-16233: Observer segfault when calling user function in internal function via trampoline In the test, I have an internal `__call` function for `_ZendTestMagicCallForward` that calls the global function with name `$name` via `call_user_function`. Note that observer writes the pointer to the previously observed frame in the last temporary of the new call frame (`*prev_observed_frame`). The following happens: First, we call `$test->callee`, this will be handled via a trampoline with T=2 for the two arguments. The call frame is allocated at this point. This call frame is not observed because it has `ZEND_ACC_CALL_VIA_TRAMPOLINE` set. Next we use `ZEND_CALL_TRAMPOLINE` to call the trampoline, this reuses the stack frame allocated earlier with T=2, but this time it is observed. The pointer to the previous frame is written outside of the call frame because `T` is too small (should be 3). We are now in the internal function `_ZendTestMagicCallForward::__call` where we call the global function `callee`. This will push a new call frame which will overlap `*prev_observed_frame`. This value gets overwritten by `zend_init_func_execute_data` when `EX(opline)` is set because `*prev_observed_frame` overlaps with `EX(opline)`. From now on, `*prev_observed_frame` is corrupted. When `zend_observer_fcall_end` is called this will result in reading wrong value `*prev_observed_frame` into `current_observed_frame`. This causes issues in `zend_observer_fcall_end_all` leading to the segfault we observe. Despite function with `ZEND_ACC_CALL_VIA_TRAMPOLINE` not being observed, the reuse of call frames makes problems when `T` is not large enough. To fix this, we make sure to add 1 to `T` if `ZEND_OBSERVER_ENABLED` is true. Closes GH-16252. --- NEWS | 2 ++ Zend/zend_object_handlers.c | 4 +++- ext/zend_test/test.c | 19 +++++++++++++++++++ ext/zend_test/test.stub.php | 5 +++++ ext/zend_test/test_arginfo.h | 21 ++++++++++++++++++++- ext/zend_test/tests/gh16233.phpt | 32 ++++++++++++++++++++++++++++++++ 6 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 ext/zend_test/tests/gh16233.phpt diff --git a/NEWS b/NEWS index 9267af608b4e9..799225ca186ca 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,8 @@ PHP NEWS 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 diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index d4586e53e4b4a..def9695ed98bd 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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 @@ -1294,7 +1295,8 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend * 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 --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 2df6c2027498a..8989413317d76 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -879,6 +879,23 @@ static ZEND_METHOD(_ZendTestMagicCall, __call) 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 +1010,8 @@ PHP_MINIT_FUNCTION(zend_test) 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 --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 7dc348934400f..8a605bdcd3280 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -52,6 +52,11 @@ class _ZendTestMagicCall 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 {} diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 19ea9e7a2adf5..9c0735a1d6f89 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 07ce28cd75080118509ac0d30d8ce5ef54110747 */ + * Stub hash: 5d861e05edfd57c385167b11b8b1ea977ed130a2 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -161,6 +161,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class__ZendTestMagicCall___call, 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() @@ -245,6 +247,7 @@ static ZEND_METHOD(_ZendTestClass, returnsStatic); 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); @@ -332,6 +335,12 @@ static const zend_function_entry class__ZendTestMagicCall_methods[] = { }; +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 @@ -532,6 +541,16 @@ static zend_class_entry *register_class__ZendTestMagicCall(void) 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) { zend_class_entry ce, *class_entry; diff --git a/ext/zend_test/tests/gh16233.phpt b/ext/zend_test/tests/gh16233.phpt new file mode 100644 index 0000000000000..e3143b6c7ce11 --- /dev/null +++ b/ext/zend_test/tests/gh16233.phpt @@ -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 + From 71222f799da8936c175b1219a1c351f778f6da69 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 6 Oct 2024 20:30:01 +0200 Subject: [PATCH 92/94] Fix GH-16259: Soap segfault when classmap instantiation fails Instantiation failure checks were missing. Closes GH-16273. --- NEWS | 2 ++ ext/soap/php_encoding.c | 20 +++++++++++++++----- ext/soap/tests/bugs/gh16259.phpt | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 ext/soap/tests/bugs/gh16259.phpt diff --git a/NEWS b/NEWS index 799225ca186ca..5f4b19f6fa865 100644 --- a/NEWS +++ b/NEWS @@ -91,6 +91,8 @@ PHP NEWS . 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). diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 6568446249a31..29cf8fbc9086b 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -1408,7 +1408,9 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z 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 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z 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 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z 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 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z 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 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z 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; diff --git a/ext/soap/tests/bugs/gh16259.phpt b/ext/soap/tests/bugs/gh16259.phpt new file mode 100644 index 0000000000000..dd7e0e1585d29 --- /dev/null +++ b/ext/soap/tests/bugs/gh16259.phpt @@ -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 From bf70d9ba0d493d054500a1d6033f43948ff03393 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 6 Oct 2024 19:57:21 +0200 Subject: [PATCH 93/94] Fix GH-16261: Reference invariant broken in mb_convert_variables() The behaviour is weird in the sense that the reference must get unwrapped. What ended up happening is that when destroying the old reference the sources list was not cleaned properly. We add handling for that. Normally we would use use ZEND_TRY_ASSIGN_STRINGL but that doesn't work here as it would keep the reference and change values through references (see bug #26639). Closes GH-16272. --- NEWS | 4 +++ ext/mbstring/mbstring.c | 19 ++++++++++++-- ext/mbstring/tests/gh16261.phpt | 44 +++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 ext/mbstring/tests/gh16261.phpt diff --git a/NEWS b/NEWS index 5f4b19f6fa865..5d3c1e46ce304 100644 --- a/NEWS +++ b/NEWS @@ -56,6 +56,10 @@ PHP NEWS . 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) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 0b362309ca438..70125dc909748 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -3289,7 +3289,7 @@ static int mb_recursive_convert_variable(mbfl_buffer_converter *convd, zval *var 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 +3305,22 @@ static int mb_recursive_convert_variable(mbfl_buffer_converter *convd, zval *var 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); diff --git a/ext/mbstring/tests/gh16261.phpt b/ext/mbstring/tests/gh16261.phpt new file mode 100644 index 0000000000000..3573bd191c63d --- /dev/null +++ b/ext/mbstring/tests/gh16261.phpt @@ -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" +} From 33657c01d305f18aeb0821e88c3e1475b3543144 Mon Sep 17 00:00:00 2001 From: Sergey Panteleev Date: Tue, 22 Oct 2024 18:12:03 +0300 Subject: [PATCH 94/94] Update versions for PHP 8.2.25 --- NEWS | 2 +- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 5d3c1e46ce304..9c7d5670e64a8 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.25 +24 Oct 2024, PHP 8.2.25 - Calendar: . Fixed GH-16240: jdtounix overflow on argument value. (David Carlier) diff --git a/Zend/zend.h b/Zend/zend.h index 8210737da9218..d59b2f203fb61 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.25-dev" +#define ZEND_VERSION "4.2.25" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 9c71f6503311d..8617033a55648 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.2.25-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.25],[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 diff --git a/main/php_version.h b/main/php_version.h index e2f9e04ada6af..c58b7a36e5b50 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 2 #define PHP_RELEASE_VERSION 25 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.25-dev" +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.2.25" #define PHP_VERSION_ID 80225