php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #26938 exec does not read consecutive long lines correctly
Submitted: 2004-01-16 16:38 UTC Modified: 2004-01-21 11:51 UTC
From: runekl at opoint dot com Assigned:
Status: Closed Package: Program Execution
PHP Version: 5CVS OS: *
Private report: No CVE-ID:
 [2004-01-16 16:38 UTC] runekl at opoint dot com
Description:
------------
Exec fails to read two consecutive lines longer than 2*EXEC_INPUT_BUF correctly.  While reading the first line, buflen is set to 3*EXEC_INPUT_BUF.  When reading part two of the second line, bufl will be EXEC_INPUT_BUF to large since b!=buf.

Here is a patch:

Index: exec.c
===================================================================
RCS file: /repository/php-src/ext/standard/exec.c,v
retrieving revision 1.108
diff -C4 -r1.108 exec.c
*** exec.c      8 Jan 2004 08:17:31 -0000       1.108
--- exec.c      16 Jan 2004 21:35:35 -0000
***************
*** 111,132 ****

        if (type != 3) {
                b = buf;

!               while (php_stream_get_line(stream, b, EXEC_INPUT_BUF, &bufl)) {
                        /* no new line found, let's read some more */
                        if (b[bufl - 1] != '\n' && !php_stream_eof(stream)) {
                                if (buflen < (bufl + (b - buf) + EXEC_INPUT_BUF)) {
                                        bufl += b - buf;
!                                       buflen = bufl + EXEC_INPUT_BUF;
                                        buf = erealloc(buf, buflen);
                                        b = buf + bufl;
                                } else {
                                        b += bufl;
                                }
                                continue;
                        } else if (b != buf) {
!                               bufl += buflen - EXEC_INPUT_BUF;
                        }

                        if (type == 1) {
                                PHPWRITE(buf, bufl);
--- 111,132 ----

        if (type != 3) {
                b = buf;

!               while (php_stream_get_line(stream, b, buflen - (b - buf), &bufl)) {
                        /* no new line found, let's read some more */
                        if (b[bufl - 1] != '\n' && !php_stream_eof(stream)) {
                                if (buflen < (bufl + (b - buf) + EXEC_INPUT_BUF)) {
                                        bufl += b - buf;
!                                       buflen = bufl + 1 + EXEC_INPUT_BUF;
                                        buf = erealloc(buf, buflen);
                                        b = buf + bufl;
                                } else {
                                        b += bufl;
                                }
                                continue;
                        } else if (b != buf) {
!                               bufl += (b - buf);
                        }

                        if (type == 1) {
                                PHPWRITE(buf, bufl);



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-01-17 10:20 UTC] runekl at opoint dot com
I suggest you replace the test for bug 26615 with the one below.  That should cover both cases.  It will also make your distribution smaller -)

--TEST--
Bug #26615 (exec crash on long input lines)
--FILE--
<?php
$out = array();
$status = -1;
$php = getenv('TEST_PHP_EXECUTABLE');
exec($php . ' -r \'' 
     . '$lengths = array(10,20000,10000,5,10000,3);'
     . 'foreach($lengths as $length) {'
     . '  for($i=0;$i<$length;$i++) print chr(65+$i % 27);'
     . '  print "\n";'
     . '}\'', $out, $status);
for ($i=0;$i<6;$i++)
     print "md5(line $i)= " . md5($out[$i]) . " (length " . strlen($out[$i]) . ")\n";
?>
--EXPECT--
md5(line 0)= e86410fa2d6e2634fd8ac5f4b3afe7f3 (length 10)
md5(line 1)= e84debf3a1d132871d7fe45c1c04c566 (length 20000)
md5(line 2)= c33b4d2f86908eea5d75ee5a61fd81f4 (length 10000)
md5(line 3)= 2ecdde3959051d913f61b14579ea136d (length 5)
md5(line 4)= c33b4d2f86908eea5d75ee5a61fd81f4 (length 10000)
md5(line 5)= 902fbdd2b1df0c4f70b4a5d23525e932 (length 3)
 [2004-01-18 16:11 UTC] runekl at opoint dot com
I get the this when running the test I have suggested.

md5(line 0)= e86410fa2d6e2634fd8ac5f4b3afe7f3 (length 10)
md5(line 1)= e84debf3a1d132871d7fe45c1c04c566 (length 20000)
md5(line 2)= 2713d01e967adfd64c49857370ab420b (length 18191)
md5(line 3)= 2ecdde3959051d913f61b14579ea136d (length 5)
md5(line 4)= 2713d01e967adfd64c49857370ab420b (length 18191)
md5(line 5)= 902fbdd2b1df0c4f70b4a5d23525e932 (length 3)

Look at the lines 2 and 4.  The lines to read are 10000 characters long, but PHP 'reads' 18191 bytes, e.g. 2*EXEC_INPUT_BUF-1 to much.  The extra characters come from line 1.

With the patch in my first post I get correct output.

Since test 26615 does not test reading long lines good enough and is about a bug in the same loop, I suggest replacing it.
 [2004-01-19 19:44 UTC] sniper@php.net
I can reproduce this now, got the same result.
Can you provide that patch in unified diff format? (diff -u)

 [2004-01-20 01:05 UTC] runekl at opoint dot com
Here it is:

Index: exec.c
===================================================================
RCS file: /repository/php-src/ext/standard/exec.c,v
retrieving revision 1.108
diff -u -r1.108 exec.c
--- exec.c      8 Jan 2004 08:17:31 -0000       1.108
+++ exec.c      20 Jan 2004 06:07:37 -0000
@@ -112,12 +112,12 @@
        if (type != 3) {
                b = buf;

-               while (php_stream_get_line(stream, b, EXEC_INPUT_BUF, &bufl)) {
+               while (php_stream_get_line(stream, b, buflen - (b - buf), &bufl)) {
                        /* no new line found, let's read some more */
                        if (b[bufl - 1] != '\n' && !php_stream_eof(stream)) {
                                if (buflen < (bufl + (b - buf) + EXEC_INPUT_BUF)) {
                                        bufl += b - buf;
-                                       buflen = bufl + EXEC_INPUT_BUF;
+                                       buflen = bufl + 1 + EXEC_INPUT_BUF;
                                        buf = erealloc(buf, buflen);
                                        b = buf + bufl;
                                } else {
@@ -125,7 +125,7 @@
                                }
                                continue;
                        } else if (b != buf) {
-                               bufl += buflen - EXEC_INPUT_BUF;
+                               bufl += (b - buf);
                        }

                        if (type == 1) {
 [2004-01-21 11:51 UTC] iliaa@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

 
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sat Apr 19 14:01:50 2014 UTC