]> granicus.if.org Git - php/commitdiff
Fixed bug #61019 (Out of memory on command stream_get_contents)
authorMichael Wallner <mike@php.net>
Wed, 2 Apr 2014 13:36:39 +0000 (15:36 +0200)
committerMichael Wallner <mike@php.net>
Wed, 2 Apr 2014 13:36:39 +0000 (15:36 +0200)
NEWS
ext/standard/tests/streams/bug61019.phpt [new file with mode: 0644]
main/streams/streams.c

diff --git a/NEWS b/NEWS
index 51ed4f30ee92e9b0460ca24b466494b6be3ce85f..bc329ade53354998fb2ec4b1c24c4a202552792c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ PHP                                                                        NEWS
 ?? ??? 2014, PHP 5.4.28
 
 - Core:
+  . Fixed bug #61019 (Out of memory on command stream_get_contents). (Mike)
   . Fixed bug #64330 (stream_socket_server() creates wrong Abstract Namespace 
     UNIX sockets). (Mike)
 
diff --git a/ext/standard/tests/streams/bug61019.phpt b/ext/standard/tests/streams/bug61019.phpt
new file mode 100644 (file)
index 0000000..45b207e
--- /dev/null
@@ -0,0 +1,78 @@
+--TEST--
+Bug #61019 (Out of memory on command stream_get_contents)
+--FILE--
+<?php
+
+echo "Test\n";
+
+$descriptorspec = array(
+       0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
+       1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
+       2 => array("pipe", "w")   // stderr is a pipe that the child will write to
+);
+
+$process=proc_open("echo testtext",$descriptorspec,$pipes);
+if(is_resource($process))
+{
+       stream_set_blocking($pipes[0],false);
+       stream_set_blocking($pipes[1],false);
+       stream_set_blocking($pipes[2],false);
+       stream_set_write_buffer($pipes[0],0);
+       stream_set_read_buffer($pipes[1],0);
+       stream_set_read_buffer($pipes[2],0);
+       $stdin_stream="";
+       $stderr_stream="";
+
+       echo "External command executed\n";     
+       do                                      
+       {
+               $process_state=proc_get_status($process);
+               $tmp_stdin=stream_get_contents($pipes[1]);      
+               if($tmp_stdin) 
+               {
+                       $stdin_stream=$stdin_stream.$tmp_stdin;
+               }
+               $tmp_stderr=stream_get_contents($pipes[2]);
+               if($tmp_stderr) 
+               {
+                       $stderr_stream=$stderr_stream.$tmp_stderr;
+               }
+       } while($process_state['running']);
+
+       echo "External command exit: ".$process_state['exitcode']."\n";
+
+       //read outstanding data
+       $tmp_stdin=stream_get_contents($pipes[1]);      
+       if($tmp_stdin) 
+       {
+               $stdin_stream=$stdin_stream.$tmp_stdin;
+       }
+       $tmp_stderr=stream_get_contents($pipes[2]);
+       if($tmp_stderr) 
+       {
+               $stderr_stream=$stderr_stream.$tmp_stderr;
+       }
+
+       fclose ($pipes[0]);
+       fclose ($pipes[1]);
+       fclose ($pipes[2]);
+
+       proc_close($process);    
+
+       echo "STDOUT: ".$stdin_stream."\n";
+       echo "STDERR: ".$stderr_stream."\n";
+}
+else
+{
+       echo "Can't start external command\n";
+}
+?>
+===DONE===
+--EXPECT--
+Test
+External command executed
+External command exit: 0
+STDOUT: testtext
+
+STDERR: 
+===DONE===
index cac50ef03fa9106502109a724e205f043da5ef8e..acc67dc2078c3c8066b7a0827cfb959b380912e2 100644 (file)
@@ -736,6 +736,10 @@ PHPAPI size_t _php_stream_read(php_stream *stream, char *buf, size_t size TSRMLS
 
                if (!stream->readfilters.head && (stream->flags & PHP_STREAM_FLAG_NO_BUFFER || stream->chunk_size == 1)) {
                        toread = stream->ops->read(stream, buf, size TSRMLS_CC);
+                       if (toread == (size_t) -1) {
+                               /* e.g. underlying read(2) returned -1 */
+                               break;
+                       }
                } else {
                        php_stream_fill_read_buffer(stream, size TSRMLS_CC);