]> granicus.if.org Git - php/commitdiff
Remove memory exhaustion checks in php_chunk_split()
authorGeorge Peter Banyard <girgias@php.net>
Fri, 23 Aug 2019 23:52:17 +0000 (01:52 +0200)
committerGeorge Peter Banyard <girgias@php.net>
Mon, 26 Aug 2019 15:14:49 +0000 (17:14 +0200)
ext/standard/string.c
ext/standard/tests/strings/chunk_split.phpt
ext/standard/tests/strings/chunk_split_variation1_32bit.phpt [new file with mode: 0644]
ext/standard/tests/strings/chunk_split_variation2_32bit.phpt [new file with mode: 0644]
ext/standard/tests/strings/chunk_split_variation3.phpt [new file with mode: 0644]

index 526eb1353a55c733823b6f8e29363132d4d02d8e..e9a584aa29034613d937cfdf6873cb26e370c27e 100644 (file)
@@ -2105,7 +2105,6 @@ static zend_string *php_chunk_split(const char *src, size_t srclen, const char *
        const char *p;
        size_t chunks;
        size_t restlen;
-       size_t out_len;
        zend_string *dest;
 
        chunks = srclen / chunklen;
@@ -2116,17 +2115,7 @@ static zend_string *php_chunk_split(const char *src, size_t srclen, const char *
                chunks++;
        }
 
-       out_len = chunks;
-       if (endlen !=0 && out_len > INT_MAX/endlen) {
-               return NULL;
-       }
-       out_len *= endlen;
-       if (out_len > INT_MAX - srclen) {
-               return NULL;
-       }
-       out_len += srclen;
-
-       dest = zend_string_alloc(out_len * sizeof(char), 0);
+       dest = zend_string_safe_alloc(chunks, endlen, srclen, 0);
 
        for (p = src, q = ZSTR_VAL(dest); p < (src + srclen - chunklen + 1); ) {
                memcpy(q, p, chunklen);
@@ -2150,7 +2139,7 @@ static zend_string *php_chunk_split(const char *src, size_t srclen, const char *
 }
 /* }}} */
 
-/* {{{ proto string|false chunk_split(string str [, int chunklen [, string ending]])
+/* {{{ proto string chunk_split(string str [, int chunklen [, string ending]])
    Returns split line */
 PHP_FUNCTION(chunk_split)
 {
@@ -2187,11 +2176,7 @@ PHP_FUNCTION(chunk_split)
 
        result = php_chunk_split(ZSTR_VAL(str), ZSTR_LEN(str), end, endlen, (size_t)chunklen);
 
-       if (result) {
-               RETURN_STR(result);
-       } else {
-               RETURN_FALSE;
-       }
+       RETURN_STR(result);
 }
 /* }}} */
 
index 648388f23a8e98df95c0f1be665de1e2ee051912..a2696cd26b20bfea001f20d253aa7c0ceb2409f7 100644 (file)
@@ -7,17 +7,6 @@ echo chunk_split('foooooooooooooooo', 5)."\n";
 echo chunk_split(str_repeat('X', 2*76))."\n";
 echo chunk_split("test", 10, "|end") . "\n";
 
-$a=str_repeat("B", 65535);
-$b=1;
-$c=str_repeat("B", 65535);
-var_dump(chunk_split($a,$b,$c));
-
-$a=str_repeat("B", 65537);
-$b=1;
-$c=str_repeat("B", 65537);
-var_dump(chunk_split($a,$b,$c));
-
-
 ?>
 --EXPECT--
 a-b-c-
@@ -30,5 +19,3 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 
 test|end
-bool(false)
-bool(false)
diff --git a/ext/standard/tests/strings/chunk_split_variation1_32bit.phpt b/ext/standard/tests/strings/chunk_split_variation1_32bit.phpt
new file mode 100644 (file)
index 0000000..be673dd
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+Test chunk_split() function : usage variations - unexpected large '$end' string argument variation 1
+--SKIPIF--
+<?php
+if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only");
+?>
+--FILE--
+<?php
+/* Prototype  : string chunk_split(string $str [, int $chunklen [, string $ending]])
+ * Description: Returns split line
+ * Source code: ext/standard/string.c
+ * Alias to functions: none
+*/
+
+echo "*** Testing chunk_split() : unexpected large 'end' string argument variation 1 ***\n";
+
+$a=str_repeat("B", 65535);
+$b=1;
+$c=str_repeat("B", 65535);
+var_dump(chunk_split($a,$b,$c));
+?>
+--EXPECTF--
+*** Testing chunk_split() : unexpected large 'end' string argument variation 1 ***
+
+Fatal error: Allowed memory size of %d bytes exhausted at %s (tried to allocate %d bytes) in %s on line %d
diff --git a/ext/standard/tests/strings/chunk_split_variation2_32bit.phpt b/ext/standard/tests/strings/chunk_split_variation2_32bit.phpt
new file mode 100644 (file)
index 0000000..ca0948d
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+Test chunk_split() function : usage variations - unexpected large '$end' string argument variation 2
+--SKIPIF--
+<?php
+if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only");
+?>
+--FILE--
+<?php
+/* Prototype  : string chunk_split(string $str [, int $chunklen [, string $ending]])
+ * Description: Returns split line
+ * Source code: ext/standard/string.c
+ * Alias to functions: none
+*/
+
+echo "*** Testing chunk_split() : unexpected large 'end' string argument variation 2 ***\n";
+
+$a=str_repeat("B", 65537);
+$b=1;
+$c=str_repeat("B", 65537);
+var_dump(chunk_split($a,$b,$c));
+?>
+--EXPECTF--
+*** Testing chunk_split() : unexpected large 'end' string argument variation 2 ***
+
+Fatal error: Possible integer overflow in memory allocation (65537 * 65537 + 65556) in %s on line %d
diff --git a/ext/standard/tests/strings/chunk_split_variation3.phpt b/ext/standard/tests/strings/chunk_split_variation3.phpt
new file mode 100644 (file)
index 0000000..687aa08
--- /dev/null
@@ -0,0 +1,26 @@
+--TEST--
+Test chunk_split() function : usage variations - unexpected large number of chunks
+--FILE--
+<?php
+/* Prototype  : string chunk_split(string $str [, int $chunklen [, string $ending]])
+ * Description: Returns split line
+ * Source code: ext/standard/string.c
+ * Alias to functions: none
+*/
+
+$chunk_length = 1;
+
+echo "*** Testing chunk_split() : unexpected large 'end' string argument variation 2 ***\n";
+
+echo "Body generation\n";
+$body = str_repeat("Hello", 10000000);
+
+echo "Using chunk_split()\n";
+var_dump(chunk_split($body, $chunk_length));
+?>
+--EXPECTF--
+*** Testing chunk_split() : unexpected large 'end' string argument variation 2 ***
+Body generation
+Using chunk_split()
+
+Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d