diff options
Diffstat (limited to 'ext/mbstring/mbstring.c')
-rw-r--r-- | ext/mbstring/mbstring.c | 317 |
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; |