diff options
Diffstat (limited to 'ext/standard/string.c')
-rw-r--r-- | ext/standard/string.c | 94 |
1 files changed, 59 insertions, 35 deletions
diff --git a/ext/standard/string.c b/ext/standard/string.c index 01c7c6dffe..3ac3614ac9 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 7 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2015 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -998,12 +998,12 @@ PHP_FUNCTION(wordwrap) /* Multiple character line break or forced cut */ if (linelength > 0) { chk = (size_t)(ZSTR_LEN(text)/linelength + 1); - newtext = zend_string_alloc(chk * breakchar_len + ZSTR_LEN(text), 0); + newtext = zend_string_safe_alloc(chk, breakchar_len, ZSTR_LEN(text), 0); alloced = ZSTR_LEN(text) + chk * breakchar_len + 1; } else { chk = ZSTR_LEN(text); alloced = ZSTR_LEN(text) * (breakchar_len + 1) + 1; - newtext = zend_string_alloc(ZSTR_LEN(text) * (breakchar_len + 1), 0); + newtext = zend_string_safe_alloc(ZSTR_LEN(text), breakchar_len + 1, 0, 0); } /* now keep track of the actual new text length */ @@ -1245,8 +1245,8 @@ PHPAPI void php_implode(const zend_string *delim, zval *arr, zval *return_value) len += ZSTR_LEN(*strptr); } } ZEND_HASH_FOREACH_END(); - - str = zend_string_alloc(len + (numelems - 1) * ZSTR_LEN(delim), 0); + /* numelems can not be 0, we checked above */ + str = zend_string_safe_alloc(numelems - 1, ZSTR_LEN(delim), len, 0); cptr = ZSTR_VAL(str) + ZSTR_LEN(str); *cptr = 0; @@ -2344,7 +2344,7 @@ PHP_FUNCTION(chunk_split) if ((size_t)chunklen > ZSTR_LEN(str)) { /* to maintain BC, we must return original string + ending */ - result = zend_string_alloc(endlen + ZSTR_LEN(str), 0); + result = zend_string_safe_alloc(ZSTR_LEN(str), 1, endlen, 0); memcpy(ZSTR_VAL(result), ZSTR_VAL(str), ZSTR_LEN(str)); memcpy(ZSTR_VAL(result) + ZSTR_LEN(str), end, endlen); ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0'; @@ -2491,8 +2491,8 @@ PHP_FUNCTION(substr_replace) if (Z_TYPE_P(str) != IS_ARRAY) { if (Z_TYPE_P(from) != IS_ARRAY) { - size_t repl_len = 0; - + zend_string *repl_str; + zend_bool repl_release = 0; f = Z_LVAL_P(from); /* if "from" position is negative, count start position from the end @@ -2533,21 +2533,26 @@ PHP_FUNCTION(substr_replace) repl_idx++; } if (repl_idx < Z_ARRVAL_P(repl)->nNumUsed) { - convert_to_string_ex(tmp_repl); - repl_len = Z_STRLEN_P(tmp_repl); + repl_str = zval_get_string(tmp_repl); + repl_release = 1; + } else { + repl_str = STR_EMPTY_ALLOC(); } } else { - repl_len = Z_STRLEN_P(repl); + repl_str = Z_STR_P(repl); } - result = zend_string_alloc(Z_STRLEN_P(str) - l + repl_len, 0); + result = zend_string_alloc(Z_STRLEN_P(str) - l + ZSTR_LEN(repl_str), 0); memcpy(ZSTR_VAL(result), Z_STRVAL_P(str), f); - if (repl_len) { - memcpy((ZSTR_VAL(result) + f), (Z_TYPE_P(repl) == IS_ARRAY ? Z_STRVAL_P(tmp_repl) : Z_STRVAL_P(repl)), repl_len); + if (ZSTR_LEN(repl_str)) { + memcpy((ZSTR_VAL(result) + f), ZSTR_VAL(repl_str), ZSTR_LEN(repl_str)); } - memcpy((ZSTR_VAL(result) + f + repl_len), Z_STRVAL_P(str) + f + l, Z_STRLEN_P(str) - f - l); + memcpy((ZSTR_VAL(result) + f + ZSTR_LEN(repl_str)), Z_STRVAL_P(str) + f + l, Z_STRLEN_P(str) - f - l); ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0'; + if (repl_release) { + zend_string_release(repl_str); + } RETURN_NEW_STR(result); } else { php_error_docref(NULL, E_WARNING, "Functionality of 'from' and 'len' as arrays is not implemented"); @@ -2705,7 +2710,7 @@ PHP_FUNCTION(quotemeta) RETURN_FALSE; } - str = zend_string_alloc(2 * ZSTR_LEN(old), 0); + str = zend_string_safe_alloc(2, ZSTR_LEN(old), 0, 0); for (p = ZSTR_VAL(old), q = ZSTR_VAL(str); p != old_end; p++) { c = *p; @@ -3226,7 +3231,11 @@ static zend_string *php_str_to_str_ex(zend_string *haystack, /* Needle doesn't occur, shortcircuit the actual replacement. */ goto nothing_todo; } - new_str = zend_string_alloc(count * (str_len - needle_len) + ZSTR_LEN(haystack), 0); + if (str_len > needle_len) { + new_str = zend_string_safe_alloc(count, str_len - needle_len, ZSTR_LEN(haystack), 0); + } else { + new_str = zend_string_alloc(count * (str_len - needle_len) + ZSTR_LEN(haystack), 0); + } e = s = ZSTR_VAL(new_str); end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack); @@ -3303,8 +3312,12 @@ static zend_string *php_str_to_str_i_ex(zend_string *haystack, char *lc_haystack zend_string_release(lc_needle); goto nothing_todo; } - - new_str = zend_string_alloc(count * (str_len - ZSTR_LEN(lc_needle)) + ZSTR_LEN(haystack), 0); + + if (str_len > ZSTR_LEN(lc_needle)) { + new_str = zend_string_safe_alloc(count, str_len - ZSTR_LEN(lc_needle), ZSTR_LEN(haystack), 0); + } else { + new_str = zend_string_alloc(count * (str_len - ZSTR_LEN(lc_needle)) + ZSTR_LEN(haystack), 0); + } e = s = ZSTR_VAL(new_str); end = lc_haystack + ZSTR_LEN(haystack); @@ -3382,7 +3395,11 @@ PHPAPI zend_string *php_str_to_str(char *haystack, size_t length, char *needle, new_str = zend_string_init(haystack, length, 0); return new_str; } else { - new_str = zend_string_alloc(count * (str_len - needle_len) + length, 0); + if (str_len > needle_len) { + new_str = zend_string_safe_alloc(count, str_len - needle_len, length, 0); + } else { + new_str = zend_string_alloc(count * (str_len - needle_len) + length, 0); + } } } @@ -3810,7 +3827,7 @@ PHPAPI zend_string *php_addcslashes(zend_string *str, int should_free, char *wha char *end; char c; size_t newlen; - zend_string *new_str = zend_string_alloc(4 * ZSTR_LEN(str), 0); + zend_string *new_str = zend_string_safe_alloc(4, ZSTR_LEN(str), 0, 0); php_charmask((unsigned char *)what, wlength, flags); @@ -3885,7 +3902,7 @@ PHPAPI zend_string *php_addslashes(zend_string *str, int should_free) do_escape: offset = source - (char *)ZSTR_VAL(str); - new_str = zend_string_alloc(offset + (2 * (ZSTR_LEN(str) - offset)), 0); + new_str = zend_string_safe_alloc(2, ZSTR_LEN(str) - offset, offset, 0); memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), offset); target = ZSTR_VAL(new_str) + offset; @@ -3968,12 +3985,12 @@ static zend_long php_str_replace_in_subject(zval *search, zval *replace, zval *s /* For each entry in the search array, get the entry */ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(search), search_entry) { /* Make sure we're dealing with strings. */ - ZVAL_DEREF(search_entry); - convert_to_string(search_entry); - if (Z_STRLEN_P(search_entry) == 0) { + zend_string *search_str = zval_get_string(search_entry); + if (ZSTR_LEN(search_str) == 0) { if (Z_TYPE_P(replace) == IS_ARRAY) { replace_idx++; } + zend_string_release(search_str); continue; } @@ -4003,11 +4020,11 @@ static zend_long php_str_replace_in_subject(zval *search, zval *replace, zval *s } } - if (Z_STRLEN_P(search_entry) == 1) { + if (ZSTR_LEN(search_str) == 1) { zend_long old_replace_count = replace_count; tmp_result = php_char_to_str_ex(Z_STR_P(result), - Z_STRVAL_P(search_entry)[0], + ZSTR_VAL(search_str)[0], replace_value, replace_len, case_sensitivity, @@ -4016,10 +4033,10 @@ static zend_long php_str_replace_in_subject(zval *search, zval *replace, zval *s zend_string_release(lc_subject_str); lc_subject_str = NULL; } - } else if (Z_STRLEN_P(search_entry) > 1) { + } else if (ZSTR_LEN(search_str) > 1) { if (case_sensitivity) { tmp_result = php_str_to_str_ex(Z_STR_P(result), - Z_STRVAL_P(search_entry), Z_STRLEN_P(search_entry), + ZSTR_VAL(search_str), ZSTR_LEN(search_str), replace_value, replace_len, &replace_count); } else { zend_long old_replace_count = replace_count; @@ -4028,7 +4045,7 @@ static zend_long php_str_replace_in_subject(zval *search, zval *replace, zval *s lc_subject_str = php_string_tolower(Z_STR_P(result)); } tmp_result = php_str_to_str_i_ex(Z_STR_P(result), ZSTR_VAL(lc_subject_str), - Z_STR_P(search_entry), replace_value, replace_len, &replace_count); + search_str, replace_value, replace_len, &replace_count); if (replace_count != old_replace_count) { zend_string_release(lc_subject_str); lc_subject_str = NULL; @@ -4036,6 +4053,8 @@ static zend_long php_str_replace_in_subject(zval *search, zval *replace, zval *s } } + zend_string_release(search_str); + if (replace_entry_str) { zend_string_release(replace_entry_str); replace_entry_str = NULL; @@ -4055,6 +4074,7 @@ static zend_long php_str_replace_in_subject(zval *search, zval *replace, zval *s zend_string_release(lc_subject_str); } } else { + ZEND_ASSERT(Z_TYPE_P(search) == IS_STRING); if (Z_STRLEN_P(search) == 1) { ZVAL_STR(result, php_char_to_str_ex(subject_str, @@ -4404,7 +4424,7 @@ PHP_FUNCTION(nl2br) { size_t repl_len = is_xhtml ? (sizeof("<br />") - 1) : (sizeof("<br>") - 1); - result = zend_string_alloc(repl_cnt * repl_len + ZSTR_LEN(str), 0); + result = zend_string_safe_alloc(repl_cnt, repl_len, ZSTR_LEN(str), 0); target = ZSTR_VAL(result); } @@ -4691,6 +4711,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha size_t pos, i = 0; char *allow_free = NULL; const char *allow_actual; + char is_xml = 0; if (stateptr) state = *stateptr; @@ -4786,7 +4807,10 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha switch (state) { case 1: /* HTML/XML */ lc = '>'; - in_q = state = 0; + if (is_xml && *(p -1) == '-') { + break; + } + in_q = state = is_xml = 0; if (allow) { if (tp - tbuf >= PHP_TAG_BUF_SIZE) { pos = tp - tbuf; @@ -4915,8 +4939,8 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha * state == 2 (PHP). Switch back to HTML. */ - if (state == 2 && p > buf+2 && strncasecmp(p-2, "xm", 2) == 0) { - state = 1; + if (state == 2 && p > buf+4 && strncasecmp(p-4, "<?xm", 4) == 0) { + state = 1; is_xml=1; break; } @@ -5585,7 +5609,7 @@ PHP_FUNCTION(money_format) } } - str = zend_string_alloc(format_len + 1024, 0); + str = zend_string_safe_alloc(format_len, 1, 1024, 0); if ((res_len = strfmon(ZSTR_VAL(str), ZSTR_LEN(str), format, value)) < 0) { zend_string_free(str); RETURN_FALSE; |