summaryrefslogtreecommitdiff
path: root/ext/mbstring/mbstring.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mbstring/mbstring.c')
-rw-r--r--ext/mbstring/mbstring.c317
1 files changed, 237 insertions, 80 deletions
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index ea753b9406..423f357eae 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.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 |
@@ -591,7 +591,7 @@ static sapi_post_entry php_post_entries[] = {
#ifdef COMPILE_DL_MBSTRING
#ifdef ZTS
-ZEND_TSRMLS_CACHE_DEFINE();
+ZEND_TSRMLS_CACHE_DEFINE()
#endif
ZEND_GET_MODULE(mbstring)
#endif
@@ -2097,8 +2097,13 @@ PHP_FUNCTION(mb_parse_str)
detected = _php_mb_encoding_handler_ex(&info, track_vars_array, encstr);
} else {
zval tmp;
- zend_array *symbol_table = zend_rebuild_symbol_table();
+ zend_array *symbol_table;
+ if (zend_forbid_dynamic_call("mb_parse_str() with a single argument") == FAILURE) {
+ efree(encstr);
+ return;
+ }
+ symbol_table = zend_rebuild_symbol_table();
ZVAL_ARR(&tmp, symbol_table);
detected = _php_mb_encoding_handler_ex(&info, &tmp, encstr);
}
@@ -2222,14 +2227,21 @@ PHP_FUNCTION(mb_strlen)
int n;
mbfl_string string;
char *enc_name = NULL;
- size_t enc_name_len;
+ size_t enc_name_len, string_len;
mbfl_string_init(&string);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", (char **)&string.val, &string_len, &enc_name, &enc_name_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(string_len)) {
+ php_error_docref(NULL, E_WARNING, "String overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ string.len = (uint32_t)string_len;
+
string.no_language = MBSTRG(language);
if (enc_name == NULL) {
string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
@@ -2255,10 +2267,10 @@ PHP_FUNCTION(mb_strlen)
PHP_FUNCTION(mb_strpos)
{
int n, reverse = 0;
- zend_long offset;
+ zend_long offset = 0, slen;
mbfl_string haystack, needle;
char *enc_name = NULL;
- size_t enc_name_len;
+ size_t enc_name_len, haystack_len, needle_len;
mbfl_string_init(&haystack);
mbfl_string_init(&needle);
@@ -2266,12 +2278,22 @@ PHP_FUNCTION(mb_strpos)
haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
needle.no_language = MBSTRG(language);
needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- offset = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ls", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &offset, &enc_name, &enc_name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ls", (char **)&haystack.val, &haystack_len, (char **)&needle.val, &needle_len, &offset, &enc_name, &enc_name_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(haystack_len)) {
+ php_error_docref(NULL, E_WARNING, "Haystack length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ } else if (ZEND_SIZE_T_UINT_OVFL(needle_len)) {
+ php_error_docref(NULL, E_WARNING, "Needle length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ haystack.len = (uint32_t)haystack_len;
+ needle.len = (uint32_t)needle_len;
+
if (enc_name != NULL) {
haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
if (haystack.no_encoding == mbfl_no_encoding_invalid) {
@@ -2280,7 +2302,11 @@ PHP_FUNCTION(mb_strpos)
}
}
- if (offset < 0 || offset > mbfl_strlen(&haystack)) {
+ slen = mbfl_strlen(&haystack);
+ if (offset < 0) {
+ offset += slen;
+ }
+ if (offset < 0 || offset > slen) {
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
RETURN_FALSE;
}
@@ -2321,7 +2347,7 @@ PHP_FUNCTION(mb_strrpos)
int n;
mbfl_string haystack, needle;
char *enc_name = NULL;
- size_t enc_name_len;
+ size_t enc_name_len, haystack_len, needle_len;
zval *zoffset = NULL;
long offset = 0, str_flg;
char *enc_name2 = NULL;
@@ -2334,10 +2360,21 @@ PHP_FUNCTION(mb_strrpos)
needle.no_language = MBSTRG(language);
needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|zs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &zoffset, &enc_name, &enc_name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|zs", (char **)&haystack.val, &haystack_len, (char **)&needle.val, &needle_len, &zoffset, &enc_name, &enc_name_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(haystack_len)) {
+ php_error_docref(NULL, E_WARNING, "Haystack length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ } else if (ZEND_SIZE_T_UINT_OVFL(needle_len)) {
+ php_error_docref(NULL, E_WARNING, "Needle length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ haystack.len = (uint32_t)haystack_len;
+ needle.len = (uint32_t)needle_len;
+
if (zoffset) {
if (Z_TYPE_P(zoffset) == IS_STRING) {
enc_name2 = Z_STRVAL_P(zoffset);
@@ -2416,17 +2453,27 @@ PHP_FUNCTION(mb_strrpos)
Finds position of first occurrence of a string within another, case insensitive */
PHP_FUNCTION(mb_stripos)
{
- int n;
- zend_long offset;
+ int n = -1;
+ zend_long offset = 0;
mbfl_string haystack, needle;
const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
- size_t from_encoding_len;
- n = -1;
- offset = 0;
+ size_t from_encoding_len, haystack_len, needle_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ls", (char **)&haystack.val, (int *)&haystack.len, (char **)&needle.val, (int *)&needle.len, &offset, &from_encoding, &from_encoding_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ls", (char **)&haystack.val, &haystack_len, (char **)&needle.val, &needle_len, &offset, &from_encoding, &from_encoding_len) == FAILURE) {
return;
}
+
+ if (ZEND_SIZE_T_UINT_OVFL(haystack_len)) {
+ php_error_docref(NULL, E_WARNING, "Haystack length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ } else if (ZEND_SIZE_T_UINT_OVFL(needle_len)) {
+ php_error_docref(NULL, E_WARNING, "Needle length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ haystack.len = (uint32_t)haystack_len;
+ needle.len = (uint32_t)needle_len;
+
if (needle.len == 0) {
php_error_docref(NULL, E_WARNING, "Empty delimiter");
RETURN_FALSE;
@@ -2445,18 +2492,27 @@ PHP_FUNCTION(mb_stripos)
Finds position of last occurrence of a string within another, case insensitive */
PHP_FUNCTION(mb_strripos)
{
- int n;
- zend_long offset;
+ int n = -1;
+ zend_long offset = 0;
mbfl_string haystack, needle;
const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
- size_t from_encoding_len;
- n = -1;
- offset = 0;
+ size_t from_encoding_len, haystack_len, needle_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ls", (char **)&haystack.val, (int *)&haystack.len, (char **)&needle.val, (int *)&needle.len, &offset, &from_encoding, &from_encoding_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|ls", (char **)&haystack.val, &haystack_len, (char **)&needle.val, &needle_len, &offset, &from_encoding, &from_encoding_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(haystack_len)) {
+ php_error_docref(NULL, E_WARNING, "Haystack length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ } else if (ZEND_SIZE_T_UINT_OVFL(needle_len)) {
+ php_error_docref(NULL, E_WARNING, "Needle length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ haystack.len = (uint32_t)haystack_len;
+ needle.len = (uint32_t)needle_len;
+
n = php_mb_stripos(1, (char *)haystack.val, haystack.len, (char *)needle.val, needle.len, offset, from_encoding);
if (n >= 0) {
@@ -2474,7 +2530,7 @@ PHP_FUNCTION(mb_strstr)
int n, len, mblen;
mbfl_string haystack, needle, result, *ret = NULL;
char *enc_name = NULL;
- size_t enc_name_len;
+ size_t enc_name_len, haystack_len, needle_len;
zend_bool part = 0;
mbfl_string_init(&haystack);
@@ -2484,10 +2540,21 @@ PHP_FUNCTION(mb_strstr)
needle.no_language = MBSTRG(language);
needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|bs", (char **)&haystack.val, (int *)&haystack.len, (char **)&needle.val, (int *)&needle.len, &part, &enc_name, &enc_name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|bs", (char **)&haystack.val, &haystack_len, (char **)&needle.val, &needle_len, &part, &enc_name, &enc_name_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(haystack_len)) {
+ php_error_docref(NULL, E_WARNING, "Haystack length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ } else if (ZEND_SIZE_T_UINT_OVFL(needle_len)) {
+ php_error_docref(NULL, E_WARNING, "Needle length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ haystack.len = (uint32_t)haystack_len;
+ needle.len = (uint32_t)needle_len;
+
if (enc_name != NULL) {
haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
if (haystack.no_encoding == mbfl_no_encoding_invalid) {
@@ -2536,7 +2603,7 @@ PHP_FUNCTION(mb_strrchr)
int n, len, mblen;
mbfl_string haystack, needle, result, *ret = NULL;
char *enc_name = NULL;
- size_t enc_name_len;
+ size_t enc_name_len, haystack_len, needle_len;
zend_bool part = 0;
mbfl_string_init(&haystack);
@@ -2546,10 +2613,21 @@ PHP_FUNCTION(mb_strrchr)
needle.no_language = MBSTRG(language);
needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &enc_name, &enc_name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|bs", (char **)&haystack.val, &haystack_len, (char **)&needle.val, &needle_len, &part, &enc_name, &enc_name_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(haystack_len)) {
+ php_error_docref(NULL, E_WARNING, "Haystack length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ } else if (ZEND_SIZE_T_UINT_OVFL(needle_len)) {
+ php_error_docref(NULL, E_WARNING, "Needle length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ haystack.len = (uint32_t)haystack_len;
+ needle.len = (uint32_t)needle_len;
+
if (enc_name != NULL) {
haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
if (haystack.no_encoding == mbfl_no_encoding_invalid) {
@@ -2598,7 +2676,7 @@ PHP_FUNCTION(mb_strrchr)
PHP_FUNCTION(mb_stristr)
{
zend_bool part = 0;
- size_t from_encoding_len, len, mblen;
+ size_t from_encoding_len, len, mblen, haystack_len, needle_len;
int n;
mbfl_string haystack, needle, result, *ret = NULL;
const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
@@ -2610,10 +2688,21 @@ PHP_FUNCTION(mb_stristr)
needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &from_encoding, &from_encoding_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|bs", (char **)&haystack.val, &haystack_len, (char **)&needle.val, &needle_len, &part, &from_encoding, &from_encoding_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(haystack_len)) {
+ php_error_docref(NULL, E_WARNING, "Haystack length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ } else if (ZEND_SIZE_T_UINT_OVFL(needle_len)) {
+ php_error_docref(NULL, E_WARNING, "Needle length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ haystack.len = (uint32_t)haystack_len;
+ needle.len = (uint32_t)needle_len;
+
if (!needle.len) {
php_error_docref(NULL, E_WARNING, "Empty delimiter");
RETURN_FALSE;
@@ -2662,7 +2751,7 @@ PHP_FUNCTION(mb_strrichr)
{
zend_bool part = 0;
int n, len, mblen;
- size_t from_encoding_len;
+ size_t from_encoding_len, haystack_len, needle_len;
mbfl_string haystack, needle, result, *ret = NULL;
const char *from_encoding = MBSTRG(current_internal_encoding)->name;
mbfl_string_init(&haystack);
@@ -2673,10 +2762,21 @@ PHP_FUNCTION(mb_strrichr)
needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &from_encoding, &from_encoding_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|bs", (char **)&haystack.val, &haystack_len, (char **)&needle.val, &needle_len, &part, &from_encoding, &from_encoding_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(haystack_len)) {
+ php_error_docref(NULL, E_WARNING, "Haystack length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ } else if (ZEND_SIZE_T_UINT_OVFL(needle_len)) {
+ php_error_docref(NULL, E_WARNING, "Needle length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ haystack.len = (uint32_t)haystack_len;
+ needle.len = (uint32_t)needle_len;
+
haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(from_encoding);
if (haystack.no_encoding == mbfl_no_encoding_invalid) {
php_error_docref(NULL, E_WARNING, "Unknown encoding \"%s\"", from_encoding);
@@ -2721,7 +2821,7 @@ PHP_FUNCTION(mb_substr_count)
int n;
mbfl_string haystack, needle;
char *enc_name = NULL;
- size_t enc_name_len;
+ size_t enc_name_len, haystack_len, needle_len;
mbfl_string_init(&haystack);
mbfl_string_init(&needle);
@@ -2730,10 +2830,21 @@ PHP_FUNCTION(mb_substr_count)
needle.no_language = MBSTRG(language);
needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|s", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &enc_name, &enc_name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|s", (char **)&haystack.val, &haystack_len, (char **)&needle.val, &needle_len, &enc_name, &enc_name_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(haystack_len)) {
+ php_error_docref(NULL, E_WARNING, "Haystack length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ } else if (ZEND_SIZE_T_UINT_OVFL(needle_len)) {
+ php_error_docref(NULL, E_WARNING, "Needle length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ haystack.len = (uint32_t)haystack_len;
+ needle.len = (uint32_t)needle_len;
+
if (enc_name != NULL) {
haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
if (haystack.no_encoding == mbfl_no_encoding_invalid) {
@@ -2760,15 +2871,14 @@ PHP_FUNCTION(mb_substr_count)
Returns part of a string */
PHP_FUNCTION(mb_substr)
{
- size_t argc = ZEND_NUM_ARGS();
- char *str, *encoding;
+ char *str, *encoding = NULL;
zend_long from, len;
int mblen;
size_t str_len, encoding_len;
- zval *z_len = NULL;
+ zend_bool len_is_null = 1;
mbfl_string string, result, *ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|zs", &str, &str_len, &from, &z_len, &encoding, &encoding_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|l!s", &str, &str_len, &from, &len, &len_is_null, &encoding, &encoding_len) == FAILURE) {
return;
}
@@ -2776,7 +2886,7 @@ PHP_FUNCTION(mb_substr)
string.no_language = MBSTRG(language);
string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (argc == 4) {
+ if (encoding) {
string.no_encoding = mbfl_name2no_encoding(encoding);
if (string.no_encoding == mbfl_no_encoding_invalid) {
php_error_docref(NULL, E_WARNING, "Unknown encoding \"%s\"", encoding);
@@ -2787,11 +2897,8 @@ PHP_FUNCTION(mb_substr)
string.val = (unsigned char *)str;
string.len = str_len;
- if (argc < 3 || Z_TYPE_P(z_len) == IS_NULL) {
+ if (len_is_null) {
len = str_len;
- } else {
- convert_to_long_ex(z_len);
- len = Z_LVAL_P(z_len);
}
/* measures length */
@@ -2840,22 +2947,28 @@ PHP_FUNCTION(mb_substr)
Returns part of a string */
PHP_FUNCTION(mb_strcut)
{
- size_t argc = ZEND_NUM_ARGS();
- char *encoding;
+ char *encoding = NULL;
zend_long from, len;
- size_t encoding_len;
- zval *z_len = NULL;
+ size_t encoding_len, string_len;
+ zend_bool len_is_null = 1;
mbfl_string string, result, *ret;
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|zs", (char **)&string.val, (int **)&string.len, &from, &z_len, &encoding, &encoding_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|l!s", (char **)&string.val, &string_len, &from, &len, &len_is_null, &encoding, &encoding_len) == FAILURE) {
return;
}
- if (argc == 4) {
+ if (ZEND_SIZE_T_UINT_OVFL(string_len)) {
+ php_error_docref(NULL, E_WARNING, "String length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ string.len = (uint32_t)string_len;
+
+ if (encoding) {
string.no_encoding = mbfl_name2no_encoding(encoding);
if (string.no_encoding == mbfl_no_encoding_invalid) {
php_error_docref(NULL, E_WARNING, "Unknown encoding \"%s\"", encoding);
@@ -2863,11 +2976,8 @@ PHP_FUNCTION(mb_strcut)
}
}
- if (argc < 3 || Z_TYPE_P(z_len) == IS_NULL) {
+ if (len_is_null) {
len = string.len;
- } else {
- convert_to_long_ex(z_len);
- len = Z_LVAL_P(z_len);
}
/* if "from" position is negative, count start position from the end
@@ -2912,17 +3022,24 @@ PHP_FUNCTION(mb_strwidth)
int n;
mbfl_string string;
char *enc_name = NULL;
- size_t enc_name_len;
+ size_t enc_name_len, string_len;
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", (char **)&string.val, &string_len, &enc_name, &enc_name_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(string_len)) {
+ php_error_docref(NULL, E_WARNING, "String length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ string.len = (uint32_t)string_len;
+
if (enc_name != NULL) {
string.no_encoding = mbfl_name2no_encoding(enc_name);
if (string.no_encoding == mbfl_no_encoding_invalid) {
@@ -2944,8 +3061,8 @@ PHP_FUNCTION(mb_strwidth)
Trim the string in terminal width */
PHP_FUNCTION(mb_strimwidth)
{
- char *str, *trimmarker, *encoding;
- zend_long from, width;
+ char *str, *trimmarker = NULL, *encoding = NULL;
+ zend_long from, width, swidth;
size_t str_len, trimmarker_len, encoding_len;
mbfl_string string, result, marker, *ret;
@@ -2962,7 +3079,7 @@ PHP_FUNCTION(mb_strimwidth)
marker.val = NULL;
marker.len = 0;
- if (ZEND_NUM_ARGS() == 5) {
+ if (encoding) {
string.no_encoding = marker.no_encoding = mbfl_name2no_encoding(encoding);
if (string.no_encoding == mbfl_no_encoding_invalid) {
php_error_docref(NULL, E_WARNING, "Unknown encoding \"%s\"", encoding);
@@ -2973,17 +3090,29 @@ PHP_FUNCTION(mb_strimwidth)
string.val = (unsigned char *)str;
string.len = str_len;
+ if ((from < 0) || (width < 0)) {
+ swidth = mbfl_strwidth(&string);
+ }
+
+ if (from < 0) {
+ from += swidth;
+ }
+
if (from < 0 || (size_t)from > str_len) {
php_error_docref(NULL, E_WARNING, "Start position is out of range");
RETURN_FALSE;
}
if (width < 0) {
- php_error_docref(NULL, E_WARNING, "Width is negative value");
+ width = swidth + width - from;
+ }
+
+ if (width < 0) {
+ php_error_docref(NULL, E_WARNING, "Width is out of range");
RETURN_FALSE;
}
- if (ZEND_NUM_ARGS() >= 4) {
+ if (trimmarker) {
marker.val = (unsigned char *)trimmarker;
marker.len = trimmarker_len;
}
@@ -3092,7 +3221,7 @@ PHP_FUNCTION(mb_convert_encoding)
{
char *arg_str, *arg_new;
size_t str_len, new_len;
- zval *arg_old;
+ zval *arg_old = NULL;
size_t size, l, n;
char *_from_encodings = NULL, *ret, *s_free = NULL;
@@ -3103,7 +3232,7 @@ PHP_FUNCTION(mb_convert_encoding)
return;
}
- if (ZEND_NUM_ARGS() == 3) {
+ if (arg_old) {
switch (Z_TYPE_P(arg_old)) {
case IS_ARRAY:
target_hash = Z_ARRVAL_P(arg_old);
@@ -3241,21 +3370,21 @@ PHP_FUNCTION(mb_detect_encoding)
char *str;
size_t str_len;
zend_bool strict=0;
- zval *encoding_list;
+ zval *encoding_list = NULL;
mbfl_string string;
const mbfl_encoding *ret;
const mbfl_encoding **elist, **list;
size_t size;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|zb", &str, &str_len, &encoding_list, &strict) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|z!b", &str, &str_len, &encoding_list, &strict) == FAILURE) {
return;
}
/* make encoding list */
list = NULL;
size = 0;
- if (ZEND_NUM_ARGS() >= 2 && !Z_ISNULL_P(encoding_list)) {
+ if (encoding_list) {
switch (Z_TYPE_P(encoding_list)) {
case IS_ARRAY:
if (FAILURE == php_mb_parse_encoding_array(encoding_list, &list, &size, 0)) {
@@ -3319,6 +3448,10 @@ PHP_FUNCTION(mb_list_encodings)
const mbfl_encoding *encoding;
int i;
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
array_init(return_value);
i = 0;
encodings = mbfl_get_supported_encodings();
@@ -3367,17 +3500,24 @@ PHP_FUNCTION(mb_encode_mimeheader)
char *trans_enc_name = NULL;
size_t trans_enc_name_len;
char *linefeed = "\r\n";
- size_t linefeed_len;
+ size_t linefeed_len, string_len;
zend_long indent = 0;
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sssl", (char **)&string.val, &string.len, &charset_name, &charset_name_len, &trans_enc_name, &trans_enc_name_len, &linefeed, &linefeed_len, &indent) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sssl", (char **)&string.val, &string_len, &charset_name, &charset_name_len, &trans_enc_name, &trans_enc_name_len, &linefeed, &linefeed_len, &indent) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(string_len)) {
+ php_error_docref(NULL, E_WARNING, "String length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ string.len = (uint32_t)string_len;
+
charset = mbfl_no_encoding_pass;
transenc = mbfl_no_encoding_base64;
@@ -3420,15 +3560,23 @@ PHP_FUNCTION(mb_encode_mimeheader)
PHP_FUNCTION(mb_decode_mimeheader)
{
mbfl_string string, result, *ret;
+ size_t string_len;
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", (char **)&string.val, &string.len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", (char **)&string.val, &string_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(string_len)) {
+ php_error_docref(NULL, E_WARNING, "String length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ string.len = (uint32_t)string_len;
+
mbfl_string_init(&result);
ret = mbfl_mime_header_decode(&string, &result, MBSTRG(current_internal_encoding)->no_encoding);
if (ret != NULL) {
@@ -3450,16 +3598,23 @@ PHP_FUNCTION(mb_convert_kana)
char *optstr = NULL;
size_t optstr_len;
char *encname = NULL;
- size_t encname_len;
+ size_t encname_len, string_len;
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ss", (char **)&string.val, &string.len, &optstr, &optstr_len, &encname, &encname_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ss", (char **)&string.val, &string_len, &optstr, &optstr_len, &encname, &encname_len) == FAILURE) {
return;
}
+ if (ZEND_SIZE_T_UINT_OVFL(string_len)) {
+ php_error_docref(NULL, E_WARNING, "String length overflows the max allowed length of %u", UINT_MAX);
+ return;
+ }
+
+ string.len = (uint32_t)string_len;
+
/* option */
if (optstr != NULL) {
char *p = optstr;
@@ -3780,17 +3935,16 @@ detect_end:
static void
php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAMETERS, int type)
{
- char *str, *encoding;
+ char *str, *encoding = NULL;
size_t str_len, encoding_len;
zval *zconvmap, *hash_entry;
HashTable *target_hash;
- int argc = ZEND_NUM_ARGS();
int i, *convmap, *mapelm, mapsize=0;
zend_bool is_hex = 0;
mbfl_string string, result, *ret;
enum mbfl_no_encoding no_encoding;
- if (zend_parse_parameters(argc, "sz|sb", &str, &str_len, &zconvmap, &encoding, &encoding_len, &is_hex) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz|sb", &str, &str_len, &zconvmap, &encoding, &encoding_len, &is_hex) == FAILURE) {
return;
}
@@ -3801,7 +3955,7 @@ php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAMETERS, int type)
string.len = str_len;
/* encoding */
- if ((argc == 3 || argc == 4) && encoding_len > 0) {
+ if (encoding && encoding_len > 0) {
no_encoding = mbfl_name2no_encoding(encoding);
if (no_encoding == mbfl_no_encoding_invalid) {
php_error_docref(NULL, E_WARNING, "Unknown encoding \"%s\"", encoding);
@@ -3811,10 +3965,8 @@ php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAMETERS, int type)
}
}
- if (argc == 4) {
- if (type == 0 && is_hex) {
- type = 2; /* output in hex format */
- }
+ if (type == 0 && is_hex) {
+ type = 2; /* output in hex format */
}
/* conversion map */
@@ -4125,11 +4277,12 @@ PHP_FUNCTION(mb_send_mail)
_php_mbstr_parse_mail_headers(&ht_headers, headers, headers_len);
}
- if ((s = zend_hash_str_find_ptr(&ht_headers, "CONTENT-TYPE", sizeof("CONTENT-TYPE") - 1))) {
+ if ((s = zend_hash_str_find(&ht_headers, "CONTENT-TYPE", sizeof("CONTENT-TYPE") - 1))) {
char *tmp;
char *param_name;
char *charset = NULL;
+ ZEND_ASSERT(Z_TYPE_P(s) == IS_STRING);
p = strchr(Z_STRVAL_P(s), ';');
if (p != NULL) {
@@ -4160,9 +4313,10 @@ PHP_FUNCTION(mb_send_mail)
suppressed_hdrs.cnt_type = 1;
}
- if ((s = zend_hash_str_find_ptr(&ht_headers, "CONTENT-TRANSFER-ENCODING", sizeof("CONTENT-TRANSFER-ENCODING") - 1))) {
+ if ((s = zend_hash_str_find(&ht_headers, "CONTENT-TRANSFER-ENCODING", sizeof("CONTENT-TRANSFER-ENCODING") - 1))) {
enum mbfl_no_encoding _body_enc;
+ ZEND_ASSERT(Z_TYPE_P(s) == IS_STRING);
_body_enc = mbfl_name2no_encoding(Z_STRVAL_P(s));
switch (_body_enc) {
case mbfl_no_encoding_base64:
@@ -4736,6 +4890,9 @@ MBSTRING_API int php_mb_stripos(int mode, const char *old_haystack, unsigned int
break;
}
} else {
+ if (offset < 0) {
+ offset += (long)haystack_char_len;
+ }
if (offset < 0 || offset > haystack_char_len) {
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
break;