php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65593 Segfault when calling ob_start from output buffering callback.
Submitted: 2013-08-30 12:15 UTC Modified: 2015-02-18 12:00 UTC
Votes:3
Avg. Score:1.7 ± 0.9
Reproduced:1 of 3 (33.3%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: arjen at react dot com Assigned: mike (profile)
Status: Closed Package: Reproducible crash
PHP Version: 5.4Git-2013-08-30 (Git) OS: Linux
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: arjen at react dot com
New email:
PHP Version: OS:

 

 [2013-08-30 12:15 UTC] arjen at react dot com
Description:
------------
Unfortunately no easy to further reduce the testscript.
You have to run it using php -e to be able to reproduce it consistently. However, 
it IS possible to generate without -e.

And yes, calling ob_start from output buffer handler is stupid. We found this by 
accident :-)

Test script:
---------------
https://gist.github.com/arjenschol/6389030#file-testscript

Expected result:
----------------
No segfault, just the fatal error.

Actual result:
--------------
See https://gist.github.com/arjenschol/6389030 for a backtrace.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-06-05 11:35 UTC] arjen at react dot com
This still crashes 5.5.12 (and 5.6.0beta3):

Fatal error: Cannot destroy active lambda function in /mnt/serve-a-lot_arjen/public_html/php/bug65593.php on line 12
*** Error in `/home/arjen/phpdebug/phpfarm/inst/php-5.5.12/bin/php': double free or corruption (!prev): 0x00000000013327d0 ***

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5d03a40 in malloc_consolidate () from /usr/lib/libc.so.6
(gdb) bt
#0  0x00007ffff5d03a40 in malloc_consolidate () from /usr/lib/libc.so.6
#1  0x00007ffff5d04e14 in _int_malloc () from /usr/lib/libc.so.6
#2  0x00007ffff5d07ac7 in calloc () from /usr/lib/libc.so.6
#3  0x00007ffff7de6c37 in _dl_new_object () from /lib64/ld-linux-x86-64.so.2
#4  0x00007ffff7de2204 in _dl_map_object_from_fd () from /lib64/ld-linux-x86-64.so.2
#5  0x00007ffff7de44bb in _dl_map_object () from /lib64/ld-linux-x86-64.so.2
#6  0x00007ffff7def253 in dl_open_worker () from /lib64/ld-linux-x86-64.so.2
#7  0x00007ffff7deaf04 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#8  0x00007ffff7deec23 in _dl_open () from /lib64/ld-linux-x86-64.so.2
#9  0x00007ffff5da8b3d in do_dlopen () from /usr/lib/libc.so.6
#10 0x00007ffff7deaf04 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#11 0x00007ffff5da8bcf in dlerror_run () from /usr/lib/libc.so.6
#12 0x00007ffff5da8c41 in __libc_dlopen_mode () from /usr/lib/libc.so.6
#13 0x00007ffff5d806b5 in init () from /usr/lib/libc.so.6
#14 0x00007ffff5a78f90 in pthread_once () from /usr/lib/libpthread.so.0
#15 0x00007ffff5d807cc in backtrace () from /usr/lib/libc.so.6
#16 0x00007ffff5ca9a44 in backtrace_and_maps () from /usr/lib/libc.so.6
#17 0x00007ffff5cfdf8e in __libc_message () from /usr/lib/libc.so.6
#18 0x00007ffff5d0388e in malloc_printerr () from /usr/lib/libc.so.6
#19 0x00007ffff5d0404b in _int_free () from /usr/lib/libc.so.6
#20 0x0000000000883350 in _efree (ptr=0x13327d0, __zend_filename=0xdd5238 "/home/arjen/phpdebug/phpfarm/src/php-5.5.12/main/output.c", __zend_lineno=718, __zend_orig_filename=0x0, __zend_orig_lineno=0)
    at /home/arjen/phpdebug/phpfarm/src/php-5.5.12/Zend/zend_alloc.c:2437
#21 0x0000000000840da8 in php_output_handler_dtor (handler=0x132fb00) at /home/arjen/phpdebug/phpfarm/src/php-5.5.12/main/output.c:718
#22 0x0000000000840e6b in php_output_handler_free (h=0x132ffc0) at /home/arjen/phpdebug/phpfarm/src/php-5.5.12/main/output.c:735
#23 0x000000000083fabb in php_output_deactivate () at /home/arjen/phpdebug/phpfarm/src/php-5.5.12/main/output.c:184
#24 0x0000000000828aeb in php_request_shutdown (dummy=0x0) at /home/arjen/phpdebug/phpfarm/src/php-5.5.12/main/main.c:1783
#25 0x0000000000969caa in do_cli (argc=2, argv=0x1143060) at /home/arjen/phpdebug/phpfarm/src/php-5.5.12/sapi/cli/php_cli.c:1177
#26 0x000000000096a39d in main (argc=2, argv=0x1143060) at /home/arjen/phpdebug/phpfarm/src/php-5.5.12/sapi/cli/php_cli.c:1378
 [2014-11-19 09:13 UTC] mike@php.net
-Status: Open +Status: Feedback
 [2014-11-19 09:13 UTC] mike@php.net
Doesn't seem to be an issue anymore?
 [2014-11-19 12:22 UTC] arjen at react dot com
-Status: Feedback +Status: Open
 [2014-11-19 12:22 UTC] arjen at react dot com
php has to be compiled in debug mode:

php-5.6.3/bin/php ~/public_html/php/bug65593.php 
PHP Fatal error:  Cannot destroy active lambda function in ~/public_html/php/bug65593.php on line 12

Fatal error: Cannot destroy active lambda function in ~/public_html/php/bug65593.php on line 12
[Wed Nov 19 13:15:22 2014]  Script:  '~/public_html/php/bug65593.php'
---------------------------------------
~/phpdebug/phpfarm/src/php-5.6.3/main/output.c(717) : Block 0x7f5a1f63ad08 status:
Beginning:  	Cached
Freed (invalid)
    Start:	OK
      End:	OK
---------------------------------------
[Wed Nov 19 13:15:22 2014]  Script:  '~/public_html/php/bug65593.php'
---------------------------------------
~/phpdebug/phpfarm/src/php-5.6.3/main/output.c(718) : Block 0x7f5a1f4649c8 status:
Beginning:  	Freed
    Start:	OK
      End:	Overflown (magic=0x0000005A instead of 0x2373547F)
          	At least 4 bytes overflown
---------------------------------------


Testscript can be reduced to https://gist.github.com/arjenschol/6389030#file-test-php
 [2015-02-17 14:21 UTC] laruence@php.net
-Assigned To: +Assigned To: mike
 [2015-02-17 14:21 UTC] laruence@php.net
also exists in 5.5+
 [2015-02-17 14:29 UTC] laruence@php.net
we need a way to indicate dtor is called:

diff --git a/main/output.c b/main/output.c
index f9b8a68..34b638f 100644
--- a/main/output.c
+++ b/main/output.c
@@ -714,7 +714,13 @@ PHPAPI int php_output_handler_hook(php_output_handler_hook_t type, void *arg TSR
  * Destroy an output handler */
 PHPAPI void php_output_handler_dtor(php_output_handler *handler TSRMLS_DC)
 {
-	STR_FREE(handler->name);
+	if (handler->name) {
+		STR_FREE(handler->name);
+		handler->name = NULL; /* prevent recursively calling to this */
+	} else {
+		return;
+	}
+
 	STR_FREE(handler->buffer.data);
 	if (handler->flags & PHP_OUTPUT_HANDLER_USER) {
 		zval_ptr_dtor(&handler->func.user->zoh);
 [2015-02-18 11:32 UTC] mike@php.net
Simpler test case:

ob_start(function(){ob_start();});

The ob layer was not written with closures in mind.
Actually I faced the exact same problem in several other extensions.

@laruence, why ain't the closure just put in the GC if it cant be destroyed now?
 [2015-02-18 12:00 UTC] mike@php.net
Shouldn't the engine increase the refcount of the closure while it is executing?
 [2015-02-18 13:09 UTC] mike@php.net
Automatic comment on behalf of mike
Revision: http://git.php.net/?p=php-src.git;a=commit;h=225af964c0324b2bf14e44c0fad77198b97cc06c
Log: Fixed bug #65593 (Segfault when calling ob_start from output buffering callback)
 [2015-02-18 13:09 UTC] mike@php.net
-Status: Assigned +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC