php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #49847 exec() confused by a specially crafted string
Submitted: 2009-10-12 16:57 UTC Modified: 2009-10-14 01:32 UTC
From: soner at comixwall dot org Assigned:
Status: Closed Package: Program Execution
PHP Version: 5.2.11 OS: OpenBSD, Linux, Windows
Private report: No CVE-ID:
 [2009-10-12 16:57 UTC] soner at comixwall dot org
Description:
------------
When shell command returns a specially crafted string, I get an empty
array as $output of exec(), instead of the string. I can very easily
reproduce this issue, please see below for test code.

Reproduce code:
---------------
Put the following lines in bug.php:

<?php
exec('php echostr.php', $output);
print_r($output);
?>

Then put the contents at the following link in echostr.php:
http://comixwall.org/dmdocuments/echostr

Expected result:
----------------
When you execute bug.php, you will get an empty array printed out:

Array
(
)

Actual result:
--------------
Actually, $output should have contained the string above as element 0 of the array.

If you delete or add a character in the string, exec() runs correctly and you get the intended result. So the issue is specific to this special string.

The problem is not with the size of the string, because much longer strings are fine.

Also this issue does *not* exists with passthru(), shell_exec() functions and backtick operator. Furthermore, exec() return value, i.e. the last line of shell command output seems fine too (it contains the string correctly). So I believe the issue is internal to exec(), effecting $output contents only.

As you can guess, this string is in fact serialized openvpn startup log lines (I just escaped the single quotes for testing purposes, that's all), it is not some manually crafted string. Therefore, it is possible that I may get more than one similar situation in the future.

I have confirmed this issue on OpenBSD, Linux, and Windows. Here are the versions:

OpenBSD:
PHP 5.2.8 with Suhosin-Patch 0.9.6.3 (cli) (built: Mar  1 2009 10:26:06) 
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
    with Suhosin v0.9.27, Copyright (c) 2007, by SektionEins GmbH

Linux:
PHP 5.2.6-3ubuntu4.2 with Suhosin-Patch 0.9.6.2 (cli) (built: Aug 21 2009 21:43:13) 
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies

Windows:
PHP 5.2.11 (cli) (built: Sep 16 2009 19:39:46)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies

Since Windows version is without Suhosin patch, suhosin as culprit is ruled out. (Also to test on Windows, I changed the exec shell command as 'php.exe echostr.php' of course.)


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-10-12 19:01 UTC] Sjoerd@php.net
The trick is that the string which is output is 4095 bytes long.

exec("printf %4095d 1", $output);
print_r($output);
 [2009-10-12 19:28 UTC] Sjoerd@php.net
From exec.c:125:
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)) {
		...
		continue;
		...
		add_next_index_stringl(array, buf, bufl, 1);

php_stream_get_line reads all the data. No newline is found, because there is none. The reading has not yet triggered php_stream_eof, because reading has stopped just before the bytes ran out. Loop starts again. php_stream_get_line now reads no bytes at all, because no bytes are left. Loop quits without adding the string to the array.
 [2009-10-12 20:20 UTC] Sjoerd@php.net
Filed Bug #49851 "HTTP breaks on long header line", which has the same cause.
 [2009-10-14 01:32 UTC] svn@php.net
Automatic comment from SVN on behalf of iliaa
Revision: http://svn.php.net/viewvc/?view=revision&revision=289624
Log: Fixed bug #49847 (exec() fails to return data inside 2nd parameter, given output lines >4095 bytes).
 [2009-10-14 01:32 UTC] iliaa@php.net
This bug has been fixed in SVN.

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.


 [2009-10-15 21:36 UTC] svn@php.net
Automatic comment from SVN on behalf of pajoye
Revision: http://svn.php.net/viewvc/?view=revision&revision=289688
Log: - Merge: #49847
 [2012-04-03 11:29 UTC] ab@php.net
Automatic comment on behalf of ab
Revision: http://git.php.net/?p=php-src.git;a=commit;h=14e74aeb579b3400bdf376b5b820fc900b4194ed
Log: Fix bug #61454 ext\standard\tests\general_functions\bug49847.phpt fails
 [2012-04-03 11:30 UTC] ab@php.net
Automatic comment on behalf of ab
Revision: http://git.php.net/?p=php-src.git;a=commit;h=84be455e22073a011af570c9bf9b79e42349b6a7
Log: Fix bug #61454 ext\standard\tests\general_functions\bug49847.phpt fails
 [2012-04-03 12:28 UTC] ab@php.net
Automatic comment on behalf of ab
Revision: http://git.php.net/?p=php-src.git;a=commit;h=14e74aeb579b3400bdf376b5b820fc900b4194ed
Log: Fix bug #61454 ext\standard\tests\general_functions\bug49847.phpt fails
 [2012-04-18 09:45 UTC] laruence@php.net
Automatic comment on behalf of ab
Revision: http://git.php.net/?p=php-src.git;a=commit;h=84be455e22073a011af570c9bf9b79e42349b6a7
Log: Fix bug #61454 ext\standard\tests\general_functions\bug49847.phpt fails
 [2012-07-24 23:36 UTC] rasmus@php.net
Automatic comment on behalf of ab
Revision: http://git.php.net/?p=php-src.git;a=commit;h=84be455e22073a011af570c9bf9b79e42349b6a7
Log: Fix bug #61454 ext\standard\tests\general_functions\bug49847.phpt fails
 [2013-11-17 09:32 UTC] laruence@php.net
Automatic comment on behalf of ab
Revision: http://git.php.net/?p=php-src.git;a=commit;h=84be455e22073a011af570c9bf9b79e42349b6a7
Log: Fix bug #61454 ext\standard\tests\general_functions\bug49847.phpt fails
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Wed Apr 23 18:01:55 2014 UTC