php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #70601 Segfault in gc_remove_from_buffer()
Submitted: 2015-09-29 03:45 UTC Modified: 2015-10-04 02:39 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:1 (50.0%)
From: p at wspnr dot com Assigned: laruence (profile)
Status: Closed Package: Reproducible crash
PHP Version: 5.6Git-2015-09-29 (Git) OS: Debian x86_64
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: p at wspnr dot com
New email:
PHP Version: OS:

 

 [2015-09-29 03:45 UTC] p at wspnr dot com
Description:
------------
There is a reliable segfault observed in one of our applications. After the first segfault, each additional request also results in a segfault. The only solution is to restart PHP-FPM.

This has been tested and reproduced on several machines, all running Debian Jessie.

This bug has been observed on 5.6.12 and 5.6.15-dev (latest Git). It HAS NOT been observed on 7.0.0RC3 or 7.1.0-dev (latest Git).




 

Test script:
---------------
I have tried to create a short test script to reproduce the bug, but have been unsuccessful. It happens reliably in one high-load use case where 100+ requests are sent to the server almost concurrently. Each request creates many objects, so it is possible that GC is triggered. After ~30 requests are processed, the first crash happens.

Expected result:
----------------
No crash, or at least a sensible error message.

Actual result:
--------------
Core was generated by `php-fpm: pool www                                                 '.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00000000009fdc2e in gc_remove_from_buffer (root=0x596d7c <zm_startup_dom+20924>) at Zend/zend_gc.h:189
189             root->next->prev = root->prev;
(gdb) bt
#0  0x00000000009fdc2e in gc_remove_from_buffer (root=0x596d7c <zm_startup_dom+20924>) at Zend/zend_gc.h:189
#1  0x00000000009fdbf4 in gc_remove_zval_from_buffer (zv=0x7f3652bddda0) at Zend/zend_gc.c:260
#2  0x00000000009ad125 in i_zval_ptr_dtor (zval_ptr=0x7f3652bddda0, __zend_filename=0xf8eadb "/.../php-src/Zend/zend_variables.c", __zend_lineno=188) at Zend/zend_execute.h:78
#3  0x00000000009acc56 in _zval_ptr_dtor (zval_ptr=0x2840318, __zend_filename=0xf8eadb "/.../php-src/Zend/zend_variables.c", __zend_lineno=188) at Zend/zend_execute_API.c:424
#4  0x00000000009c4ba1 in _zval_ptr_dtor_wrapper (zval_ptr=0x2840318) at Zend/zend_variables.c:188
#5  0x00000000009dee9e in zend_hash_destroy (ht=0x283e678) at Zend/zend_hash.c:548
#6  0x00000000009c46f9 in _zval_dtor_func (zvalue=0x25fef38, __zend_filename=0xf8db06 "Zend/zend_execute.h", __zend_lineno=79) at Zend/zend_variables.c:45
#7  0x0000000000a7085c in _zval_dtor (zvalue=0x25fef38, __zend_filename=0xf8db06 "Zend/zend_execute.h", __zend_lineno=79) at Zend/zend_variables.h:35
#8  0x0000000000a7062a in i_zval_ptr_dtor (zval_ptr=0x25fef38, __zend_filename=0xf8db06 "Zend/zend_execute.h", __zend_lineno=308) at Zend/zend_execute.h:79
#9  0x0000000000a70727 in zend_vm_stack_clear_multiple (nested=0) at Zend/zend_execute.h:308
#10 0x0000000000a6f561 in zend_do_fcall_common_helper_SPEC (execute_data=0x2723740) at Zend/zend_vm_execute.h:650
#11 0x0000000000a2a873 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0x2723740) at Zend/zend_vm_execute.h:2602
#12 0x0000000000a14138 in execute_ex (execute_data=0x2723740) at Zend/zend_vm_execute.h:363
#13 0x0000000000a1421e in zend_execute (op_array=0x275cf38) at Zend/zend_vm_execute.h:388
#14 0x00000000009c8e87 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at Zend/zend.c:1341
#15 0x00000000009139f8 in php_execute_script (primary_file=0x7ffe0a895820) at main/main.c:2597
#16 0x0000000000aa891b in main (argc=4, argv=0x7ffe0a8959a8) at /.../php-src/sapi/fpm/fpm/fpm_main.c:1964

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-10-02 14:25 UTC] laruence@php.net
-Status: Open +Status: Feedback
 [2015-10-02 14:25 UTC] laruence@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc. If the script requires a 
database to demonstrate the issue, please make sure it creates 
all necessary tables, stored procedures etc.

Please avoid embedding huge scripts into the report.

I am sorry, but if no reproduce script provided, we can not do much things here..
 [2015-10-03 10:11 UTC] p at wspnr dot com
-Status: Feedback +Status: Open
 [2015-10-03 10:11 UTC] p at wspnr dot com
After some poking around with gdb, I've managed to narrow the issue down.
It only happens with opcache enabled, and with concurrent requests. I was using `ab -n 10000 -c 100 "http://my.server/crash.php"` to test.

The following code causes the issue to appear:

-- BEGIN CODE --

<?php

class a {
	const
            REPLACEMENTS_PASS_1 = [
        	"\x00" => "", "\x01" => "", "\x02" => "", "\x03" => "", 
		"\x04" => "", "\x05" => "", "\x06" => "", "\x07" => "", 
		"\x08" => "", "\x0B" => "", "\x0C" => "", "\x0D" => "", 
		"\x0E" => "", "\x0F" => "", "\x10" => "", "\x11" => "", 
		"\x12" => "", "\x13" => "", "\x14" => "", "\x15" => "", 
		"\x16" => "", "\x17" => "", "\x18" => "", "\x19" => "", 
		"\x1A" => "", "\x1B" => "", "\x1C" => "", "\x1D" => "", 
		"\x1E" => "", "\x1F" => "", "\x7F" => "",
    ];
	
	public function __construct() {
		echo strtr("abcd", self::REPLACEMENTS_PASS_1);
	}
}

new a();


-- END CODE --
 [2015-10-03 16:38 UTC] laruence@php.net
-Assigned To: +Assigned To: laruence
 [2015-10-03 16:38 UTC] laruence@php.net
okey, great, thanks for the script, I get what's going wrong there, a quick fix could be:

diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c
index 4ed3dd4..949be9e 100644
--- a/ext/opcache/Optimizer/pass1_5.c
+++ b/ext/opcache/Optimizer/pass1_5.c
@@ -314,6 +314,8 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
 							    ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) {
 								break;
 							}
+						} else if (Z_TYPE_PP(c) == IS_ARRAY) {
+							break;
 						} else {
 							t = **c;
 							zval_copy_ctor(&t);



anyway, I need discuss with Dmitry about this before I commit it..

thanks
 [2015-10-03 16:41 UTC] laruence@php.net
-Status: Assigned +Status: Feedback
 [2015-10-03 16:41 UTC] laruence@php.net
hmm, forget to say: please help verify the fix. :)
 [2015-10-03 17:51 UTC] p at wspnr dot com
-Status: Feedback +Status: Assigned
 [2015-10-03 17:51 UTC] p at wspnr dot com
Applied patch and recompiled -- problem seems to be resolved!
 [2015-10-04 06:17 UTC] laruence@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=c147d90dbfcc4f9fd494215b7e5740e497d818c1
Log: Fixed bug #70601 (Segfault in gc_remove_from_buffer())
 [2015-10-04 06:17 UTC] laruence@php.net
-Status: Assigned +Status: Closed
 [2015-10-05 12:23 UTC] hajo dot passon at form4 dot de
We encounter the same problem on 5.5.9-1ubuntu4.13. In the backtrace the gdb shows the same problem at Zend/zend_gc.h:189.

Please, could someone backport the solution to 5.5?
 [2015-10-13 10:12 UTC] ab@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=c147d90dbfcc4f9fd494215b7e5740e497d818c1
Log: Fixed bug #70601 (Segfault in gc_remove_from_buffer())
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 28 19:01:28 2024 UTC