From c34d4fbbf4786851f463ce52d4133e5cedd33d6b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 11 Oct 2024 05:42:03 +0100 Subject: [PATCH] Fix GH-16360 mb_substr overflow on start and length arguments. occurs when they are negated to start working from the end instead when set with ZEND_LONG_MIN. --- NEWS | 4 ++++ ext/mbstring/mbstring.c | 10 ++++++++++ ext/mbstring/tests/gh16360.phpt | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 ext/mbstring/tests/gh16360.phpt diff --git a/NEWS b/NEWS index 0b6e93a1f86..315690eddfc 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,10 @@ PHP NEWS . Fixed bug GH-16316 (DOMXPath breaks when not initialized properly). (nielsdos) +- MBstring: + . Fixed bug GH-16361 (mb_substr overflow on start/length arguments). + (David Carlier) + - PHPDBG: . Fixed bug GH-16174 (Empty string is an invalid expression for ev). (cmb) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 70125dc9097..7efefb77e57 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2172,6 +2172,16 @@ PHP_FUNCTION(mb_substr) Z_PARAM_STR_OR_NULL(encoding) ZEND_PARSE_PARAMETERS_END(); + if (from == ZEND_LONG_MIN) { + zend_argument_value_error(2, "must be between " ZEND_LONG_FMT " and " ZEND_LONG_FMT, (ZEND_LONG_MIN + 1), ZEND_LONG_MAX); + RETURN_THROWS(); + } + + if (!len_is_null && len == ZEND_LONG_MIN) { + zend_argument_value_error(3, "must be between " ZEND_LONG_FMT " and " ZEND_LONG_FMT, (ZEND_LONG_MIN + 1), ZEND_LONG_MAX); + RETURN_THROWS(); + } + string.encoding = php_mb_get_encoding(encoding, 4); if (!string.encoding) { RETURN_THROWS(); diff --git a/ext/mbstring/tests/gh16360.phpt b/ext/mbstring/tests/gh16360.phpt new file mode 100644 index 00000000000..4e2e8fb4bfc --- /dev/null +++ b/ext/mbstring/tests/gh16360.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-16320 mb_substr overflow from negative length +--EXTENSIONS-- +mbstring +--FILE-- +getMessage() . PHP_EOL; +} +try { + mb_substr("abcd", 0, PHP_INT_MIN, "UTF-8"); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} +var_dump(mb_substr("abcd", PHP_INT_MAX, PHP_INT_MAX, "UTF-8")); +?> +--EXPECTF-- +mb_substr(): Argument #2 ($start) must be between %s and %s +mb_substr(): Argument #3 ($length) must be between %s and %s +string(0) "" +