From 2eb3100dcaba63a394f0d0ab9993637a97d84a42 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 26 Apr 2025 23:20:16 +0200 Subject: [PATCH 1/3] Fix GH-18438: Handling of empty data and errors in ZipArchive::addPattern There is a ZPP arginfo violation because the empty return or error return is not always properly handled. And there is also a memory leak if creating the regular expression instance fails. Closes GH-18438. --- NEWS | 2 ++ ext/zip/php_zip.c | 8 ++++++ ext/zip/tests/gh18438.phpt | 50 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 ext/zip/tests/gh18438.phpt diff --git a/NEWS b/NEWS index c167074f0b8..efd92cb011a 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ PHP NEWS - Zip: . Fixed bug GH-18431 (Registering ZIP progress callback twice doesn't work). (nielsdos) + . Fixed bug GH-18438 (Handling of empty data and errors in + ZipArchive::addPattern). (nielsdos) 08 May 2025, PHP 8.3.21 diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 388b3485cbd..62f51ce9f35 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -761,6 +761,10 @@ int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_val re = pcre_get_compiled_regex(regexp, &capture_count); if (!re) { + for (i = 0; i < files_cnt; i++) { + zend_string_release_ex(namelist[i], 0); + } + efree(namelist); php_error_docref(NULL, E_WARNING, "Invalid expression"); return -1; } @@ -1837,6 +1841,10 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* #endif } } + } else if (found == 0) { + RETURN_EMPTY_ARRAY(); + } else { + RETURN_FALSE; } } /* }}} */ diff --git a/ext/zip/tests/gh18438.phpt b/ext/zip/tests/gh18438.phpt new file mode 100644 index 00000000000..b997931c708 --- /dev/null +++ b/ext/zip/tests/gh18438.phpt @@ -0,0 +1,50 @@ +--TEST-- +GH-18438 (Handling of empty data and errors in ZipArchive::addPattern) +--EXTENSIONS-- +zip +--SKIPIF-- + +--FILE-- +open($file, ZIPARCHIVE::CREATE); +var_dump($zip->addPattern('/nomatches/')); +var_dump($zip->addPattern('/invalid')); + +stream_wrapper_register('custom', CustomStreamWrapper::class); +var_dump($zip->addPattern('/invalid', 'custom://')); +?> +--CLEAN-- + +--EXPECTF-- +array(0) { +} + +Warning: ZipArchive::addPattern(): No ending delimiter '/' found in %s on line %d + +Warning: ZipArchive::addPattern(): Invalid expression in %s on line %d +bool(false) +array(0) { +} From 2beec54e47572ed8d3c4bf853047195988e4ee55 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 27 Apr 2025 00:29:12 +0200 Subject: [PATCH 2/3] datefmt_parse/datefmt_localtime references type system fixes Closes GH-18441. --- NEWS | 3 ++ ext/intl/dateformat/dateformat_parse.c | 18 +++++----- .../datefmt_parse_localtime_references.phpt | 35 +++++++++++++++++++ 3 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 ext/intl/tests/datefmt_parse_localtime_references.phpt diff --git a/NEWS b/NEWS index efd92cb011a..6d317e7507f 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,9 @@ PHP NEWS inaccurate sunrise and sunset times, but other calculated times are correct) (JiriJozif). +- Intl: + . datefmt_parse/datefmt_localtime references type system fixes. (nielsdos) + - SPL: . Fixed bug GH-18421 (Integer overflow with large numbers in LimitIterator). (nielsdos) diff --git a/ext/intl/dateformat/dateformat_parse.c b/ext/intl/dateformat/dateformat_parse.c index 69aeff886d3..cd6c2c35978 100644 --- a/ext/intl/dateformat/dateformat_parse.c +++ b/ext/intl/dateformat/dateformat_parse.c @@ -136,9 +136,9 @@ PHP_FUNCTION(datefmt_parse) DATE_FORMAT_METHOD_FETCH_OBJECT; if (z_parse_pos) { - zend_long long_parse_pos; - ZVAL_DEREF(z_parse_pos); - long_parse_pos = zval_get_long(z_parse_pos); + zval *z_parse_pos_tmp = z_parse_pos; + ZVAL_DEREF(z_parse_pos_tmp); + zend_long long_parse_pos = zval_get_long(z_parse_pos_tmp); if (ZEND_LONG_INT_OVFL(long_parse_pos)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); intl_error_set_custom_msg(NULL, "String index is out of valid range.", 0); @@ -151,8 +151,7 @@ PHP_FUNCTION(datefmt_parse) } internal_parse_to_timestamp( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, return_value); if(z_parse_pos) { - zval_ptr_dtor(z_parse_pos); - ZVAL_LONG(z_parse_pos, parse_pos); + ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); } } /* }}} */ @@ -177,9 +176,9 @@ PHP_FUNCTION(datefmt_localtime) DATE_FORMAT_METHOD_FETCH_OBJECT; if (z_parse_pos) { - zend_long long_parse_pos; - ZVAL_DEREF(z_parse_pos); - long_parse_pos = zval_get_long(z_parse_pos); + zval *z_parse_pos_tmp = z_parse_pos; + ZVAL_DEREF(z_parse_pos_tmp); + zend_long long_parse_pos = zval_get_long(z_parse_pos_tmp); if (ZEND_LONG_INT_OVFL(long_parse_pos)) { intl_error_set_code(NULL, U_ILLEGAL_ARGUMENT_ERROR); intl_error_set_custom_msg(NULL, "String index is out of valid range.", 0); @@ -192,8 +191,7 @@ PHP_FUNCTION(datefmt_localtime) } internal_parse_to_localtime( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, return_value); if (z_parse_pos) { - zval_ptr_dtor(z_parse_pos); - ZVAL_LONG(z_parse_pos, parse_pos); + ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); } } /* }}} */ diff --git a/ext/intl/tests/datefmt_parse_localtime_references.phpt b/ext/intl/tests/datefmt_parse_localtime_references.phpt new file mode 100644 index 00000000000..d9bede82ee1 --- /dev/null +++ b/ext/intl/tests/datefmt_parse_localtime_references.phpt @@ -0,0 +1,35 @@ +--TEST-- +datefmt_parse/datefmt_localtime references type system +--EXTENSIONS-- +intl +--FILE-- +prop; +$offset2 =& $test->prop; + +$fmt = datefmt_create( + 'en_US', + IntlDateFormatter::FULL, + IntlDateFormatter::FULL, + 'America/Los_Angeles', + IntlDateFormatter::GREGORIAN +); +datefmt_localtime($fmt, 'Wednesday, December 31, 1969 4:00:00 PM PT', $offset1); +datefmt_parse($fmt, 'Wednesday, December 31, 1969 4:00:00 PM PT', $offset2); +var_dump($offset1, $offset2); +var_dump($test); + +?> +--EXPECT-- +float(1) +float(1) +object(Test)#1 (1) { + ["prop"]=> + &float(1) +} From 173dccb646409945f8ed5dfef08fa68333fffcbe Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 27 Apr 2025 00:13:11 +0200 Subject: [PATCH 3/3] Fix IntlDateFormatter::parseToCalendar() reference type system breaks Closes GH-18440. --- NEWS | 2 ++ ext/intl/dateformat/dateformat_parse.c | 11 ++++---- ...arseToCalendar_references_type_system.phpt | 26 +++++++++++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 ext/intl/tests/parseToCalendar_references_type_system.phpt diff --git a/NEWS b/NEWS index cf676ed0dc6..1485a9f3110 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,8 @@ PHP NEWS - Intl: . datefmt_parse/datefmt_localtime references type system fixes. (nielsdos) + . Fix IntlDateFormatter::parseToCalendar() reference type system breaks. + (nielsdos) - SPL: . Fixed bug GH-18421 (Integer overflow with large numbers in LimitIterator). diff --git a/ext/intl/dateformat/dateformat_parse.c b/ext/intl/dateformat/dateformat_parse.c index b578b8bf854..129e007107d 100644 --- a/ext/intl/dateformat/dateformat_parse.c +++ b/ext/intl/dateformat/dateformat_parse.c @@ -185,12 +185,12 @@ PHP_METHOD(IntlDateFormatter, parseToCalendar) DATE_FORMAT_METHOD_FETCH_OBJECT; if (z_parse_pos) { - zend_long long_parse_pos; - ZVAL_DEREF(z_parse_pos); + zval *z_parse_pos_tmp = z_parse_pos; + ZVAL_DEREF(z_parse_pos_tmp); bool failed = false; - long_parse_pos = zval_try_get_long(z_parse_pos, &failed); + zend_long long_parse_pos = zval_try_get_long(z_parse_pos_tmp, &failed); if (failed) { - zend_argument_type_error(2, "must be of type int, %s given", zend_zval_value_name(z_parse_pos)); + zend_argument_type_error(2, "must be of type int, %s given", zend_zval_value_name(z_parse_pos_tmp)); RETURN_THROWS(); } if (ZEND_LONG_INT_OVFL(long_parse_pos)) { @@ -205,8 +205,7 @@ PHP_METHOD(IntlDateFormatter, parseToCalendar) } internal_parse_to_timestamp( dfo, ZSTR_VAL(text_to_parse), ZSTR_LEN(text_to_parse), z_parse_pos ? &parse_pos : NULL, true, return_value); if (z_parse_pos) { - zval_ptr_dtor(z_parse_pos); - ZVAL_LONG(z_parse_pos, parse_pos); + ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos); } } diff --git a/ext/intl/tests/parseToCalendar_references_type_system.phpt b/ext/intl/tests/parseToCalendar_references_type_system.phpt new file mode 100644 index 00000000000..d0cef570842 --- /dev/null +++ b/ext/intl/tests/parseToCalendar_references_type_system.phpt @@ -0,0 +1,26 @@ +--TEST-- +IntlDateFormatter::parseToCalendar() reference type system breaks +--EXTENSIONS-- +intl +--FILE-- +prop; + +$oIntlDateFormatter = new IntlDateFormatter("en_GB"); +$oIntlDateFormatter->setTimeZone('Europe/Berlin'); +$oIntlDateFormatter->setPattern('VV'); +var_dump($oIntlDateFormatter->parseToCalendar('America/Los_Angeles', $offset)); +var_dump($offset); +var_dump($test); +?> +--EXPECTF-- +int(%d) +float(%f) +object(Test)#%d (1) { + ["prop"]=> + &float(%f) +}