php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67467 print_r with $return=true outputs its argument if it is too large
Submitted: 2014-06-18 16:38 UTC Modified: 2017-07-05 08:26 UTC
Votes:4
Avg. Score:4.2 ± 0.8
Reproduced:4 of 4 (100.0%)
Same Version:2 (50.0%)
Same OS:2 (50.0%)
From: igor at wiedler dot ch Assigned:
Status: Open Package: Output Control
PHP Version: 5.5.13 OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: igor at wiedler dot ch
New email:
PHP Version: OS:

 

 [2014-06-18 16:38 UTC] igor at wiedler dot ch
Description:
------------
Sufficiently large nested structures will cause print_r to output its first argument, even if the second $return argument is true.

From a glance at how print_r works, it appears to be using output buffering internally. If the output written to the buffer is too large, it will be implicitly flushed.

This is quite a serious problem, as one can easily expose the entire application state accidentally.

This has been reproduced in the FPM and CLI SAPIs.

Test script:
---------------
<?php
ini_set('memory_limit', '512M');
$a = [];
for ($i = 0; $i < 10000; $i++) {
    $a = [$i, $a];
}
print_r($a, true);


Expected result:
----------------
Blank.

Actual result:
--------------
Array
(
    [0] => 9999
    [1] => Array
        (
            [0] => 9998
            [1] => Array
                (
                    [0] => 9997
                    [1] => Array
                        (

...

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-06-20 08:41 UTC] arjen at react dot com
Duplicate of #66928 and #51362
 [2014-06-20 13:13 UTC] johannes@php.net
-Status: Open +Status: Duplicate
 [2015-10-07 09:48 UTC] nikic@php.net
-Status: Duplicate +Status: Open
 [2015-10-07 09:48 UTC] nikic@php.net
PR for this: https://github.com/php/php-src/pull/1554

A side-effect of this change would be that if print_r is used in "print" mode and we go out of memory, nothing will be printed (so the reverse of the issue here). I don't know if that's a problem.

Alternatively (or additionally), we could change the OB flushing condition in http://lxr.php.net/xref/PHP_TRUNK/main/main.c#1768. Probably the `(size_t)PG(memory_limit) < zend_memory_usage(1)` part of the check doesn't do what it's supposed to, as the memory usage will always be lower than the limit (we only *tried* to go higher and failed). We could drop this part. However this would mean we don't flush OB on other fatal errors either. Which may or may not be a problem.
 [2015-10-07 12:07 UTC] nikic@php.net
Thinking about it again, we should change the condition to never flush on fatals. This situation is not unique to memory_limit, same could happen with the time limit as well. There's really no reason why a fatal error, which can occur pretty much anywhere, would trigger an OB flush.
 [2017-07-05 08:26 UTC] nikic@php.net
This specific issue is fixed as of PHP 7.2, but I still think that we should drop the OB flushing on OOM entirely.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Oct 08 05:01:27 2024 UTC