summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-01-23 14:58:01 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-01-23 14:58:10 +0100
commit6489e2983159be3b8f4482a2cdf29438d0e1610a (patch)
treead074dc45ea116248d546620ace6015895d18bd1
parent3f020aef85f13e5d6749314cedd1e0e1c5e64ab0 (diff)
parent67421a780d670ea2eec8157c39f2682bb3cfb7dd (diff)
downloadphp-git-6489e2983159be3b8f4482a2cdf29438d0e1610a.tar.gz
Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3: Fixed bug #78902 Add unit test for bug #78902
-rw-r--r--NEWS3
-rw-r--r--ext/standard/tests/streams/bug78902.phpt28
-rw-r--r--main/streams/streams.c11
3 files changed, 40 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index 2dac44405a..bf3e34e71c 100644
--- a/NEWS
+++ b/NEWS
@@ -37,6 +37,9 @@ PHP NEWS
. Fixed bug #79115 (ReflectionClass::isCloneable call reflected class
__destruct). (Nikita)
+- Standard:
+ . Fixed bug #78902 (Memory leak when using stream_filter_append). (liudaixiao)
+
23 Jan 2020, PHP 7.4.2
- Core:
diff --git a/ext/standard/tests/streams/bug78902.phpt b/ext/standard/tests/streams/bug78902.phpt
new file mode 100644
index 0000000000..1216c89bc2
--- /dev/null
+++ b/ext/standard/tests/streams/bug78902.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #78902: Memory leak when using stream_filter_append
+--INI--
+memory_limit=512k
+--FILE--
+<?php
+
+/** create temporary file 2mb file */
+$tmp_file_name = tempnam(sys_get_temp_dir(), 'test_');
+$fp = fopen($tmp_file_name, 'w+');
+$size = 1024 * 1024 * 2; // 2mb
+$chunk = 1024;
+while ($size > 0) {
+ fputs($fp, str_pad('', min($chunk,$size)));
+ $size -= $chunk;
+}
+fclose($fp);
+
+$fp = fopen($tmp_file_name, 'r');
+stream_filter_append($fp, "string.toupper");
+while (!feof($fp)) {
+ fread($fp, 1);
+}
+fclose($fp);
+var_dump(true);
+?>
+--EXPECT--
+bool(true)
diff --git a/main/streams/streams.c b/main/streams/streams.c
index ce370941a8..f269f06f3e 100644
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -590,8 +590,15 @@ PHPAPI int _php_stream_fill_read_buffer(php_stream *stream, size_t size)
* stream read buffer */
while (brig_inp->head) {
bucket = brig_inp->head;
- /* grow buffer to hold this bucket
- * TODO: this can fail for persistent streams */
+ /* reduce buffer memory consumption if possible, to avoid a realloc */
+ if (stream->readbuf && stream->readbuflen - stream->writepos < bucket->buflen) {
+ if (stream->writepos > stream->readpos) {
+ memmove(stream->readbuf, stream->readbuf + stream->readpos, stream->writepos - stream->readpos);
+ }
+ stream->writepos -= stream->readpos;
+ stream->readpos = 0;
+ }
+ /* grow buffer to hold this bucket */
if (stream->readbuflen - stream->writepos < bucket->buflen) {
stream->readbuflen += bucket->buflen;
stream->readbuf = perealloc(stream->readbuf, stream->readbuflen,