php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #54199 callin ob_end_... in ob_start callback function cause stack overflow
Submitted: 2011-03-09 00:39 UTC Modified: 2012-06-09 22:35 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: keidii at gmail dot com Assigned:
Status: Not a bug Package: Output Control
PHP Version: 5.3 OS: Linux (other not tested)
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: keidii at gmail dot com
New email:
PHP Version: OS:

 

 [2011-03-09 00:39 UTC] keidii at gmail dot com
Description:
------------
After calling ob_end_{flush|clean}()  inside ob callback function 
PHP run into infinite call loop. This results in SIGSEGV or SIGILL process termination caused by stack overflow.

Tested on php 5.2 and 5.3  (apache and cli)

Latest tested version (compiled with debug):
PHP 5.3.5 (cli) (built: Mar  8 2011 23:29:45) (DEBUG)
Copyright (c) 1997-2010 The PHP Group

----------------------------------------------------------

valgrind output fragment:
(always end with stack grow error)

==5925== Process terminating with default action of signal 11 (SIGSEGV)
==5925==  Access not within mapped region at address 0xBE363FFC
==5925==    at 0x402685B: bcmp (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5925== Stack overflow in thread 1: can't grow stack to 0xBE363FF0


----------------------------------------------------------

gdb: it crash on random function after stack is full.

[testrun1]
(gdb) r -f obtest.php
Starting program: /tmp/php/php-5.3.5/sapi/cli/php -f obtest.php
[Thread debugging using libthread_db enabled]
[New process 6663]
[New Thread -1210878272 (LWP 6663)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1210878272 (LWP 6663)]
zend_parse_va_args (num_args=0, type_spec=0x835d484 "", va=0xbf7620e0, flags=0) at /tmp/php/php-5.3.5/Zend/zend_API.c:679
679		int arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);

[testrun2]
(gdb) r -f obtest.php
Starting program: /tmp/php/php-5.3.5/sapi/cli/php -f obtest.php
[Thread debugging using libthread_db enabled]
[New process 6701]
[New Thread -1210427712 (LWP 6701)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1210427712 (LWP 6701)]
0xb7e2dc69 in ?? () from /lib/libc.so.6



----------------------------------------------------------

backtrace: (mor than 5k entries)
#0  zend_parse_va_args 
#1  0x0820516c in zend_parse_parameters 
#2  0x081ae3d4 in zif_ob_end_clean 
#3  0x0822fc0c in zend_do_fcall_common_helper_SPEC 
#4  0x08233750 in ZEND_DO_FCALL_SPEC_CONST_HANDLER 
#5  0x0822f2a9 in execute 
#6  0x081f4bc6 in zend_call_function 
#7  0x081f3f70 in call_user_function_ex 
#8  0x081acb0b in php_end_ob_buffer 
#9  0x081ae47c in zif_ob_end_clean 
#10 0x0822fc0c in zend_do_fcall_common_helper_SPEC 
#11 0x08233750 in ZEND_DO_FCALL_SPEC_CONST_HANDLER 
#12 0x0822f2a9 in execute 
#13 0x081f4bc6 in zend_call_function 
#14 0x081f3f70 in call_user_function_ex 
#15 0x081acb0b in php_end_ob_buffer 
#16 0x081ae47c in zif_ob_end_clean 
#17 0x0822fc0c in zend_do_fcall_common_helper_SPEC 
#18 0x08233750 in ZEND_DO_FCALL_SPEC_CONST_HANDLER 
#19 0x0822f2a9 in execute 
#20 0x081f4bc6 in zend_call_function 
#21 0x081f3f70 in call_user_function_ex 
#22 0x081acb0b in php_end_ob_buffer 
#23 0x081ae47c in zif_ob_end_clean 
#24 0x0822fc0c in zend_do_fcall_common_helper_SPEC 
#25 0x08233750 in ZEND_DO_FCALL_SPEC_CONST_HANDLER 
#26 0x0822f2a9 in execute
(...)

----------------------------------------------------------






Test script:
---------------
<?PHP

function catcher_test(){
 ob_end_clean(); // OR ob_end_flush();
 //^-- should produce E_NOTICE
 die("killed!");
}

ob_start( 'catcher_test' );            

echo "test output";
die("force-ob-end"); // ob termination by die()
?>




Expected result:
----------------
ob_end_clean() and ob_end_flush() doc:

"If the function fails it generates an E_NOTICE. "

After ob termination and before calling ob callback function [set in ob_start(func)] buffering should be terminated.
 

Actual result:
--------------
ob seems not to be terminated before calling callback function.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-03-09 01:00 UTC] keidii at gmail dot com
-PHP Version: 5.3.6RC2 +PHP Version: 5.3
 [2011-03-09 01:00 UTC] keidii at gmail dot com
version change
 [2011-03-09 12:57 UTC] felipe@php.net
-Type: Bug +Type: Security -Package: Security related +Package: Output Control -Private report: N +Private report: Y
 [2011-03-09 13:06 UTC] felipe@php.net
-Type: Security +Type: Bug
 [2011-03-09 13:06 UTC] felipe@php.net
The documentation says: "ob_end_clean(), ob_end_flush(), ob_clean(), ob_flush() and ob_start() may not be called from a callback function. If you call them from callback function, the behavior is undefined. If you would like to delete the contents of a buffer, return "" (a null string) from callback function."
 [2012-06-09 22:35 UTC] frozenfire@php.net
-Status: Open +Status: Not a bug
 [2012-06-09 22:35 UTC] frozenfire@php.net
This is a documented behaviour, that is not a bug. The documentation notes that 
affecting the contents or state of the output buffer itself from within the 
output buffer callback as an undefined behaviour.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 14:01:32 2024 UTC