]> granicus.if.org Git - php/commitdiff
strpos()/stripos(): Add support for negative offsets
authorFrancois Laupretre <francois@php.net>
Wed, 22 Jul 2015 22:08:57 +0000 (00:08 +0200)
committerNikita Popov <nikic@php.net>
Wed, 9 Mar 2016 13:41:37 +0000 (14:41 +0100)
ext/iconv/tests/iconv_strpos.phpt
ext/mbstring/tests/bug45923.phpt
ext/standard/string.c
ext/standard/tests/strings/stripos_basic2.phpt
ext/standard/tests/strings/stripos_error.phpt
ext/standard/tests/strings/stripos_variation14.phpt
ext/standard/tests/strings/strpos.phpt
tests/lang/bug22592.phpt

index 6965f6fae185ca3136ee298a35c01c9cc7b86eab..f0f1c48f3b7e09dca6e9ddb884dd02e1271e0a7e 100644 (file)
@@ -37,7 +37,6 @@ var_dump(iconv_strpos("", "string"));
 
 ?>
 --EXPECTF--
-2: %s
 bool(false)
 2: %s
 bool(false)
index 2d184ab019dac95a79f9b73c6bdacbd0d98127e3..7819b94e13c91e77e622a110e3e4f27d5af86578 100644 (file)
@@ -6,197 +6,253 @@ Bug #45923 (mb_st[r]ripos() offset not handled correctly)
 mbstring.internal_encoding=UTF-8
 --FILE--
 <?php
-var_dump(strpos("abc abc abc", "abc", 0));
-var_dump(strpos("abc abc abc", "abc", 3));
-var_dump(strpos("abc abc abc", "abc", 6));
-var_dump(strpos("abc abc abc", "abc", 9));
-var_dump(strpos("abc abc abc", "abc", 11));
-var_dump(strpos("abc abc abc", "abc", 12));
-var_dump(strpos("abc abc abc", "abc", -1));
-var_dump(strpos("abc abc abc", "abc", -3));
-var_dump(strpos("abc abc abc", "abc", -6));
-
-var_dump(mb_strpos("●○◆ ●○◆ ●○◆", "●○◆", 0));
-var_dump(mb_strpos("●○◆ ●○◆ ●○◆", "●○◆", 3));
-var_dump(mb_strpos("●○◆ ●○◆ ●○◆", "●○◆", 6));
-var_dump(mb_strpos("●○◆ ●○◆ ●○◆", "●○◆", 9));
-var_dump(mb_strpos("●○◆ ●○◆ ●○◆", "●○◆", 11));
-var_dump(mb_strpos("●○◆ ●○◆ ●○◆", "●○◆", 12));
-var_dump(mb_strpos("●○◆ ●○◆ ●○◆", "●○◆", -1));
-var_dump(mb_strpos("●○◆ ●○◆ ●○◆", "●○◆", -3));
-var_dump(mb_strpos("●○◆ ●○◆ ●○◆", "●○◆", -6));
-
-var_dump(stripos("abc abc abc", "abc", 0));
-var_dump(stripos("abc abc abc", "abc", 3));
-var_dump(stripos("abc abc abc", "abc", 6));
-var_dump(stripos("abc abc abc", "abc", 9));
-var_dump(stripos("abc abc abc", "abc", 11));
-var_dump(stripos("abc abc abc", "abc", 12));
-var_dump(stripos("abc abc abc", "abc", -1));
-var_dump(stripos("abc abc abc", "abc", -3));
-var_dump(stripos("abc abc abc", "abc", -6));
-
-var_dump(mb_stripos("●○◆ ●○◆ ●○◆", "●○◆", 0));
-var_dump(mb_stripos("●○◆ ●○◆ ●○◆", "●○◆", 3));
-var_dump(mb_stripos("●○◆ ●○◆ ●○◆", "●○◆", 6));
-var_dump(mb_stripos("●○◆ ●○◆ ●○◆", "●○◆", 9));
-var_dump(mb_stripos("●○◆ ●○◆ ●○◆", "●○◆", 11));
-var_dump(mb_stripos("●○◆ ●○◆ ●○◆", "●○◆", 12));
-var_dump(mb_stripos("●○◆ ●○◆ ●○◆", "●○◆", -1));
-var_dump(mb_stripos("●○◆ ●○◆ ●○◆", "●○◆", -3));
-var_dump(mb_stripos("●○◆ ●○◆ ●○◆", "●○◆", -6));
-
-var_dump(strrpos("abc abc abc", "abc", 0));
-var_dump(strrpos("abc abc abc", "abc", 3));
-var_dump(strrpos("abc abc abc", "abc", 6));
-var_dump(strrpos("abc abc abc", "abc", 9));
-var_dump(strrpos("abc abc abc", "abc", 11));
-var_dump(strrpos("abc abc abc", "abc", 12));
-var_dump(strrpos("abc abc abc", "abc", -1));
-var_dump(strrpos("abc abc abc", "abc", -3));
-var_dump(strrpos("abc abc abc", "abc", -6));
-
-var_dump(mb_strrpos("●○◆ ●○◆ ●○◆", "●○◆", 0));
-var_dump(mb_strrpos("●○◆ ●○◆ ●○◆", "●○◆", 3));
-var_dump(mb_strrpos("●○◆ ●○◆ ●○◆", "●○◆", 6));
-var_dump(mb_strrpos("●○◆ ●○◆ ●○◆", "●○◆", 9));
-var_dump(mb_strrpos("●○◆ ●○◆ ●○◆", "●○◆", 11));
-var_dump(mb_strrpos("●○◆ ●○◆ ●○◆", "●○◆", 12));
-var_dump(mb_strrpos("●○◆ ●○◆ ●○◆", "●○◆", -1));
-var_dump(mb_strrpos("●○◆ ●○◆ ●○◆", "●○◆", -3));
-var_dump(mb_strrpos("●○◆ ●○◆ ●○◆", "●○◆", -6));
-
-var_dump(strripos("abc abc abc", "abc", 0));
-var_dump(strripos("abc abc abc", "abc", 3));
-var_dump(strripos("abc abc abc", "abc", 6));
-var_dump(strripos("abc abc abc", "abc", 9));
-var_dump(strripos("abc abc abc", "abc", 11));
-var_dump(strripos("abc abc abc", "abc", 12));
-var_dump(strripos("abc abc abc", "abc", -1));
-var_dump(strripos("abc abc abc", "abc", -3));
-var_dump(strripos("abc abc abc", "abc", -6));
-
-var_dump(mb_strripos("●○◆ ●○◆ ●○◆", "●○◆", 0));
-var_dump(mb_strripos("●○◆ ●○◆ ●○◆", "●○◆", 3));
-var_dump(mb_strripos("●○◆ ●○◆ ●○◆", "●○◆", 6));
-var_dump(mb_strripos("●○◆ ●○◆ ●○◆", "●○◆", 9));
-var_dump(mb_strripos("●○◆ ●○◆ ●○◆", "●○◆", 11));
-var_dump(mb_strripos("●○◆ ●○◆ ●○◆", "●○◆", 12));
-var_dump(mb_strripos("●○◆ ●○◆ ●○◆", "●○◆", -1));
-var_dump(mb_strripos("●○◆ ●○◆ ●○◆", "●○◆", -3));
-var_dump(mb_strripos("●○◆ ●○◆ ●○◆", "●○◆", -6));
 
+function section($func, $haystack, $needle)
+{
+       echo "\n------- $func -----------\n\n";
+       foreach(array(0, 3, 6, 9, 11, 12, -1, -3, -6, -20) as $offset) {
+               echo "> Offset: $offset\n";
+               var_dump($func($haystack,$needle,$offset));
+       }
+}
+
+section('strpos'     , "abc abc abc"  , "abc");
+section('mb_strpos'  , "●○◆ ●○◆ ●○◆", "●○◆");
+
+section('stripos'    , "abc abc abc"  , "abc");
+section('mb_stripos' , "●○◆ ●○◆ ●○◆", "●○◆");
+
+section('strrpos'    , "abc abc abc"  , "abc");
+section('mb_strrpos' , "●○◆ ●○◆ ●○◆", "●○◆");
+
+section('strripos'   , "abc abc abc"  , "abc");
+section('mb_strripos', "●○◆ ●○◆ ●○◆", "●○◆");
 ?>
 --EXPECTF--
+------- strpos -----------
+
+> Offset: 0
 int(0)
+> Offset: 3
 int(4)
+> Offset: 6
 int(8)
+> Offset: 9
 bool(false)
+> Offset: 11
 bool(false)
+> Offset: 12
 
 Warning: strpos(): Offset not contained in string in %s on line %d
 bool(false)
-
-Warning: strpos(): Offset not contained in string in %s on line %d
+> Offset: -1
 bool(false)
+> Offset: -3
+int(8)
+> Offset: -6
+int(8)
+> Offset: -20
 
 Warning: strpos(): Offset not contained in string in %s on line %d
 bool(false)
 
-Warning: strpos(): Offset not contained in string in %s on line %d
-bool(false)
+------- mb_strpos -----------
+
+> Offset: 0
 int(0)
+> Offset: 3
 int(4)
+> Offset: 6
 int(8)
+> Offset: 9
 bool(false)
+> Offset: 11
 bool(false)
+> Offset: 12
 
 Warning: mb_strpos(): Offset not contained in string in %s on line %d
 bool(false)
+> Offset: -1
 
 Warning: mb_strpos(): Offset not contained in string in %s on line %d
 bool(false)
+> Offset: -3
 
 Warning: mb_strpos(): Offset not contained in string in %s on line %d
 bool(false)
+> Offset: -6
 
 Warning: mb_strpos(): Offset not contained in string in %s on line %d
 bool(false)
+> Offset: -20
+
+Warning: mb_strpos(): Offset not contained in string in %s on line %d
+bool(false)
+
+------- stripos -----------
+
+> Offset: 0
 int(0)
+> Offset: 3
 int(4)
+> Offset: 6
 int(8)
+> Offset: 9
 bool(false)
+> Offset: 11
 bool(false)
+> Offset: 12
 
 Warning: stripos(): Offset not contained in string in %s on line %d
 bool(false)
-
-Warning: stripos(): Offset not contained in string in %s on line %d
+> Offset: -1
 bool(false)
+> Offset: -3
+int(8)
+> Offset: -6
+int(8)
+> Offset: -20
 
 Warning: stripos(): Offset not contained in string in %s on line %d
 bool(false)
 
-Warning: stripos(): Offset not contained in string in %s on line %d
-bool(false)
+------- mb_stripos -----------
+
+> Offset: 0
 int(0)
+> Offset: 3
 int(4)
+> Offset: 6
 int(8)
+> Offset: 9
+bool(false)
+> Offset: 11
 bool(false)
+> Offset: 12
+
+Warning: mb_stripos(): Offset not contained in string in %s on line %d
 bool(false)
+> Offset: -1
 
 Warning: mb_stripos(): Offset not contained in string in %s on line %d
 bool(false)
+> Offset: -3
 
 Warning: mb_stripos(): Offset not contained in string in %s on line %d
 bool(false)
+> Offset: -6
 
 Warning: mb_stripos(): Offset not contained in string in %s on line %d
 bool(false)
+> Offset: -20
 
 Warning: mb_stripos(): Offset not contained in string in %s on line %d
 bool(false)
+
+------- strrpos -----------
+
+> Offset: 0
 int(8)
+> Offset: 3
 int(8)
+> Offset: 6
 int(8)
+> Offset: 9
 bool(false)
+> Offset: 11
 bool(false)
+> Offset: 12
 
 Warning: strrpos(): Offset is greater than the length of haystack string in %s on line %d
 bool(false)
+> Offset: -1
 int(8)
+> Offset: -3
 int(8)
+> Offset: -6
 int(4)
+> Offset: -20
+
+Warning: strrpos(): Offset is greater than the length of haystack string in %s on line %d
+bool(false)
+
+------- mb_strrpos -----------
+
+> Offset: 0
 int(8)
+> Offset: 3
 int(8)
+> Offset: 6
 int(8)
+> Offset: 9
 bool(false)
+> Offset: 11
 bool(false)
+> Offset: 12
 
 Warning: mb_strrpos(): Offset is greater than the length of haystack string in %s on line %d
 bool(false)
+> Offset: -1
 int(8)
+> Offset: -3
 int(8)
+> Offset: -6
 int(4)
+> Offset: -20
+
+Warning: mb_strrpos(): Offset is greater than the length of haystack string in %s on line %d
+bool(false)
+
+------- strripos -----------
+
+> Offset: 0
 int(8)
+> Offset: 3
 int(8)
+> Offset: 6
 int(8)
+> Offset: 9
 bool(false)
+> Offset: 11
 bool(false)
+> Offset: 12
 
 Warning: strripos(): Offset is greater than the length of haystack string in %s on line %d
 bool(false)
+> Offset: -1
 int(8)
+> Offset: -3
 int(8)
+> Offset: -6
 int(4)
+> Offset: -20
+
+Warning: strripos(): Offset is greater than the length of haystack string in %s on line %d
+bool(false)
+
+------- mb_strripos -----------
+
+> Offset: 0
 int(8)
+> Offset: 3
 int(8)
+> Offset: 6
 int(8)
+> Offset: 9
 bool(false)
+> Offset: 11
 bool(false)
+> Offset: 12
 
 Warning: mb_strripos(): Offset is greater than the length of haystack string in %s on line %d
 bool(false)
+> Offset: -1
 int(8)
+> Offset: -3
 int(8)
+> Offset: -6
 int(4)
+> Offset: -20
+
+Warning: mb_strripos(): Offset is greater than the length of haystack string in %s on line %d
+bool(false)
\ No newline at end of file
index 43778309865a772f578e041e1d74a8a66182d15b..746bdd062024fa3e758e7a1b7fbb631ffc9bc02b 100644 (file)
@@ -1968,6 +1968,9 @@ PHP_FUNCTION(strpos)
        ZEND_PARSE_PARAMETERS_END();
 #endif
 
+       if (offset < 0) {
+               offset += (zend_long)ZSTR_LEN(haystack);
+       }
        if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) {
                php_error_docref(NULL, E_WARNING, "Offset not contained in string");
                RETURN_FALSE;
@@ -2018,6 +2021,9 @@ PHP_FUNCTION(stripos)
                return;
        }
 
+       if (offset < 0) {
+               offset += (zend_long)ZSTR_LEN(haystack);
+       }
        if (offset < 0 || (size_t)offset > ZSTR_LEN(haystack)) {
                php_error_docref(NULL, E_WARNING, "Offset not contained in string");
                RETURN_FALSE;
index 3022bae168052177d514d943d6160e9c158ade94..226d3f61d28349e3c2b10dc7ff3146547e59cd8e 100644 (file)
@@ -18,6 +18,9 @@ var_dump( stripos("Hello, World", "Hello", 0) );
 var_dump( stripos("Hello, World", 'Hello', 1) );
 var_dump( stripos('Hello, World', 'WORLD', 1) );
 var_dump( stripos('Hello, World', "WoRld", 5) );
+var_dump( stripos('Hello, World', "WoRld", -6) );
+var_dump( stripos('Hello, World', "WoRld", -3) );
+var_dump( stripos('Hello, World', "WoRld", -12) );
 
 //heredoc string for haystack & needle, with various offsets
 var_dump( stripos($heredoc_str, "Hello, World", 0) );
@@ -25,12 +28,19 @@ var_dump( stripos($heredoc_str, 'Hello', 0) );
 var_dump( stripos($heredoc_str, 'Hello', 1) );
 var_dump( stripos($heredoc_str, $heredoc_str, 0) );
 var_dump( stripos($heredoc_str, $heredoc_str, 1) );
+var_dump( stripos($heredoc_str, $heredoc_str, -strlen($heredoc_str)) );
+var_dump( stripos($heredoc_str, $heredoc_str, -strlen($heredoc_str)+1) );
 
 //various offsets
 var_dump( stripos("Hello, World", "o", 3) );
 var_dump( stripos("Hello, World", "O", 5) );
 var_dump( stripos("Hello, World", "o", 6) );
 var_dump( stripos("Hello, World", "o", 10) );
+var_dump( stripos("Hello, World", "o", -7) );
+var_dump( stripos("Hello, World", "o", -8) );
+var_dump( stripos("Hello, World", "o", -10) );
+var_dump( stripos("Hello, World", "o", -4) );
+var_dump( stripos("Hello, World", "o", -3) );
 echo "*** Done ***";
 ?>
 --EXPECTF--
@@ -40,13 +50,23 @@ int(0)
 bool(false)
 int(7)
 int(7)
+int(7)
+bool(false)
+int(7)
 int(0)
 int(0)
 bool(false)
 int(0)
 bool(false)
+int(0)
+bool(false)
 int(4)
 int(8)
 int(8)
 bool(false)
+int(8)
+int(4)
+int(4)
+int(8)
+bool(false)
 *** Done ***
index ef6ad9e6ec2c221c22c99a02ec2756d1c34b3a10..c59473046ddbe8da72f2ece60c0522f256819a9e 100644 (file)
@@ -16,6 +16,13 @@ var_dump( stripos("String") );
 
 echo "\n-- With more than expected number of arguments --";
 var_dump( stripos("string", "String", 1, 'extra_arg') );
+
+echo "\n-- Offset beyond the end of the string --";
+var_dump( stripos("Hello World", "o", 12) );
+
+echo "\n-- Offset before the start of the string --";
+var_dump( stripos("Hello World", "o", -12) );
+
 echo "*** Done ***";
 ?>
 --EXPECTF--
@@ -32,4 +39,12 @@ NULL
 -- With more than expected number of arguments --
 Warning: stripos() expects at most 3 parameters, 4 given in %s on line %d
 NULL
+
+-- Offset beyond the end of the string --
+Warning: stripos(): Offset not contained in string in %s on line %d
+bool(false)
+
+-- Offset before the start of the string --
+Warning: stripos(): Offset not contained in string in %s on line %d
+bool(false)
 *** Done ***
index aabf0e62ea3ef37ed8c86a29d8eb90225b66de55..3339e2f27ec879761492526a5235fafcd25bc233 100644 (file)
@@ -1,7 +1,5 @@
 --TEST--
 Test stripos() function : usage variations - unexpected inputs for 'offset' argument
---SKIPIF--
-<?php if (PHP_INT_SIZE != 8) die("skip this test is for 64-bit only");
 --FILE--
 <?php
 /* Prototype  : int stripos ( string $haystack, string $needle [, int $offset] );
@@ -37,7 +35,7 @@ $offsets =  array (
   // float values
   1.5,
   -1.5,
-  1.5e10,
+  1.5e6,
   1.6E-10,
   .5,
 
@@ -91,8 +89,6 @@ echo "*** Done ***";
 -- Iteration 1 --
 int(6)
 -- Iteration 2 --
-
-Warning: stripos(): Offset not contained in string in %s on line %d
 bool(false)
 -- Iteration 3 --
 
index 36854d1b372d6f6cc50d5575ccffc66b09e66567..f5d60a69b58cdf45b3c525faaf9032e086d2fc88 100644 (file)
Binary files a/ext/standard/tests/strings/strpos.phpt and b/ext/standard/tests/strings/strpos.phpt differ
index 270584185f91e43625f587f40ca413b52fcdb970..4614efc1692b768aa980926c6bb2a5117bcfc0ad 100644 (file)
@@ -32,7 +32,8 @@ var_dump($result);
 $e = $result[1] = $result[6];
 var_dump($result);
 var_dump($a, $b, $c, $d, $e);
-$result[-1] = 'a';
+$result[0] = $result[-4] = $result[-1] = 'a';
+var_dump($result);
 ?>
 --EXPECT--
 string(5) "* *-*"
@@ -50,4 +51,4 @@ string(1) "s"
 string(1) "4"
 string(1) "5"
 string(1) "5"
-[Illegal string offset:  -1]
+string(9) "a54s4a50a"