Skip to content

Commit

Permalink
Don't throw for out of bounds offsets in strspn()
Browse files Browse the repository at this point in the history
Make strspn($str1, $str2, $offset, $length) behaviorally
equivalent to strspn(substr($str1, $offset, $length), $str2)
by not throwing for out of bounds offset.

There have been two reports that this change cause issues,
including bug #80285.
  • Loading branch information
nikic committed Oct 27, 2020
1 parent 76e4bf3 commit d776d25
Show file tree
Hide file tree
Showing 8 changed files with 5,126 additions and 5,155 deletions.
2 changes: 0 additions & 2 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -532,8 +532,6 @@ PHP 8.0 UPGRADE NOTES
. parse_str() can no longer be used without specifying a result array.
. fgetss() has been removed.
. The string.strip_tags filter has been removed.
. strspn() and strcspn() now throw a ValueError when the start or length
argument exceed the bounds of the string.
. The needle argument of strpos(), strrpos(), stripos(), strripos(), strstr(),
strchr(), strrchr(), and stristr() will now always be interpreted as a
string. Previously non-string needles were interpreted as an ASCII code
Expand Down
23 changes: 13 additions & 10 deletions ext/standard/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,22 +258,25 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
Z_PARAM_LONG_OR_NULL(len, len_is_null)
ZEND_PARSE_PARAMETERS_END();

size_t remain_len = ZSTR_LEN(s11);
if (start < 0) {
start += (zend_long)ZSTR_LEN(s11);
}
if (start < 0 || (size_t)start > ZSTR_LEN(s11)) {
zend_argument_value_error(3, "must be contained in argument #1 ($str)");
RETURN_THROWS();
start += remain_len;
if (start < 0) {
start = 0;
}
} else if ((size_t) start > remain_len) {
start = remain_len;
}

size_t remain_len = ZSTR_LEN(s11) - start;
remain_len -= start;
if (!len_is_null) {
if (len < 0) {
len += remain_len;
}
if (len < 0 || (size_t)len > remain_len) {
zend_argument_value_error(4, "must be contained in argument #1 ($str)");
RETURN_THROWS();
if (len < 0) {
len = 0;
}
} else if ((size_t) len > remain_len) {
len = remain_len;
}
} else {
len = remain_len;
Expand Down
18 changes: 4 additions & 14 deletions ext/standard/tests/strings/bug40754.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,8 @@ $v = 2147483647;

var_dump(substr("abcde", 1, $v));
var_dump(substr_replace("abcde", "x", $v, $v));

try {
var_dump(strspn("abcde", "abc", $v, $v));
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

try {
var_dump(strcspn("abcde", "abc", $v, $v));
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}
var_dump(strspn("abcde", "abc", $v, $v));
var_dump(strcspn("abcde", "abc", $v, $v));

try {
var_dump(substr_count("abcde", "abc", $v, $v));
Expand Down Expand Up @@ -88,8 +78,8 @@ var_dump(substr("abcde", $v, $v));
--EXPECT--
string(4) "bcde"
string(6) "abcdex"
strspn(): Argument #3 ($offset) must be contained in argument #1 ($str)
strcspn(): Argument #3 ($offset) must be contained in argument #1 ($str)
int(0)
int(0)
substr_count(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
substr_compare(): Argument #3 ($offset) must be contained in argument #1 ($main_str)
stripos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)
Expand Down
8 changes: 2 additions & 6 deletions ext/standard/tests/strings/strcspn.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,12 @@ var_dump($b);
var_dump(strcspn($a,$b));
var_dump(strcspn($a,$b,9));
var_dump(strcspn($a,$b,9,6));
try {
var_dump(strcspn('a', 'B', 1, 2147483647));
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
var_dump(strcspn('a', 'B', 1, 2147483647));
?>
--EXPECT--
string(25) "22222222aaaa bbb1111 cccc"
string(4) "1234"
int(0)
int(7)
int(6)
strcspn(): Argument #4 ($length) must be contained in argument #1 ($str)
int(0)

0 comments on commit d776d25

Please sign in to comment.