]> granicus.if.org Git - php/commitdiff
substr_count(): Support negative values for '$offset' and '$length' parameters.
authorFrancois Laupretre <francois@php.net>
Thu, 23 Jul 2015 02:01:23 +0000 (04:01 +0200)
committerNikita Popov <nikic@php.net>
Wed, 9 Mar 2016 13:41:37 +0000 (14:41 +0100)
ext/standard/string.c
ext/standard/tests/strings/bug40754.phpt
ext/standard/tests/strings/substr_count_basic.phpt
ext/standard/tests/strings/substr_count_error.phpt

index 746bdd062024fa3e758e7a1b7fbb631ffc9bc02b..4fe4f6123c07a92d8612d23ac63c724156a4f017 100644 (file)
@@ -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;
index 6cfe47056ba5c8eb9c20096b4a3bfe5f92811c32..84e4337463c712bf5034eae91be0459277786bd2 100644 (file)
@@ -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
index f880e9481e7964de5814a101877afc875863e660..c7c96fd55bac05b14dc7fea4354467242600eeb2 100644 (file)
@@ -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
index f6924217b9d341bee28ab09e40b85b4cd8cf5cf7..881da391e658265df2d9f4b6fe722301b6011c4a 100644 (file)
@@ -4,27 +4,31 @@ Test substr_count() function (error conditions)
 <?php
 
 echo "\n*** Testing error conditions ***\n";
+$str = 'abcdefghik';
+
 /* Zero argument */
 var_dump( substr_count() );
 
 /* more than expected no. of args */
 var_dump( substr_count($str, "t", 0, 15, 30) );
        
-/* offset as negative value */
-var_dump(substr_count($str, "t", -5));
+/* offset before start */
+var_dump(substr_count($str, "t", -20));
 
 /* offset > 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