Bug #65784 [Com]: Segfault with finally

From: Date: Mon, 09 Dec 2013 03:24:24 +0000
Subject: Bug #65784 [Com]: Segfault with finally
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-183198@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=65784&edit=1 ID: 65784 Comment by: phpmpan at mpan dot pl Reported by: r dot wilczek at web-appz dot de Summary: Segfault with finally Status: Open Type: Bug Package: *General Issues Operating System: Linux PHP Version: 5.5.4 Block user comment: N Private report: N New Comment: Minimal code to reproduce: ------------------------------------------------------- function foo() { try { throw new \Exception(); return true; } finally { try { throw new \Exception(); } catch (\Exception $e) { } } } $bar = foo(); ------------------------------------------------------- Clean gdb backtrace from php -f for master snap: ------------------------------------------------------- #0 0x0000000000639587 in zval_isref_p (pz=0x0) at /tmp/php-master-201312082230/Zend/zend.h:415 #1 0x000000000063d47f in zend_assign_to_variable (variable_ptr_ptr=0x7ffff7fc3bc0, value=0x0) at /tmp/php-master-201312082230/Zend/zend_execute.c:916 #2 0x000000000069d558 in ZEND_ASSIGN_SPEC_CV_VAR_HANDLER (execute_data=0x7ffff7f891f0) at /tmp/php-master-201312082230/Zend/zend_vm_execute.h:36797 #3 0x000000000063f4dd in execute_ex (execute_data=0x7ffff7f891f0) at /tmp/php-master-201312082230/Zend/zend_vm_execute.h:363 #4 0x000000000063f54e in zend_execute (op_array=0x7ffff7fc0498) at /tmp/php-master-201312082230/Zend/zend_vm_execute.h:388 #5 0x0000000000600773 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /tmp/php-master-201312082230/Zend/zend.c:1334 #6 0x000000000057a2b9 in php_execute_script (primary_file=0x7fffffffe490) at /tmp/php-master-201312082230/main/main.c:2507 #7 0x00000000006a8cf6 in do_cli (argc=3, argv=0xa3ba90) at /tmp/php-master-201312082230/sapi/cli/php_cli.c:994 #8 0x00000000006a9cc4 in main (argc=3, argv=0xa3ba90) at /tmp/php-master-201312082230/sapi/cli/php_cli.c:1378 ------------------------------------------------------- A quick dive into the code suggests that something bad happens around the catch. After this piece of code FAST_RET, instead of passing the outer exception higher, goes to ASSIGN. However, the function never provides a return value to copy from and as a result an unexpected NULL flies around ZEND_ASSIGN_SPEC_CV_VAR_HANDLER. Previous Comments: ------------------------------------------------------------------------ [2013-11-25 20:33:43] crussell52 at gmail dot com core-dump info from my example: #0 zval_delref_p (execute_data=0xb7f12234) at /opt/src/apache2.4/php-5.5.5/Zend/zend.h:409 #1 zend_pzval_unlock_func (execute_data=0xb7f12234) at /opt/src/apache2.4/php-5.5.5/Zend/zend_execute.c:72 #2 _get_zval_ptr_var (execute_data=0xb7f12234) at /opt/src/apache2.4/php-5.5.5/Zend/zend_execute.c:186 #3 ZEND_ASSIGN_SPEC_CV_VAR_HANDLER (execute_data=0xb7f12234) at /opt/src/apache2.4/php-5.5.5/Zend/zend_vm_execute.h:36995 #4 0x012b7496 in execute_ex (execute_data=0xb7f12234) at /opt/src/apache2.4/php-5.5.5/Zend/zend_vm_execute.h:363 #5 0x007f3f35 in xdebug_execute_ex (execute_data=0xb7f12234) at /opt/src/apache2.4/xdebug-2.2.3/xdebug.c:1437 #6 0x012cf5cf in ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER (execute_data=0xb7f12160) at /opt/src/apache2.4/php-5.5.5/Zend/zend_vm_execute.h:13418 #7 0x012b7496 in execute_ex (execute_data=0xb7f12160) at /opt/src/apache2.4/php-5.5.5/Zend/zend_vm_execute.h:363 #8 0x007f3f35 in xdebug_execute_ex (execute_data=0xb7f12160) at /opt/src/apache2.4/xdebug-2.2.3/xdebug.c:1437 #9 0x01286fe5 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /opt/src/apache2.4/php-5.5.5/Zend/zend.c:1320 #10 0x0122a3cf in php_execute_script (primary_file=0xbfd233c0) at /opt/src/apache2.4/php-5.5.5/main/main.c:2489 #11 0x0132812b in php_handler (r=0x9eb98c8) at /opt/src/apache2.4/php-5.5.5/sapi/apache2handler/sapi_apache2.c:667 #12 0x08098037 in ?? () ------------------------------------------------------------------------ [2013-11-25 20:16:54] crussell52 at gmail dot com The following script in php 5.5.5 demonstrates this problem. Note, my testing indicates that all of these conditions must be true: 1. Exception is thrown in try block. 2. An Exception is thrown AND handled during execution of the corresponding finally block. 3. The return value must be referenced. ----------------- class Executor { public function go() { try { // 1. Throw exception in try block. throw new Exception("Failed to do something!"); return true; } finally { // 2. Throw and handle exception within finally block. // Note, this step could occur in a function/method which // is called within the finally block. try { throw new Exception("Failed to clean up."); } catch (Exception $E) { /* Ignore */ } } } } $Executor = new Executor(); // 3. Reference the return value. $value = $Executor->go(); ----------------- #3 is interesting and threw me off a bit while trying to come up with a reproduction script. See the following variations and outcome: $value = $Executor->go(); // fail echo $Executor->go(); // fail $Executor->go(); // success ------------------------------------------------------------------------ [2013-10-15 11:54:52] php-bugs at lists dot php dot net No feedback was provided. The bug is being suspended because we assume that you are no longer experiencing the problem. If this is not the case and you are able to provide the information that was requested earlier, please do so and change the status of the bug back to "Re-Opened". Thank you. ------------------------------------------------------------------------ [2013-10-03 11:53:28] r dot wilczek at web-appz dot de Here you are ... /* @var $sql string */ /* @var $expr SomeInterface */ /* @var $ctxt AnotherInterface */ $trx = $this->ctxt->beginTransaction(); // an interface $memento = $this->ctxt->getMemento(); // can be anything try { $this->ctxt->persist(); // don't return or throw exception return $this->execute($expr, $sql); // return scalar[] or throw exception } finally { $this->ctxt->setMemento($memento); // don't return or throw exception $trx->rollback(); // don't return or throw exception } Don't know, if this helps. What I forgot to mention was, that the segfault occurs, when there is an exception thrown from within the try-block. ------------------------------------------------------------------------ [2013-10-01 22:58:15] nikic@php.net Could you please post the code as it is actually used (just the part containing the finally)? Your backtrace indicates that the segfault happens during an argument send, but your code samples do not include any function calls with arguments. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=65784 -- Edit this bug report at https://bugs.php.net/bug.php?id=65784&edit=1

« previous php.bugs (#183198) next »