summaryrefslogtreecommitdiff
path: root/ext/mbstring
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-06-12 10:05:16 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-06-12 10:08:34 +0200
commitf691693ebc7a0f6604455c004dc1ba78251c0ac1 (patch)
tree1b80a8fa0bec2f5600a84d8ca45d84877d75c3e6 /ext/mbstring
parentccf3e0121671f85b9cc0d0a9e96b39c3fc4d5117 (diff)
downloadphp-git-f691693ebc7a0f6604455c004dc1ba78251c0ac1.tar.gz
Fix null pointer ub in encoding parsing
And do a bit of drive-by cleanup by extracting count_commas and reducing some variable scopes.
Diffstat (limited to 'ext/mbstring')
-rw-r--r--ext/mbstring/mbstring.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index a30c3ca99c..4a3549bbe9 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.c
@@ -287,6 +287,15 @@ static const mbfl_encoding *php_mb_get_encoding_or_pass(const char *encoding_nam
return mbfl_name2encoding(encoding_name);
}
+static size_t count_commas(const char *p, size_t length) {
+ size_t count = 0;
+ while ((p = memchr(p, ',', length))) {
+ count++;
+ p++;
+ }
+ return count;
+}
+
/* {{{ static int php_mb_parse_encoding_list()
* Return FAILURE if input contains any illegal encoding, otherwise SUCCESS.
* Emits a ValueError in function context and a warning in INI context, in INI context arg_num must be 0.
@@ -302,7 +311,7 @@ static int php_mb_parse_encoding_list(const char *value, size_t value_length,
} else {
zend_bool included_auto;
size_t n, size;
- char *p, *p1, *p2, *endp, *tmpstr;
+ char *p1, *endp, *tmpstr;
const mbfl_encoding **entry, **list;
/* copy the value string for work */
@@ -312,26 +321,17 @@ static int php_mb_parse_encoding_list(const char *value, size_t value_length,
} else {
tmpstr = (char *)estrndup(value, value_length);
}
- /* count the number of listed encoding names */
- endp = tmpstr + value_length;
- n = 1;
- p1 = tmpstr;
- while ((p2 = (char*)php_memnstr(p1, ",", 1, endp)) != NULL) {
- p1 = p2 + 1;
- n++;
- }
- size = n + MBSTRG(default_detect_order_list_size);
- /* make list */
+
+ size = 1 + count_commas(tmpstr, value_length) + MBSTRG(default_detect_order_list_size);
list = (const mbfl_encoding **)pecalloc(size, sizeof(mbfl_encoding*), persistent);
entry = list;
n = 0;
included_auto = 0;
p1 = tmpstr;
- do {
- p2 = p = (char*)php_memnstr(p1, ",", 1, endp);
- if (p == NULL) {
- p = endp;
- }
+ endp = tmpstr + value_length;
+ while (1) {
+ char *comma = (char *) php_memnstr(p1, ",", 1, endp);
+ char *p = comma ? comma : endp;
*p = '\0';
/* trim spaces */
while (p1 < p && (*p1 == ' ' || *p1 == '\t')) {
@@ -372,8 +372,11 @@ static int php_mb_parse_encoding_list(const char *value, size_t value_length,
*entry++ = encoding;
n++;
}
- p1 = p2 + 1;
- } while (n < size && p2 != NULL);
+ if (n >= size || comma == NULL) {
+ break;
+ }
+ p1 = comma + 1;
+ }
*return_list = list;
*return_size = n;
efree(tmpstr);