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
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
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

Add a Patch

Pull Requests

Add a Pull Request

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 Apr 16 11:01:29 2024 UTC