summaryrefslogtreecommitdiff
path: root/ext/standard/string.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-09-22 10:42:24 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-09-22 10:46:50 +0200
commit5d9ab53a5d53f11a18ae11ed31b17ff87c8d52a7 (patch)
treef3de54137489c2fdbd135f708de6c4191d486518 /ext/standard/string.c
parent12e772f18dcf0116935e5fad8443a717e4ffde8e (diff)
downloadphp-git-5d9ab53a5d53f11a18ae11ed31b17ff87c8d52a7.tar.gz
Check string bounds in strspn/strcspn
strspn/strcspn are string search functions, and as such should throw ValueError on out-of-bounds offsets, just like strpos etc do.
Diffstat (limited to 'ext/standard/string.c')
-rw-r--r--ext/standard/string.c37
1 files changed, 16 insertions, 21 deletions
diff --git a/ext/standard/string.c b/ext/standard/string.c
index a3f547c556..35404cb3fd 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -258,33 +258,28 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
Z_PARAM_LONG_OR_NULL(len, len_is_null)
ZEND_PARSE_PARAMETERS_END();
- if (len_is_null) {
- len = ZSTR_LEN(s11);
- }
-
- /* look at substr() function for more information */
-
if (start < 0) {
start += (zend_long)ZSTR_LEN(s11);
- if (start < 0) {
- start = 0;
- }
- } else if ((size_t)start > ZSTR_LEN(s11)) {
- RETURN_FALSE;
+ }
+ if (start < 0 || (size_t)start > ZSTR_LEN(s11)) {
+ zend_argument_value_error(3, "must be contained in argument #1 ($str)");
+ RETURN_THROWS();
}
- if (len < 0) {
- len += (ZSTR_LEN(s11) - start);
+ size_t remain_len = ZSTR_LEN(s11) - start;
+ if (!len_is_null) {
if (len < 0) {
- 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();
+ }
+ } else {
+ len = remain_len;
}
- if (len > (zend_long)ZSTR_LEN(s11) - start) {
- len = ZSTR_LEN(s11) - start;
- }
-
- if(len == 0) {
+ if (len == 0) {
RETURN_LONG(0);
}
@@ -293,13 +288,13 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) /
ZSTR_VAL(s22) /*str2_start*/,
ZSTR_VAL(s11) + start + len /*str1_end*/,
ZSTR_VAL(s22) + ZSTR_LEN(s22) /*str2_end*/));
- } else if (behavior == STR_STRCSPN) {
+ } else {
+ ZEND_ASSERT(behavior == STR_STRCSPN);
RETURN_LONG(php_strcspn(ZSTR_VAL(s11) + start /*str1_start*/,
ZSTR_VAL(s22) /*str2_start*/,
ZSTR_VAL(s11) + start + len /*str1_end*/,
ZSTR_VAL(s22) + ZSTR_LEN(s22) /*str2_end*/));
}
-
}
/* }}} */