From 1c3e1a3d28fa2956b8795b135aaad46fd02a2c6a Mon Sep 17 00:00:00 2001 From: Francois Laupretre Date: Thu, 23 Jul 2015 04:01:23 +0200 Subject: [PATCH] substr_count(): Support negative values for '$offset' and '$length' parameters. --- ext/standard/string.c | 15 +++---- ext/standard/tests/strings/bug40754.phpt | 6 +-- .../tests/strings/substr_count_basic.phpt | 8 ++++ .../tests/strings/substr_count_error.phpt | 40 ++++++++----------- 4 files changed, 33 insertions(+), 36 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index 746bdd0620..4fe4f6123c 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -5293,12 +5293,10 @@ PHP_FUNCTION(substr_count) endp = p + haystack_len; if (offset < 0) { - php_error_docref(NULL, E_WARNING, "Offset should be greater than or equal to 0"); - RETURN_FALSE; + offset += (zend_long)haystack_len; } - - if ((size_t)offset > haystack_len) { - php_error_docref(NULL, E_WARNING, "Offset value " ZEND_LONG_FMT " exceeds string length", offset); + if ((offset < 0) || ((size_t)offset > haystack_len)) { + php_error_docref(NULL, E_WARNING, "Offset not contained in string"); RETURN_FALSE; } p += offset; @@ -5306,11 +5304,10 @@ PHP_FUNCTION(substr_count) if (ac == 4) { if (length <= 0) { - php_error_docref(NULL, E_WARNING, "Length should be greater than 0"); - RETURN_FALSE; + length += (haystack_len - offset); } - if (length > (haystack_len - offset)) { - php_error_docref(NULL, E_WARNING, "Length value " ZEND_LONG_FMT " exceeds string length", length); + if ((length <= 0) || (length > (haystack_len - offset))) { + php_error_docref(NULL, E_WARNING, "Invalid length value"); RETURN_FALSE; } endp = p + length; diff --git a/ext/standard/tests/strings/bug40754.phpt b/ext/standard/tests/strings/bug40754.phpt index 6cfe47056b..84e4337463 100644 --- a/ext/standard/tests/strings/bug40754.phpt +++ b/ext/standard/tests/strings/bug40754.phpt @@ -32,7 +32,7 @@ var_dump(substr("abcde", $v, $v)); bool(false) bool(false) -Warning: substr_count(): Offset value 2147483647 exceeds string length in %s on line %d +Warning: substr_count(): Offset not contained in string in %s on line %d bool(false) Warning: substr_compare(): The start position cannot exceed initial string length in %s on line %d @@ -41,10 +41,10 @@ bool(false) Warning: stripos(): Offset not contained in string in %s on line %d bool(false) -Warning: substr_count(): Offset value 2147483647 exceeds string length in %s on line %d +Warning: substr_count(): Offset not contained in string in %s on line %d bool(false) -Warning: substr_count(): Length value 2147483647 exceeds string length in %s on line %d +Warning: substr_count(): Invalid length value in %s on line %d bool(false) Warning: strpos(): Offset not contained in string in %s on line %d diff --git a/ext/standard/tests/strings/substr_count_basic.phpt b/ext/standard/tests/strings/substr_count_basic.phpt index f880e9481e..c7c96fd55b 100644 --- a/ext/standard/tests/strings/substr_count_basic.phpt +++ b/ext/standard/tests/strings/substr_count_basic.phpt @@ -9,12 +9,17 @@ var_dump(@substr_count("a", "")); var_dump(@substr_count("", "a")); var_dump(@substr_count("", "a")); var_dump(@substr_count("", chr(0))); + $a = str_repeat("abcacba", 100); var_dump(@substr_count($a, "bca")); + $a = str_repeat("abcacbabca", 100); var_dump(@substr_count($a, "bca")); var_dump(substr_count($a, "bca", 200)); var_dump(substr_count($a, "bca", 200, 50)); +var_dump(substr_count($a, "bca", -200)); +var_dump(substr_count($a, "bca", -200, 50)); +var_dump(substr_count($a, "bca", -200, -50)); echo "Done\n"; @@ -30,4 +35,7 @@ int(100) int(200) int(160) int(10) +int(40) +int(10) +int(30) Done diff --git a/ext/standard/tests/strings/substr_count_error.phpt b/ext/standard/tests/strings/substr_count_error.phpt index f6924217b9..881da391e6 100644 --- a/ext/standard/tests/strings/substr_count_error.phpt +++ b/ext/standard/tests/strings/substr_count_error.phpt @@ -4,27 +4,31 @@ Test substr_count() function (error conditions) size of the string */ var_dump(substr_count($str, "t", 25)); /* Using offset and length to go beyond the size of the string: Warning message expected, as length+offset > length of string */ -var_dump( substr_count($str, "i", 5, 15) ); +var_dump( substr_count($str, "i", 5, 7) ); -/* length as Null */ -var_dump( substr_count($str, "t", "", "") ); -var_dump( substr_count($str, "i", NULL, NULL) ); - -echo "Done\n"; +/* Invalid offset argument */ +var_dump( substr_count($str, "t", "") ); + +/* length too small */ +var_dump( substr_count($str, "t", 2, -20) ); + +echo "Done\n"; ?> --EXPECTF-- @@ -33,33 +37,21 @@ echo "Done\n"; Warning: substr_count() expects at least 2 parameters, 0 given in %s on line %d NULL -Notice: Undefined variable: str in %s on line %d - Warning: substr_count() expects at most 4 parameters, 5 given in %s on line %d NULL -Notice: Undefined variable: str in %s on line %d - -Warning: substr_count(): Offset should be greater than or equal to 0 in %s on line %d +Warning: substr_count(): Offset not contained in string in %s on line %d bool(false) -Notice: Undefined variable: str in %s on line %d - -Warning: substr_count(): Offset value 25 exceeds string length in %s on line %d +Warning: substr_count(): Offset not contained in string in %s on line %d bool(false) -Notice: Undefined variable: str in %s on line %d - -Warning: substr_count(): Offset value 5 exceeds string length in %s on line %d +Warning: substr_count(): Invalid length value in %s on line %d bool(false) -Notice: Undefined variable: str in %s on line %d - Warning: substr_count() expects parameter 3 to be integer, string given in %s on line %d NULL -Notice: Undefined variable: str in %s on line %d - -Warning: substr_count(): Length should be greater than 0 in %s on line %d +Warning: substr_count(): Invalid length value in %s on line %d bool(false) Done -- 2.50.1