From b843e03c83d6be2cad555c6b701eb2d250070899 Mon Sep 17 00:00:00 2001 From: Nurzhan Bazhirov Date: Wed, 4 Feb 2026 12:34:54 +0500 Subject: [PATCH 1/3] Zend: Remove unused parameter from zend_dval_to_lval_cap() The `zend_string *s` parameter became unused after commit f754ffa8b20 (GH-20746) removed the `zend_oob_string_to_long_error()` calls. This fixes an unused-parameter compiler warning and updates a stale comment in zend_operators.c that incorrectly stated this function can emit warnings. Closes GH-21112 --- UPGRADING.INTERNALS | 2 ++ Zend/zend_operators.c | 12 ++++-------- Zend/zend_operators.h | 2 +- ext/dom/php_dom.c | 2 +- ext/tidy/tidy.c | 2 +- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 840edc786ac8b..27414f52b3754 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -68,6 +68,8 @@ PHP 8.6 INTERNALS UPGRADE NOTES more correctly represents the generic nature of the returned pointer and allows to remove explicit casts, but possibly breaks pointer arithmetic performed on the result. + . The zend_dval_to_lval_cap() function no longer takes a second + zend_string* parameter. ======================== 2. Build system changes diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 2550fcbeb1cde..571494088e331 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -427,18 +427,14 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval * * We use use saturating conversion to emulate strtol()'s * behaviour. */ - if (op_str == NULL) { - /* zend_dval_to_lval_cap() can emit a warning so always do the copy here */ - op_str = zend_string_copy(Z_STR_P(op)); - } - lval = zend_dval_to_lval_cap(dval, op_str); + lval = zend_dval_to_lval_cap(dval); if (!zend_is_long_compatible(dval, lval)) { - zend_incompatible_string_to_long_error(op_str); + zend_incompatible_string_to_long_error(op_str ? op_str : Z_STR_P(op)); if (UNEXPECTED(EG(exception))) { *failed = true; } } - zend_string_release(op_str); + zend_tmp_string_release(op_str); return lval; } } @@ -994,7 +990,7 @@ ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(const zval *op, bool is_stri * behaviour. */ /* Most usages are expected to not be (int) casts */ - lval = zend_dval_to_lval_cap(dval, Z_STR_P(op)); + lval = zend_dval_to_lval_cap(dval); if (UNEXPECTED(is_strict)) { if (!zend_is_long_compatible(dval, lval)) { zend_incompatible_string_to_long_error(Z_STR_P(op)); diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 2f226a76ccaf8..e6d648d1208a0 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -146,7 +146,7 @@ static zend_always_inline zend_long zend_dval_to_lval_silent(double d) } /* Used to convert a string float to integer during an (int) cast */ -static zend_always_inline zend_long zend_dval_to_lval_cap(double d, const zend_string *s) +static zend_always_inline zend_long zend_dval_to_lval_cap(double d) { if (UNEXPECTED(!zend_finite(d))) { return 0; diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 33a22e47c7800..57fa5e71f6bcb 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -2267,7 +2267,7 @@ static bool dom_nodemap_or_nodelist_process_offset_as_named(zval *offset, zend_l if (0 == (is_numeric_string_type = is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), lval, &dval, true))) { return true; } else if (is_numeric_string_type == IS_DOUBLE) { - *lval = zend_dval_to_lval_cap(dval, Z_STR_P(offset)); + *lval = zend_dval_to_lval_cap(dval); } } else { *lval = zval_get_long(offset); diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index 8cf45dc7fcbbc..9dcfb733a591f 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -757,7 +757,7 @@ static bool php_tidy_set_tidy_opt(TidyDoc doc, const char *optname, zval *value, } uint8_t type = is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &lval, &dval, true); if (type == IS_DOUBLE) { - lval = zend_dval_to_lval_cap(dval, str); + lval = zend_dval_to_lval_cap(dval); type = IS_LONG; } if (type == IS_LONG) { From 345bf38480a4bf190f15e3a1761dfec474d16e2b Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Wed, 4 Feb 2026 17:10:53 +0100 Subject: [PATCH 2/3] Install missing headers (#21125) These are included in public headers and should therefore be also installed. Follow-up of d16e6f52a432cc70fa8d54a3cd0c635ff403ec07 --- ext/random/config.m4 | 1 + ext/random/config.w32 | 2 +- ext/uri/config.m4 | 1 + ext/uri/config.w32 | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ext/random/config.m4 b/ext/random/config.m4 index ff43b856acf00..484f0549e0192 100644 --- a/ext/random/config.m4 +++ b/ext/random/config.m4 @@ -38,4 +38,5 @@ PHP_INSTALL_HEADERS([ext/random], m4_normalize([ php_random_csprng.h php_random_uint128.h php_random.h + random_decl.h ])) diff --git a/ext/random/config.w32 b/ext/random/config.w32 index 717055d6fc41b..bb0badbd183d7 100644 --- a/ext/random/config.w32 +++ b/ext/random/config.w32 @@ -1,4 +1,4 @@ EXTENSION("random", "random.c", false /* never shared */, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); PHP_RANDOM="yes"; ADD_SOURCES(configure_module_dirname, "csprng.c engine_mt19937.c engine_pcgoneseq128xslrr64.c engine_xoshiro256starstar.c engine_secure.c engine_user.c gammasection.c randomizer.c zend_utils.c", "random"); -PHP_INSTALL_HEADERS("ext/random", "php_random.h php_random_csprng.h php_random_uint128.h"); +PHP_INSTALL_HEADERS("ext/random", "php_random.h php_random_csprng.h php_random_uint128.h random_decl.h"); diff --git a/ext/uri/config.m4 b/ext/uri/config.m4 index dda586b752aa1..31d6c0e10c844 100644 --- a/ext/uri/config.m4 +++ b/ext/uri/config.m4 @@ -11,6 +11,7 @@ PHP_ARG_WITH([external-uriparser], PHP_INSTALL_HEADERS([ext/uri], m4_normalize([ php_uri.h php_uri_common.h + php_uri_decl.h uri_parser_rfc3986.h uri_parser_whatwg.h uri_parser_php_parse_url.h diff --git a/ext/uri/config.w32 b/ext/uri/config.w32 index 97c10caf098f6..b7c4bfbd22469 100644 --- a/ext/uri/config.w32 +++ b/ext/uri/config.w32 @@ -9,4 +9,4 @@ ADD_SOURCES("ext/uri/uriparser/src", "UriCommon.c UriCompare.c UriCopy.c UriEsca UriMemory.c UriNormalize.c UriNormalizeBase.c UriParse.c UriParseBase.c UriQuery.c UriRecompose.c UriResolve.c \ UriSetFragment.c UriSetHostAuto.c UriSetHostCommon.c UriSetHostIp4.c UriSetHostIp6.c UriSetHostIpFuture.c UriSetHostRegName.c \ UriSetPath.c UriSetPort.c UriSetQuery.c UriSetScheme.c UriSetUserInfo.c UriShorten.c UriVersion.c", "uri"); -PHP_INSTALL_HEADERS("ext/uri", "php_uri.h php_uri_common.h uri_parser_rfc3986.h uri_parser_whatwg.h uri_parser_php_parse_url.h uriparser/src uriparser/include"); +PHP_INSTALL_HEADERS("ext/uri", "php_uri.h php_uri_common.h php_uri_decl.h uri_parser_rfc3986.h uri_parser_whatwg.h uri_parser_php_parse_url.h uriparser/src uriparser/include"); From 7445b0f6d92a78a784df1037445455d345e5697e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Wed, 14 Jan 2026 18:38:37 +0100 Subject: [PATCH 3/3] Fix GH-20936: DatePeriod::__set_state() cannot handle null start The "current" and "end" field also rely on start_ce, which is set by "start". Therefore, if "current" or "end" are provided, so must "start" be provided. Closes GH-20939. --- NEWS | 4 ++++ ext/date/php_date.c | 4 ++-- ext/date/tests/gh20936.phpt | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 ext/date/tests/gh20936.phpt diff --git a/NEWS b/NEWS index 6416ddedb980d..81d0a689972ed 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,10 @@ PHP NEWS . Fixed bug GH-21023 (CURLOPT_XFERINFOFUNCTION crash with a null callback). (David Carlier) +- Date: + . Fixed bug GH-20936 (DatePeriod::__set_state() cannot handle null start). + (ndossche) + - DOM: . Fixed bug GH-21077 (Accessing Dom\Node::baseURI can throw TypeError). (ndossche) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 6d0f0428f08dd..a67a58bcf9232 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -5811,7 +5811,7 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, Has php_date_obj *date_obj; date_obj = Z_PHPDATE_P(ht_entry); - if (!date_obj->time) { + if (!date_obj->time || !period_obj->start_ce) { return 0; } @@ -5832,7 +5832,7 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, Has php_date_obj *date_obj; date_obj = Z_PHPDATE_P(ht_entry); - if (!date_obj->time) { + if (!date_obj->time || !period_obj->start_ce) { return 0; } diff --git a/ext/date/tests/gh20936.phpt b/ext/date/tests/gh20936.phpt new file mode 100644 index 0000000000000..e6a525dd4583e --- /dev/null +++ b/ext/date/tests/gh20936.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-20936 (DatePeriod::__set_state() cannot handle null start) +--FILE-- + null, 'end' => $end, 'current' => null, 'interval' => $interval, 'recurrences' => 2, 'include_start_date' => false, 'include_end_date' => true]); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), "\n"; +} +?> +--EXPECT-- +Error: Invalid serialization data for DatePeriod object