php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #47020 print_r produces output with $return set to true
Submitted: 2009-01-06 14:05 UTC Modified: 2009-01-15 16:45 UTC
Votes:3
Avg. Score:3.0 ± 0.0
Reproduced:3 of 3 (100.0%)
Same Version:2 (66.7%)
Same OS:0 (0.0%)
From: kulminaator at gmail dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.2.8 OS: Mac OS X 10.5.6
Private report: No CVE-ID: None
 [2009-01-06 14:05 UTC] kulminaator at gmail dot com
Description:
------------
print_r creates output although it was not asked to

The code 

$str = print_r($expression, true);  

should never produce any output, but it does if php hits the memory limit closely enough.

My memory_limit is set to 128M (may be this has to be the same to reproduce the bug).

Needless to say, this is a security issue and may output information to clients that never should go there by the code.

Reproduce code:
---------------
<?php
// php.ini has memory limit at  128M
$limit = (str_replace('M','',ini_get('memory_limit')))*1024*1024;
print "Memory limit is $limit bytes\n";
$data = str_repeat('x', $limit / 3 );
$x = print_r($data, true);

Expected result:
----------------
Out of memory error or no output at all.

Actual result:
--------------
The huge amount of x-es (xxxxxxxxxxxx about 40 million times) followed by 

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 44739243 bytes) in /private/tmp/proof_of_concept.php on line 6

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-01-06 15:19 UTC] finsoft at gmail dot com
Same thing reproduced on PHP Version 5.2.6, Windows XP Pro SP3, Apache 2.2.8
 [2009-01-15 15:22 UTC] jani@php.net
This has nothing to do with print_r(). Fix your php.ini not to output errors. 
 [2009-01-15 15:45 UTC] kulminaator at gmail dot com
even with display_errors set to Off or zero, output is still produced
 [2009-01-15 16:45 UTC] kulminaator at gmail dot com
After looking around a bit, this extra output of xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx like data is caused by the weird behaviour of ob_start/ob_end and the fact that output buffers are always flushed when a fatal error is coughed up from below.

straight from the source of ext/standard/basic_functions.c

PHP_FUNCTION(print_r)
{
    zval *var;
    zend_bool i = 0;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &var, &i) == FAILURE) {
        RETURN_FALSE;
    }

    if (i) {
        php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
    }

    zend_print_zval_r(var, 0 TSRMLS_CC);

    if (i) {
        php_ob_get_buffer (return_value TSRMLS_CC);
        php_end_ob_buffer (0, 0 TSRMLS_CC);
    } else {
        RETURN_TRUE;
    }
}


Here the zend_print_zval_r causes creating/appending to ob , ob hits the memory limit and bang, the output is created, although it never should be.

Can we hope for a fix (either root out the issue of ob being flushed or avoiding ob in the first place ?) or are supposed to remove all sensitive data from ever reaching print_r ?
 [2010-06-30 13:53 UTC] cxscott at uk dot insight dot com
I can confirm that this is definitely an issue, even with error reporting set to off. I'm using PHP 5.3.2 running on 64-bit Red Hat Linux.
 [2010-10-22 12:52 UTC] spaze-bugs at exploited dot cz
The same issue was present in var_export() though that's now fixed in 5.3.3:
"Rewrote var_export() to use smart_str rather than output buffering, prevents data disclosure if a fatal error occurs (CVE-2010-2531). (Scott)"
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sat Jul 05 12:01:34 2025 UTC