From: Francois Laupretre Date: Wed, 22 Jul 2015 22:08:57 +0000 (+0200) Subject: strpos()/stripos(): Add support for negative offsets X-Git-Tag: php-7.1.0alpha1~515 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=56fce8990f8872f9d36a4f1ea9a5a14bee2ad016;p=php strpos()/stripos(): Add support for negative offsets --- diff --git a/ext/iconv/tests/iconv_strpos.phpt b/ext/iconv/tests/iconv_strpos.phpt index 6965f6fae1..f0f1c48f3b 100644 --- a/ext/iconv/tests/iconv_strpos.phpt +++ b/ext/iconv/tests/iconv_strpos.phpt @@ -37,7 +37,6 @@ var_dump(iconv_strpos("", "string")); ?> --EXPECTF-- -2: %s bool(false) 2: %s bool(false) diff --git a/ext/mbstring/tests/bug45923.phpt b/ext/mbstring/tests/bug45923.phpt index 2d184ab019..7819b94e13 100644 --- a/ext/mbstring/tests/bug45923.phpt +++ b/ext/mbstring/tests/bug45923.phpt @@ -6,197 +6,253 @@ Bug #45923 (mb_st[r]ripos() offset not handled correctly) mbstring.internal_encoding=UTF-8 --FILE-- 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 diff --git a/ext/standard/string.c b/ext/standard/string.c index 4377830986..746bdd0620 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -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; diff --git a/ext/standard/tests/strings/stripos_basic2.phpt b/ext/standard/tests/strings/stripos_basic2.phpt index 3022bae168..226d3f61d2 100644 --- a/ext/standard/tests/strings/stripos_basic2.phpt +++ b/ext/standard/tests/strings/stripos_basic2.phpt @@ -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 *** diff --git a/ext/standard/tests/strings/stripos_error.phpt b/ext/standard/tests/strings/stripos_error.phpt index ef6ad9e6ec..c59473046d 100644 --- a/ext/standard/tests/strings/stripos_error.phpt +++ b/ext/standard/tests/strings/stripos_error.phpt @@ -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 *** diff --git a/ext/standard/tests/strings/stripos_variation14.phpt b/ext/standard/tests/strings/stripos_variation14.phpt index aabf0e62ea..3339e2f27e 100644 --- a/ext/standard/tests/strings/stripos_variation14.phpt +++ b/ext/standard/tests/strings/stripos_variation14.phpt @@ -1,7 +1,5 @@ --TEST-- Test stripos() function : usage variations - unexpected inputs for 'offset' argument ---SKIPIF-- - --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"