diff options
Diffstat (limited to 'ext/standard/string.c')
| -rw-r--r-- | ext/standard/string.c | 459 |
1 files changed, 114 insertions, 345 deletions
diff --git a/ext/standard/string.c b/ext/standard/string.c index fc234aafad..047f5454d6 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | @@ -236,15 +234,11 @@ PHP_FUNCTION(bin2hex) result = php_bin2hex((unsigned char *)ZSTR_VAL(data), ZSTR_LEN(data)); - if (!result) { - RETURN_FALSE; - } - RETURN_STR(result); } /* }}} */ -/* {{{ proto string hex2bin(string data) +/* {{{ proto string|false hex2bin(string data) Converts the hex representation of data to binary */ PHP_FUNCTION(hex2bin) { @@ -328,7 +322,7 @@ static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior) / } /* }}} */ -/* {{{ proto int strspn(string str, string mask [, int start [, int len]]) +/* {{{ proto int|false strspn(string str, string mask [, int start [, int len]]) Finds length of initial segment consisting entirely of characters found in mask. If start or/and length is provided works like strspn(substr($s,$start,$len),$good_chars) */ PHP_FUNCTION(strspn) { @@ -336,7 +330,7 @@ PHP_FUNCTION(strspn) } /* }}} */ -/* {{{ proto int strcspn(string str, string mask [, int start [, int len]]) +/* {{{ proto int|false strcspn(string str, string mask [, int start [, int len]]) Finds length of initial segment consisting entirely of characters not found in mask. If start or/and length is provide works like strcspn(substr($s,$start,$len),$bad_chars) */ PHP_FUNCTION(strcspn) { @@ -514,7 +508,7 @@ PHP_MINIT_FUNCTION(nl_langinfo) } /* }}} */ -/* {{{ proto string nl_langinfo(int item) +/* {{{ proto string|false nl_langinfo(int item) Query language and locale information */ PHP_FUNCTION(nl_langinfo) { @@ -937,13 +931,13 @@ PHP_FUNCTION(wordwrap) } if (breakchar_len == 0) { - php_error_docref(NULL, E_WARNING, "Break string cannot be empty"); - RETURN_FALSE; + zend_throw_error(NULL, "Break string cannot be empty"); + return; } if (linelength == 0 && docut) { - php_error_docref(NULL, E_WARNING, "Can't force cut when width is zero"); - RETURN_FALSE; + zend_throw_error(NULL, "Can't force cut when width is zero"); + return; } /* Special case for a single-character break as it needs no @@ -1149,14 +1143,14 @@ PHP_FUNCTION(explode) ZEND_PARSE_PARAMETERS_END(); if (ZSTR_LEN(delim) == 0) { - php_error_docref(NULL, E_WARNING, "Empty delimiter"); - RETURN_FALSE; + zend_throw_error(NULL, "Empty delimiter"); + return; } array_init(return_value); if (ZSTR_LEN(str) == 0) { - if (limit >= 0) { + if (limit >= 0) { ZVAL_EMPTY_STRING(&tmp); zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp); } @@ -1281,7 +1275,7 @@ PHP_FUNCTION(implode) if (arg2 == NULL) { if (Z_TYPE_P(arg1) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "Argument must be an array"); + zend_type_error("Argument must be an array"); return; } @@ -1298,7 +1292,7 @@ PHP_FUNCTION(implode) glue = zval_get_tmp_string(arg1, &tmp_glue); pieces = arg2; } else { - php_error_docref(NULL, E_WARNING, "Invalid arguments passed"); + zend_type_error("Invalid arguments passed"); return; } } @@ -1310,7 +1304,7 @@ PHP_FUNCTION(implode) #define STRTOK_TABLE(p) BG(strtok_table)[(unsigned char) *p] -/* {{{ proto string strtok([string str,] string token) +/* {{{ proto string|false strtok([string str,] string token) Tokenize a string */ PHP_FUNCTION(strtok) { @@ -1648,7 +1642,7 @@ PHP_FUNCTION(dirname) ZSTR_LEN(ret) = zend_dirname(ZSTR_VAL(ret), str_len); #endif } else if (levels < 1) { - php_error_docref(NULL, E_WARNING, "Invalid argument, levels must be >= 1"); + zend_throw_error(NULL, "Invalid argument, levels must be >= 1"); zend_string_efree(ret); return; } else { @@ -1666,7 +1660,7 @@ PHP_FUNCTION(dirname) } /* }}} */ -/* {{{ proto array pathinfo(string path[, int options]) +/* {{{ proto array|string pathinfo(string path[, int options]) Returns information about a certain string */ PHP_FUNCTION(pathinfo) { @@ -1798,76 +1792,28 @@ PHPAPI size_t php_strcspn(char *s1, char *s2, char *s1_end, char *s2_end) } /* }}} */ -/* {{{ php_needle_char - */ -static int php_needle_char(zval *needle, char *target) -{ - switch (Z_TYPE_P(needle)) { - case IS_LONG: - *target = (char)Z_LVAL_P(needle); - return SUCCESS; - case IS_NULL: - case IS_FALSE: - *target = '\0'; - return SUCCESS; - case IS_TRUE: - *target = '\1'; - return SUCCESS; - case IS_DOUBLE: - case IS_OBJECT: - *target = (char) zval_get_long(needle); - return SUCCESS; - default: - php_error_docref(NULL, E_WARNING, "needle is not a string or an integer"); - return FAILURE; - } -} -/* }}} */ - -/* {{{ proto string stristr(string haystack, string needle[, bool part]) +/* {{{ proto string|false stristr(string haystack, string needle[, bool part]) Finds first occurrence of a string within another, case insensitive */ PHP_FUNCTION(stristr) { - zval *needle; - zend_string *haystack; + zend_string *haystack, *needle; const char *found = NULL; size_t found_offset; char *haystack_dup; - char needle_char[2]; + char *orig_needle; zend_bool part = 0; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(needle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_BOOL(part) ZEND_PARSE_PARAMETERS_END(); haystack_dup = estrndup(ZSTR_VAL(haystack), ZSTR_LEN(haystack)); - - if (Z_TYPE_P(needle) == IS_STRING) { - char *orig_needle; - if (!Z_STRLEN_P(needle)) { - php_error_docref(NULL, E_WARNING, "Empty needle"); - efree(haystack_dup); - RETURN_FALSE; - } - orig_needle = estrndup(Z_STRVAL_P(needle), Z_STRLEN_P(needle)); - found = php_stristr(haystack_dup, orig_needle, ZSTR_LEN(haystack), Z_STRLEN_P(needle)); - efree(orig_needle); - } else { - if (php_needle_char(needle, needle_char) != SUCCESS) { - efree(haystack_dup); - RETURN_FALSE; - } - needle_char[1] = 0; - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - found = php_stristr(haystack_dup, needle_char, ZSTR_LEN(haystack), 1); - } + orig_needle = estrndup(ZSTR_VAL(needle), ZSTR_LEN(needle)); + found = php_stristr(haystack_dup, orig_needle, ZSTR_LEN(haystack), ZSTR_LEN(needle)); + efree(orig_needle); if (found) { found_offset = found - haystack_dup; @@ -1884,43 +1830,23 @@ PHP_FUNCTION(stristr) } /* }}} */ -/* {{{ proto string strstr(string haystack, string needle[, bool part]) +/* {{{ proto string|false strstr(string haystack, string needle[, bool part]) Finds first occurrence of a string within another */ PHP_FUNCTION(strstr) { - zval *needle; - zend_string *haystack; + zend_string *haystack, *needle; const char *found = NULL; - char needle_char[2]; zend_long found_offset; zend_bool part = 0; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(needle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_BOOL(part) ZEND_PARSE_PARAMETERS_END(); - if (Z_TYPE_P(needle) == IS_STRING) { - if (!Z_STRLEN_P(needle)) { - php_error_docref(NULL, E_WARNING, "Empty needle"); - RETURN_FALSE; - } - - found = php_memnstr(ZSTR_VAL(haystack), Z_STRVAL_P(needle), Z_STRLEN_P(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); - } else { - if (php_needle_char(needle, needle_char) != SUCCESS) { - RETURN_FALSE; - } - needle_char[1] = 0; - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - found = php_memnstr(ZSTR_VAL(haystack), needle_char, 1, ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); - } + found = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); if (found) { found_offset = found - ZSTR_VAL(haystack); @@ -1938,19 +1864,17 @@ PHP_FUNCTION(strstr) An alias for strstr */ /* }}} */ -/* {{{ proto int strpos(string haystack, string needle [, int offset]) +/* {{{ proto int|false strpos(string haystack, string needle [, int offset]) Finds position of first occurrence of a string within another */ PHP_FUNCTION(strpos) { - zval *needle; - zend_string *haystack; + zend_string *haystack, *needle; const char *found = NULL; - char needle_char[2]; - zend_long offset = 0; + zend_long offset = 0; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(needle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_LONG(offset) ZEND_PARSE_PARAMETERS_END(); @@ -1963,31 +1887,9 @@ PHP_FUNCTION(strpos) RETURN_FALSE; } - if (Z_TYPE_P(needle) == IS_STRING) { - if (!Z_STRLEN_P(needle)) { - php_error_docref(NULL, E_WARNING, "Empty needle"); - RETURN_FALSE; - } - - found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset, - Z_STRVAL_P(needle), - Z_STRLEN_P(needle), - ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); - } else { - if (php_needle_char(needle, needle_char) != SUCCESS) { - RETURN_FALSE; - } - needle_char[1] = 0; - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset, - needle_char, - 1, - ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); - } + found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset, + ZSTR_VAL(needle), ZSTR_LEN(needle), + ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); if (found) { RETURN_LONG(found - ZSTR_VAL(haystack)); @@ -1997,20 +1899,18 @@ PHP_FUNCTION(strpos) } /* }}} */ -/* {{{ proto int stripos(string haystack, string needle [, int offset]) +/* {{{ proto int|false stripos(string haystack, string needle [, int offset]) Finds position of first occurrence of a string within another, case insensitive */ PHP_FUNCTION(stripos) { const char *found = NULL; - zend_string *haystack; + zend_string *haystack, *needle; zend_long offset = 0; - char needle_char[2]; - zval *needle; zend_string *needle_dup = NULL, *haystack_dup; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(needle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_LONG(offset) ZEND_PARSE_PARAMETERS_END(); @@ -2023,37 +1923,14 @@ PHP_FUNCTION(stripos) RETURN_FALSE; } - if (ZSTR_LEN(haystack) == 0) { + if (ZSTR_LEN(needle) > ZSTR_LEN(haystack)) { RETURN_FALSE; } - if (Z_TYPE_P(needle) == IS_STRING) { - if (Z_STRLEN_P(needle) == 0 || Z_STRLEN_P(needle) > ZSTR_LEN(haystack)) { - RETURN_FALSE; - } - - haystack_dup = php_string_tolower(haystack); - needle_dup = php_string_tolower(Z_STR_P(needle)); - found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset, - ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack)); - } else { - if (php_needle_char(needle, needle_char) != SUCCESS) { - RETURN_FALSE; - } - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - haystack_dup = php_string_tolower(haystack); - needle_char[0] = tolower(needle_char[0]); - needle_char[1] = '\0'; - found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset, - needle_char, - sizeof(needle_char) - 1, - ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack)); - } - + haystack_dup = php_string_tolower(haystack); + needle_dup = php_string_tolower(needle); + found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset, + ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack)); if (found) { RETVAL_LONG(found - ZSTR_VAL(haystack_dup)); @@ -2062,72 +1939,48 @@ PHP_FUNCTION(stripos) } zend_string_release_ex(haystack_dup, 0); - if (needle_dup) { - zend_string_release_ex(needle_dup, 0); - } + zend_string_release_ex(needle_dup, 0); } /* }}} */ -/* {{{ proto int strrpos(string haystack, string needle [, int offset]) +/* {{{ proto int|false strrpos(string haystack, string needle [, int offset]) Finds position of last occurrence of a string within another string */ PHP_FUNCTION(strrpos) { - zval *zneedle; + zend_string *needle; zend_string *haystack; - size_t needle_len; zend_long offset = 0; - char ord_needle[2]; - const char *p, *e, *found, *needle; + const char *p, *e, *found; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(zneedle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_LONG(offset) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - if (Z_TYPE_P(zneedle) == IS_STRING) { - needle = Z_STRVAL_P(zneedle); - needle_len = Z_STRLEN_P(zneedle); - } else { - if (php_needle_char(zneedle, ord_needle) != SUCCESS) { - RETURN_FALSE; - } - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - ord_needle[1] = '\0'; - needle = ord_needle; - needle_len = 1; - } - - if ((ZSTR_LEN(haystack) == 0) || (needle_len == 0)) { - RETURN_FALSE; - } - if (offset >= 0) { if ((size_t)offset > ZSTR_LEN(haystack)) { - php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string"); + php_error_docref(NULL, E_WARNING, "Offset not contained in string"); RETURN_FALSE; } p = ZSTR_VAL(haystack) + (size_t)offset; e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack); } else { if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) { - php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string"); + php_error_docref(NULL, E_WARNING, "Offset not contained in string"); RETURN_FALSE; } + p = ZSTR_VAL(haystack); - if ((size_t)-offset < needle_len) { + if ((size_t)-offset < ZSTR_LEN(needle)) { e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack); } else { - e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + offset + needle_len; + e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + offset + ZSTR_LEN(needle); } } - if ((found = zend_memnrstr(p, needle, needle_len, e))) { + if ((found = zend_memnrstr(p, ZSTR_VAL(needle), ZSTR_LEN(needle), e))) { RETURN_LONG(found - ZSTR_VAL(haystack)); } @@ -2135,54 +1988,30 @@ PHP_FUNCTION(strrpos) } /* }}} */ -/* {{{ proto int strripos(string haystack, string needle [, int offset]) +/* {{{ proto int|false strripos(string haystack, string needle [, int offset]) Finds position of last occurrence of a string within another string */ PHP_FUNCTION(strripos) { - zval *zneedle; zend_string *needle; zend_string *haystack; zend_long offset = 0; const char *p, *e, *found; - zend_string *needle_dup, *haystack_dup, *ord_needle = NULL; - ALLOCA_FLAG(use_heap); + zend_string *needle_dup, *haystack_dup; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(zneedle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_LONG(offset) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - ZSTR_ALLOCA_ALLOC(ord_needle, 1, use_heap); - if (Z_TYPE_P(zneedle) == IS_STRING) { - needle = Z_STR_P(zneedle); - } else { - if (php_needle_char(zneedle, ZSTR_VAL(ord_needle)) != SUCCESS) { - ZSTR_ALLOCA_FREE(ord_needle, use_heap); - RETURN_FALSE; - } - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - ZSTR_VAL(ord_needle)[1] = '\0'; - needle = ord_needle; - } - - if ((ZSTR_LEN(haystack) == 0) || (ZSTR_LEN(needle) == 0)) { - ZSTR_ALLOCA_FREE(ord_needle, use_heap); - RETURN_FALSE; - } - if (ZSTR_LEN(needle) == 1) { /* Single character search can shortcut memcmps Can also avoid tolower emallocs */ + char lowered; if (offset >= 0) { if ((size_t)offset > ZSTR_LEN(haystack)) { - ZSTR_ALLOCA_FREE(ord_needle, use_heap); - php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string"); + php_error_docref(NULL, E_WARNING, "Offset not contained in string"); RETURN_FALSE; } p = ZSTR_VAL(haystack) + (size_t)offset; @@ -2190,22 +2019,19 @@ PHP_FUNCTION(strripos) } else { p = ZSTR_VAL(haystack); if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) { - ZSTR_ALLOCA_FREE(ord_needle, use_heap); - php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string"); + php_error_docref(NULL, E_WARNING, "Offset not contained in string"); RETURN_FALSE; } e = ZSTR_VAL(haystack) + (ZSTR_LEN(haystack) + (size_t)offset); } /* Borrow that ord_needle buffer to avoid repeatedly tolower()ing needle */ - *ZSTR_VAL(ord_needle) = tolower(*ZSTR_VAL(needle)); + lowered = tolower(*ZSTR_VAL(needle)); while (e >= p) { - if (tolower(*e) == *ZSTR_VAL(ord_needle)) { - ZSTR_ALLOCA_FREE(ord_needle, use_heap); + if (tolower(*e) == lowered) { RETURN_LONG(e - p + (offset > 0 ? offset : 0)); } e--; } - ZSTR_ALLOCA_FREE(ord_needle, use_heap); RETURN_FALSE; } @@ -2213,8 +2039,7 @@ PHP_FUNCTION(strripos) if (offset >= 0) { if ((size_t)offset > ZSTR_LEN(haystack)) { zend_string_release_ex(haystack_dup, 0); - ZSTR_ALLOCA_FREE(ord_needle, use_heap); - php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string"); + php_error_docref(NULL, E_WARNING, "Offset not contained in string"); RETURN_FALSE; } p = ZSTR_VAL(haystack_dup) + offset; @@ -2222,10 +2047,10 @@ PHP_FUNCTION(strripos) } else { if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) { zend_string_release_ex(haystack_dup, 0); - ZSTR_ALLOCA_FREE(ord_needle, use_heap); - php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string"); + php_error_docref(NULL, E_WARNING, "Offset not contained in string"); RETURN_FALSE; } + p = ZSTR_VAL(haystack_dup); if ((size_t)-offset < ZSTR_LEN(needle)) { e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack); @@ -2239,45 +2064,28 @@ PHP_FUNCTION(strripos) RETVAL_LONG(found - ZSTR_VAL(haystack_dup)); zend_string_release_ex(needle_dup, 0); zend_string_release_ex(haystack_dup, 0); - ZSTR_ALLOCA_FREE(ord_needle, use_heap); } else { zend_string_release_ex(needle_dup, 0); zend_string_release_ex(haystack_dup, 0); - ZSTR_ALLOCA_FREE(ord_needle, use_heap); RETURN_FALSE; } } /* }}} */ -/* {{{ proto string strrchr(string haystack, string needle) +/* {{{ proto string|false strrchr(string haystack, string needle) Finds the last occurrence of a character in a string within another */ PHP_FUNCTION(strrchr) { - zval *needle; - zend_string *haystack; + zend_string *haystack, *needle; const char *found = NULL; zend_long found_offset; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(needle) + Z_PARAM_STR(needle) ZEND_PARSE_PARAMETERS_END(); - if (Z_TYPE_P(needle) == IS_STRING) { - found = zend_memrchr(ZSTR_VAL(haystack), *Z_STRVAL_P(needle), ZSTR_LEN(haystack)); - } else { - char needle_chr; - if (php_needle_char(needle, &needle_chr) != SUCCESS) { - RETURN_FALSE; - } - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - found = zend_memrchr(ZSTR_VAL(haystack), needle_chr, ZSTR_LEN(haystack)); - } - + found = zend_memrchr(ZSTR_VAL(haystack), *ZSTR_VAL(needle), ZSTR_LEN(haystack)); if (found) { found_offset = found - ZSTR_VAL(haystack); RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset); @@ -2293,28 +2101,19 @@ static zend_string *php_chunk_split(const char *src, size_t srclen, const char * { char *q; const char *p; - size_t chunks; /* complete chunks! */ + size_t chunks; size_t restlen; - size_t out_len; zend_string *dest; chunks = srclen / chunklen; restlen = srclen - chunks * chunklen; /* srclen % chunklen */ - - if (chunks > INT_MAX - 1) { - return NULL; - } - out_len = chunks + 1; - if (endlen !=0 && out_len > INT_MAX/endlen) { - return NULL; - } - out_len *= endlen; - if (out_len > INT_MAX - srclen - 1) { - return NULL; + if (restlen) { + /* We want chunks to be rounded up rather than rounded down. + * Increment can't overflow because chunks <= SIZE_MAX/2 at this point. */ + chunks++; } - out_len += srclen + 1; - dest = zend_string_alloc(out_len * sizeof(char), 0); + dest = zend_string_safe_alloc(chunks, endlen, srclen, 0); for (p = src, q = ZSTR_VAL(dest); p < (src + srclen - chunklen + 1); ) { memcpy(q, p, chunklen); @@ -2332,7 +2131,7 @@ static zend_string *php_chunk_split(const char *src, size_t srclen, const char * } *q = '\0'; - ZSTR_LEN(dest) = q - ZSTR_VAL(dest); + ZEND_ASSERT(q - ZSTR_VAL(dest) == ZSTR_LEN(dest)); return dest; } @@ -2356,8 +2155,8 @@ PHP_FUNCTION(chunk_split) ZEND_PARSE_PARAMETERS_END(); if (chunklen <= 0) { - php_error_docref(NULL, E_WARNING, "Chunk length should be greater than zero"); - RETURN_FALSE; + zend_throw_error(NULL, "Chunk length should be greater than zero"); + return; } if ((size_t)chunklen > ZSTR_LEN(str)) { @@ -2375,15 +2174,11 @@ PHP_FUNCTION(chunk_split) result = php_chunk_split(ZSTR_VAL(str), ZSTR_LEN(str), end, endlen, (size_t)chunklen); - if (result) { - RETURN_STR(result); - } else { - RETURN_FALSE; - } + RETURN_STR(result); } /* }}} */ -/* {{{ proto string substr(string str, int start [, int length]) +/* {{{ proto string|false substr(string str, int start [, int length]) Returns part of a string */ PHP_FUNCTION(substr) { @@ -2459,7 +2254,7 @@ truncate_len: } /* }}} */ -/* {{{ proto mixed substr_replace(mixed str, mixed repl, mixed start [, mixed length]) +/* {{{ proto string|array|false substr_replace(mixed str, mixed repl, mixed start [, mixed length]) Replaces part of a string with another string */ PHP_FUNCTION(substr_replace) { @@ -2739,8 +2534,8 @@ PHP_FUNCTION(quotemeta) old_end = ZSTR_VAL(old) + ZSTR_LEN(old); - if (ZSTR_VAL(old) == old_end) { - RETURN_FALSE; + if (ZSTR_LEN(old) == 0) { + RETURN_EMPTY_STRING(); } str = zend_string_safe_alloc(2, ZSTR_LEN(old), 0, 0); @@ -2796,7 +2591,7 @@ PHP_FUNCTION(chr) ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_LONG(c) - ZEND_PARSE_PARAMETERS_END_EX(c = 0); + ZEND_PARSE_PARAMETERS_END(); c &= 0xff; ZVAL_INTERNED_STR(return_value, ZSTR_CHAR(c)); @@ -3473,8 +3268,8 @@ PHP_FUNCTION(strtr) ZEND_PARSE_PARAMETERS_END(); if (ac == 2 && Z_TYPE_P(from) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "The second argument is not an array"); - RETURN_FALSE; + zend_type_error("The second argument is not an array"); + return; } /* shortcut for empty string */ @@ -4616,7 +4411,7 @@ static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines) ZEND_PARSE_PARAMETERS_END(); if (str_len == 0) { - RETURN_FALSE; + RETURN_EMPTY_STRING(); } tmp = str; @@ -4916,7 +4711,7 @@ PHP_FUNCTION(strip_tags) } /* }}} */ -/* {{{ proto string setlocale(mixed category, string locale [, string ...]) +/* {{{ proto string|false setlocale(mixed category, string locale [, string ...]) Set locale information */ PHP_FUNCTION(setlocale) { @@ -5029,7 +4824,7 @@ PHP_FUNCTION(setlocale) } /* }}} */ -/* {{{ proto void parse_str(string encoded_string [, array &result]) +/* {{{ proto void parse_str(string encoded_string, array &result) Parses GET/POST/COOKIE data and sets global variables */ PHP_FUNCTION(parse_str) { @@ -5038,39 +4833,18 @@ PHP_FUNCTION(parse_str) char *res = NULL; size_t arglen; - ZEND_PARSE_PARAMETERS_START(1, 2) + ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_STRING(arg, arglen) - Z_PARAM_OPTIONAL Z_PARAM_ZVAL(arrayArg) ZEND_PARSE_PARAMETERS_END(); - res = estrndup(arg, arglen); - - if (arrayArg == NULL) { - zval tmp; - zend_array *symbol_table; - if (zend_forbid_dynamic_call("parse_str() with a single argument") == FAILURE) { - efree(res); - return; - } - - php_error_docref(NULL, E_DEPRECATED, "Calling parse_str() without the result argument is deprecated"); - - symbol_table = zend_rebuild_symbol_table(); - ZVAL_ARR(&tmp, symbol_table); - sapi_module.treat_data(PARSE_STRING, res, &tmp); - if (UNEXPECTED(zend_hash_del(symbol_table, ZSTR_KNOWN(ZEND_STR_THIS)) == SUCCESS)) { - zend_throw_error(NULL, "Cannot re-assign $this"); - } - } else { - arrayArg = zend_try_array_init(arrayArg); - if (!arrayArg) { - efree(res); - return; - } - - sapi_module.treat_data(PARSE_STRING, res, arrayArg); + arrayArg = zend_try_array_init(arrayArg); + if (!arrayArg) { + return; } + + res = estrndup(arg, arglen); + sapi_module.treat_data(PARSE_STRING, res, arrayArg); } /* }}} */ @@ -5547,7 +5321,7 @@ PHP_FUNCTION(str_repeat) ZEND_PARSE_PARAMETERS_END(); if (mult < 0) { - php_error_docref(NULL, E_WARNING, "Second argument has to be greater than or equal to 0"); + zend_throw_error(NULL, "Second argument has to be greater than or equal to 0"); return; } @@ -5585,7 +5359,7 @@ PHP_FUNCTION(str_repeat) } /* }}} */ -/* {{{ proto mixed count_chars(string input [, int mode]) +/* {{{ proto array|string|false count_chars(string input [, int mode]) Returns info about what characters are used in input */ PHP_FUNCTION(count_chars) { @@ -5773,7 +5547,7 @@ PHP_FUNCTION(strnatcasecmp) } /* }}} */ -/* {{{ proto int substr_count(string haystack, string needle [, int offset [, int length]]) +/* {{{ proto int|false substr_count(string haystack, string needle [, int offset [, int length]]) Returns the number of times a substring occurs in the string */ PHP_FUNCTION(substr_count) { @@ -5794,8 +5568,8 @@ PHP_FUNCTION(substr_count) ZEND_PARSE_PARAMETERS_END(); if (needle_len == 0) { - php_error_docref(NULL, E_WARNING, "Empty substring"); - RETURN_FALSE; + zend_throw_error(NULL, "Empty substring"); + return; } p = haystack; @@ -5871,21 +5645,16 @@ PHP_FUNCTION(str_pad) } if (pad_str_len == 0) { - php_error_docref(NULL, E_WARNING, "Padding string cannot be empty"); + zend_throw_error(NULL, "Padding string cannot be empty"); return; } if (pad_type_val < STR_PAD_LEFT || pad_type_val > STR_PAD_BOTH) { - php_error_docref(NULL, E_WARNING, "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH"); + zend_throw_error(NULL, "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH"); return; } num_pad_chars = pad_length - ZSTR_LEN(input); - if (num_pad_chars >= INT_MAX) { - php_error_docref(NULL, E_WARNING, "Padding length is too long"); - return; - } - result = zend_string_safe_alloc(1, ZSTR_LEN(input), num_pad_chars, 0); ZSTR_LEN(result) = 0; @@ -6083,7 +5852,7 @@ static void php_string_shuffle(char *str, zend_long len) /* {{{ */ } /* }}} */ -/* {{{ proto void str_shuffle(string str) +/* {{{ proto string str_shuffle(string str) Shuffles string. One permutation of all possible is created */ PHP_FUNCTION(str_shuffle) { @@ -6100,13 +5869,13 @@ PHP_FUNCTION(str_shuffle) } /* }}} */ -/* {{{ proto mixed str_word_count(string str, [int format [, string charlist]]) + +/* {{{ proto array|int str_word_count(string str, [int format [, string charlist]]) Counts the number of words inside a string. If format of 1 is specified, then the function will return an array containing all the words found inside the string. If format of 2 is specified, then the function will return an associated array where the position of the word is the key and the word itself is the value. - For the purpose of this function, 'word' is defined as a locale dependent string containing alphabetic characters, which also may contain, but not start with "'" and "-" characters. @@ -6141,8 +5910,8 @@ PHP_FUNCTION(str_word_count) /* nothing to be done */ break; default: - php_error_docref(NULL, E_WARNING, "Invalid format value " ZEND_LONG_FMT, type); - RETURN_FALSE; + zend_throw_error(NULL, "Invalid format value " ZEND_LONG_FMT, type); + return; } if (char_list) { @@ -6191,7 +5960,7 @@ PHP_FUNCTION(str_word_count) /* }}} */ #if HAVE_STRFMON -/* {{{ proto string money_format(string format , float value) +/* {{{ proto string|false money_format(string format , float value) Convert monetary value(s) to string */ PHP_FUNCTION(money_format) { @@ -6258,8 +6027,8 @@ PHP_FUNCTION(str_split) ZEND_PARSE_PARAMETERS_END(); if (split_length <= 0) { - php_error_docref(NULL, E_WARNING, "The length of each segment must be greater than zero"); - RETURN_FALSE; + zend_throw_error(NULL, "The length of each segment must be greater than zero"); + return; } @@ -6285,7 +6054,7 @@ PHP_FUNCTION(str_split) } /* }}} */ -/* {{{ proto array strpbrk(string haystack, string char_list) +/* {{{ proto string|false strpbrk(string haystack, string char_list) Search a string for any of a set of characters */ PHP_FUNCTION(strpbrk) { @@ -6314,7 +6083,7 @@ PHP_FUNCTION(strpbrk) } /* }}} */ -/* {{{ proto int substr_compare(string main_str, string str, int offset [, int length [, bool case_sensitivity]]) +/* {{{ proto int|false substr_compare(string main_str, string str, int offset [, int length [, bool case_sensitivity]]) Binary safe optionally case insensitive comparison of 2 strings from an offset, up to length characters */ PHP_FUNCTION(substr_compare) { @@ -6337,8 +6106,8 @@ PHP_FUNCTION(substr_compare) if (len == 0) { RETURN_LONG(0L); } else { - php_error_docref(NULL, E_WARNING, "The length must be greater than or equal to zero"); - RETURN_FALSE; + zend_throw_error(NULL, "The length must be greater than or equal to zero"); + return; } } |
