Skip to content

Commit 88bd7cb

Browse files
committed
Use safe alloc functions when calculations are made on sizes.
Fixes bug #71449, bug #71450
1 parent 6239e44 commit 88bd7cb

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ PHP NEWS
33
?? ??? 2016 PHP 7.0.4
44

55
- Core:
6+
. Fixed bug #71450 (An integer overflow bug in php_str_to_str_ex()). (Stas)
7+
. Fixed bug #71449 (An integer overflow bug in php_implode()). (Stas)
68
. Fixed bug #71443 (Segfault using built-in webserver with intl using
79
symfony). (Laruence)
810
. Fixed bug #71442 (forward_static_call crash). (Laruence)

ext/standard/string.c

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -998,12 +998,12 @@ PHP_FUNCTION(wordwrap)
998998
/* Multiple character line break or forced cut */
999999
if (linelength > 0) {
10001000
chk = (size_t)(ZSTR_LEN(text)/linelength + 1);
1001-
newtext = zend_string_alloc(chk * breakchar_len + ZSTR_LEN(text), 0);
1001+
newtext = zend_string_safe_alloc(chk, breakchar_len, ZSTR_LEN(text), 0);
10021002
alloced = ZSTR_LEN(text) + chk * breakchar_len + 1;
10031003
} else {
10041004
chk = ZSTR_LEN(text);
10051005
alloced = ZSTR_LEN(text) * (breakchar_len + 1) + 1;
1006-
newtext = zend_string_alloc(ZSTR_LEN(text) * (breakchar_len + 1), 0);
1006+
newtext = zend_string_safe_alloc(ZSTR_LEN(text), breakchar_len + 1, 0, 0);
10071007
}
10081008

10091009
/* 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)
12451245
len += ZSTR_LEN(*strptr);
12461246
}
12471247
} ZEND_HASH_FOREACH_END();
1248-
1249-
str = zend_string_alloc(len + (numelems - 1) * ZSTR_LEN(delim), 0);
1248+
/* numelems can not be 0, we checked above */
1249+
str = zend_string_safe_alloc(numelems - 1, ZSTR_LEN(delim), len, 0);
12501250
cptr = ZSTR_VAL(str) + ZSTR_LEN(str);
12511251
*cptr = 0;
12521252

@@ -2344,7 +2344,7 @@ PHP_FUNCTION(chunk_split)
23442344

23452345
if ((size_t)chunklen > ZSTR_LEN(str)) {
23462346
/* to maintain BC, we must return original string + ending */
2347-
result = zend_string_alloc(endlen + ZSTR_LEN(str), 0);
2347+
result = zend_string_safe_alloc(ZSTR_LEN(str), 1, endlen, 0);
23482348
memcpy(ZSTR_VAL(result), ZSTR_VAL(str), ZSTR_LEN(str));
23492349
memcpy(ZSTR_VAL(result) + ZSTR_LEN(str), end, endlen);
23502350
ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0';
@@ -2714,7 +2714,7 @@ PHP_FUNCTION(quotemeta)
27142714
RETURN_FALSE;
27152715
}
27162716

2717-
str = zend_string_alloc(2 * ZSTR_LEN(old), 0);
2717+
str = zend_string_safe_alloc(2, ZSTR_LEN(old), 0, 0);
27182718

27192719
for (p = ZSTR_VAL(old), q = ZSTR_VAL(str); p != old_end; p++) {
27202720
c = *p;
@@ -3235,7 +3235,11 @@ static zend_string *php_str_to_str_ex(zend_string *haystack,
32353235
/* Needle doesn't occur, shortcircuit the actual replacement. */
32363236
goto nothing_todo;
32373237
}
3238-
new_str = zend_string_alloc(count * (str_len - needle_len) + ZSTR_LEN(haystack), 0);
3238+
if (str_len > needle_len) {
3239+
new_str = zend_string_safe_alloc(count, str_len - needle_len, ZSTR_LEN(haystack), 0);
3240+
} else {
3241+
new_str = zend_string_alloc(count * (str_len - needle_len) + ZSTR_LEN(haystack), 0);
3242+
}
32393243

32403244
e = s = ZSTR_VAL(new_str);
32413245
end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
@@ -3312,8 +3316,12 @@ static zend_string *php_str_to_str_i_ex(zend_string *haystack, char *lc_haystack
33123316
zend_string_release(lc_needle);
33133317
goto nothing_todo;
33143318
}
3315-
3316-
new_str = zend_string_alloc(count * (str_len - ZSTR_LEN(lc_needle)) + ZSTR_LEN(haystack), 0);
3319+
3320+
if (str_len > ZSTR_LEN(lc_needle)) {
3321+
new_str = zend_string_safe_alloc(count, str_len - ZSTR_LEN(lc_needle), ZSTR_LEN(haystack), 0);
3322+
} else {
3323+
new_str = zend_string_alloc(count * (str_len - ZSTR_LEN(lc_needle)) + ZSTR_LEN(haystack), 0);
3324+
}
33173325

33183326
e = s = ZSTR_VAL(new_str);
33193327
end = lc_haystack + ZSTR_LEN(haystack);
@@ -3391,7 +3399,11 @@ PHPAPI zend_string *php_str_to_str(char *haystack, size_t length, char *needle,
33913399
new_str = zend_string_init(haystack, length, 0);
33923400
return new_str;
33933401
} else {
3394-
new_str = zend_string_alloc(count * (str_len - needle_len) + length, 0);
3402+
if (str_len > needle_len) {
3403+
new_str = zend_string_safe_alloc(count, str_len - needle_len, length, 0);
3404+
} else {
3405+
new_str = zend_string_alloc(count * (str_len - needle_len) + length, 0);
3406+
}
33953407
}
33963408
}
33973409

@@ -3819,7 +3831,7 @@ PHPAPI zend_string *php_addcslashes(zend_string *str, int should_free, char *wha
38193831
char *end;
38203832
char c;
38213833
size_t newlen;
3822-
zend_string *new_str = zend_string_alloc(4 * ZSTR_LEN(str), 0);
3834+
zend_string *new_str = zend_string_safe_alloc(4, ZSTR_LEN(str), 0, 0);
38233835

38243836
php_charmask((unsigned char *)what, wlength, flags);
38253837

@@ -3894,7 +3906,7 @@ PHPAPI zend_string *php_addslashes(zend_string *str, int should_free)
38943906

38953907
do_escape:
38963908
offset = source - (char *)ZSTR_VAL(str);
3897-
new_str = zend_string_alloc(offset + (2 * (ZSTR_LEN(str) - offset)), 0);
3909+
new_str = zend_string_safe_alloc(2, ZSTR_LEN(str) - offset, offset, 0);
38983910
memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), offset);
38993911
target = ZSTR_VAL(new_str) + offset;
39003912

@@ -4416,7 +4428,7 @@ PHP_FUNCTION(nl2br)
44164428
{
44174429
size_t repl_len = is_xhtml ? (sizeof("<br />") - 1) : (sizeof("<br>") - 1);
44184430

4419-
result = zend_string_alloc(repl_cnt * repl_len + ZSTR_LEN(str), 0);
4431+
result = zend_string_safe_alloc(repl_cnt, repl_len, ZSTR_LEN(str), 0);
44204432
target = ZSTR_VAL(result);
44214433
}
44224434

@@ -5600,7 +5612,7 @@ PHP_FUNCTION(money_format)
56005612
}
56015613
}
56025614

5603-
str = zend_string_alloc(format_len + 1024, 0);
5615+
str = zend_string_safe_alloc(format_len, 1, 1024, 0);
56045616
if ((res_len = strfmon(ZSTR_VAL(str), ZSTR_LEN(str), format, value)) < 0) {
56055617
zend_string_free(str);
56065618
RETURN_FALSE;

0 commit comments

Comments
 (0)