Skip to content

Commit ff8d2af

Browse files
committed
Remove memory exhaustion checks in php_chunk_split()
1 parent 743729d commit ff8d2af

7 files changed

+129
-31
lines changed

ext/standard/string.c

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,7 +2127,6 @@ static zend_string *php_chunk_split(const char *src, size_t srclen, const char *
21272127
const char *p;
21282128
size_t chunks;
21292129
size_t restlen;
2130-
size_t out_len;
21312130
zend_string *dest;
21322131

21332132
chunks = srclen / chunklen;
@@ -2138,17 +2137,7 @@ static zend_string *php_chunk_split(const char *src, size_t srclen, const char *
21382137
chunks++;
21392138
}
21402139

2141-
out_len = chunks;
2142-
if (endlen !=0 && out_len > INT_MAX/endlen) {
2143-
return NULL;
2144-
}
2145-
out_len *= endlen;
2146-
if (out_len > INT_MAX - srclen) {
2147-
return NULL;
2148-
}
2149-
out_len += srclen;
2150-
2151-
dest = zend_string_alloc(out_len * sizeof(char), 0);
2140+
dest = zend_string_safe_alloc(chunks, endlen, srclen, 0);
21522141

21532142
for (p = src, q = ZSTR_VAL(dest); p < (src + srclen - chunklen + 1); ) {
21542143
memcpy(q, p, chunklen);
@@ -2172,7 +2161,7 @@ static zend_string *php_chunk_split(const char *src, size_t srclen, const char *
21722161
}
21732162
/* }}} */
21742163

2175-
/* {{{ proto string|false chunk_split(string str [, int chunklen [, string ending]])
2164+
/* {{{ proto string chunk_split(string str [, int chunklen [, string ending]])
21762165
Returns split line */
21772166
PHP_FUNCTION(chunk_split)
21782167
{
@@ -2209,11 +2198,7 @@ PHP_FUNCTION(chunk_split)
22092198

22102199
result = php_chunk_split(ZSTR_VAL(str), ZSTR_LEN(str), end, endlen, (size_t)chunklen);
22112200

2212-
if (result) {
2213-
RETURN_STR(result);
2214-
} else {
2215-
RETURN_FALSE;
2216-
}
2201+
RETURN_STR(result);
22172202
}
22182203
/* }}} */
22192204

ext/standard/tests/strings/chunk_split.phpt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,6 @@ echo chunk_split('foooooooooooooooo', 5)."\n";
77
echo chunk_split(str_repeat('X', 2*76))."\n";
88
echo chunk_split("test", 10, "|end") . "\n";
99

10-
$a=str_repeat("B", 65535);
11-
$b=1;
12-
$c=str_repeat("B", 65535);
13-
var_dump(chunk_split($a,$b,$c));
14-
15-
$a=str_repeat("B", 65537);
16-
$b=1;
17-
$c=str_repeat("B", 65537);
18-
var_dump(chunk_split($a,$b,$c));
19-
20-
2110
?>
2211
--EXPECT--
2312
a-b-c-
@@ -30,5 +19,3 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3019
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3120

3221
test|end
33-
bool(false)
34-
bool(false)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Test chunk_split() function : usage variations - unexpected large '$end' string argument variation 1
3+
--SKIPIF--
4+
<?php
5+
if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only");
6+
?>
7+
--FILE--
8+
<?php
9+
/* Prototype : string chunk_split(string $str [, int $chunklen [, string $ending]])
10+
* Description: Returns split line
11+
* Source code: ext/standard/string.c
12+
* Alias to functions: none
13+
*/
14+
15+
echo "*** Testing chunk_split() : unexpected large 'end' string argument variation 1 ***\n";
16+
17+
$a=str_repeat("B", 65535);
18+
$b=1;
19+
$c=str_repeat("B", 65535);
20+
var_dump(chunk_split($a,$b,$c));
21+
?>
22+
--EXPECTF--
23+
*** Testing chunk_split() : unexpected large 'end' string argument variation 1 ***
24+
25+
Fatal error: Possible integer overflow in memory allocation (65536 * 65535 + 65556) in %s on line %d
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Test chunk_split() function : usage variations - unexpected large '$end' string argument variation 1
3+
--SKIPIF--
4+
<?php
5+
if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only");
6+
?>
7+
--FILE--
8+
<?php
9+
/* Prototype : string chunk_split(string $str [, int $chunklen [, string $ending]])
10+
* Description: Returns split line
11+
* Source code: ext/standard/string.c
12+
* Alias to functions: none
13+
*/
14+
15+
echo "*** Testing chunk_split() : unexpected large 'end' string argument variation 1 ***\n";
16+
17+
$a=str_repeat("B", 65535);
18+
$b=1;
19+
$c=str_repeat("B", 65535);
20+
var_dump(chunk_split($a,$b,$c));
21+
?>
22+
--EXPECTF--
23+
*** Testing chunk_split() : unexpected large 'end' string argument variation 1 ***
24+
25+
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Test chunk_split() function : usage variations - unexpected large '$end' string argument variation 2
3+
--SKIPIF--
4+
<?php
5+
if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only");
6+
?>
7+
--FILE--
8+
<?php
9+
/* Prototype : string chunk_split(string $str [, int $chunklen [, string $ending]])
10+
* Description: Returns split line
11+
* Source code: ext/standard/string.c
12+
* Alias to functions: none
13+
*/
14+
15+
echo "*** Testing chunk_split() : unexpected large 'end' string argument variation 2 ***\n";
16+
17+
$a=str_repeat("B", 65537);
18+
$b=1;
19+
$c=str_repeat("B", 65537);
20+
var_dump(chunk_split($a,$b,$c));
21+
?>
22+
--EXPECTF--
23+
*** Testing chunk_split() : unexpected large 'end' string argument variation 2 ***
24+
25+
Fatal error: Possible integer overflow in memory allocation (65538 * 65537 + 65556) in %s on line %d
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Test chunk_split() function : usage variations - unexpected large '$end' string argument variation 2
3+
--SKIPIF--
4+
<?php
5+
if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only");
6+
?>
7+
--FILE--
8+
<?php
9+
/* Prototype : string chunk_split(string $str [, int $chunklen [, string $ending]])
10+
* Description: Returns split line
11+
* Source code: ext/standard/string.c
12+
* Alias to functions: none
13+
*/
14+
15+
echo "*** Testing chunk_split() : unexpected large 'end' string argument variation 2 ***\n";
16+
17+
$a=str_repeat("B", 65537);
18+
$b=1;
19+
$c=str_repeat("B", 65537);
20+
var_dump(chunk_split($a,$b,$c));
21+
?>
22+
--EXPECTF--
23+
*** Testing chunk_split() : unexpected large 'end' string argument variation 2 ***
24+
25+
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Test chunk_split() function : usage variations - unexpected large number of chunks
3+
--FILE--
4+
<?php
5+
/* Prototype : string chunk_split(string $str [, int $chunklen [, string $ending]])
6+
* Description: Returns split line
7+
* Source code: ext/standard/string.c
8+
* Alias to functions: none
9+
*/
10+
11+
$chunk_length = 1;
12+
13+
echo "*** Testing chunk_split() : unexpected large 'end' string argument variation 2 ***\n";
14+
15+
echo "Body generation\n";
16+
$body = str_repeat("Hello", 10000000);
17+
18+
echo "Using chunk_split()\n";
19+
var_dump(chunk_split($body, $chunk_length));
20+
?>
21+
--EXPECTF--
22+
*** Testing chunk_split() : unexpected large 'end' string argument variation 2 ***
23+
Body generation
24+
Using chunk_split()
25+
26+
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d

0 commit comments

Comments
 (0)