phalcon/cphalcon — pull request #1131 by sjinks (2013-08-22 02:40:20+00:00)
Title: Fix segfault on exception when RVO is used

Scenario:

```c
PHP_METHOD(SomeClass, someMethod)
{
phalcon_call_method_p0_ex(return_value, return_value_ptr, this_ptr, "anotherMethod");
}
```

If SomeClass::anotherMethod() throws an exception, phalcon_alt_call_method() will destroy its return_value (which is the same as SomeClass::someMethod()'s return_value) and set it to NULL. When SomeClass::someMethod() returns, EG(exception) will not be NULL and phalcon_alt_call_method() will try to destroy the already destroyed return_value and will crash.

Something like this:
```
#0 0x0000000000976502 in zval_delref_p (pz=0x0) at /tmp/php-build/source/5.5.0/Zend/zend.h:409
#1 0x000000000097675f in i_zval_ptr_dtor (zval_ptr=0x0, __zend_filename=0x7f47df285898 "/home/vladimir/workspace/cphalcon/ext/kernel/alternative/fcall.c", __zend_lineno=839) at /tmp/php-build/source/5.5.0/Zend/zend_execute.h:76
#2 0x0000000000977a3c in _zval_ptr_dtor (zval_ptr=0x7fff526fd2b8, __zend_filename=0x7f47df285898 "/home/vladimir/workspace/cphalcon/ext/kernel/alternative/fcall.c", __zend_lineno=839)
at /tmp/php-build/source/5.5.0/Zend/zend_execute_API.c:426
#3 0x00007f47df03c360 in phalcon_alt_call_method (fci=0x7fff526fcfe0, ce=0x33ac140, hash_key=10432451519307380380, method_name=0x7f47df4d7e28 "_getexpression", method_len=14, method_key=11293103426560632820)
at /home/vladimir/workspace/cphalcon/ext/kernel/alternative/fcall.c:839
#4 0x00007f47df03c985 in phalcon_alt_call_user_method (ce=0x33ac140, object_pp=0x7fff526fd078, method_name=0x7f47df4d7e28 "_getexpression", method_len=14, retval_ptr=0x7f47daa6b920, retval_ptr_ptr=0x7fff526fd2b8, param_count=1,
params=0x7fff526fd0c0, method_key=11293103426560632820) at /home/vladimir/workspace/cphalcon/ext/kernel/alternative/fcall.c:959
#5 0x00007f47df01b505 in phalcon_call_method_vparams (return_value=0x7f47daa6b920, return_value_ptr=0x7fff526fd2b8, object=0x7f47daa66590, method_name=0x7f47df4d7e28 "_getexpression", method_len=14, method_key=11293103426560632820,
param_count=1, ap=0x7fff526fd168) at /home/vladimir/workspace/cphalcon/ext/kernel/fcall.c:255
#6 0x00007f47df01bc45 in phalcon_call_method_params (return_value=0x0, return_value_ptr=0x7fff526fd2b8, object=0x7f47daa66590, method_name=0x7f47df4d7e28 "_getexpression", method_len=14, method_key=11293103426560632820, param_count=1)
at /home/vladimir/workspace/cphalcon/ext/kernel/fcall.c:391
#7 0x00007f47df1607df in zim_Phalcon_Mvc_Model_Query__getSelectColumn (ht=1, return_value=0x7f47daa6b538, return_value_ptr=0x7fff526fd530, this_ptr=0x7f47daa66590, return_value_used=1)
at /home/vladimir/workspace/cphalcon/ext/mvc/model/query.c:1190
#8 0x00007f47df03c31e in phalcon_alt_call_method (fci=0x7fff526fd580, ce=0x33ac140, hash_key=12003194334336468502, method_name=0x7f47df4d886c "_getselectcolumn", method_len=16, method_key=16594755089970257330)
at /home/vladimir/workspace/cphalcon/ext/kernel/alternative/fcall.c:831
#9 0x00007f47df03c985 in phalcon_alt_call_user_method (ce=0x33ac140, object_pp=0x7fff526fd618, method_name=0x7f47df4d886c "_getselectcolumn", method_len=16, retval_ptr=0x7f47daa6ace0, retval_ptr_ptr=0x0, param_count=1,
params=0x7fff526fd660, method_key=16594755089970257330) at /home/vladimir/workspace/cphalcon/ext/kernel/alternative/fcall.c:959
#10 0x00007f47df01b505 in phalcon_call_method_vparams (return_value=0x7f47daa6ace0, return_value_ptr=0x0, object=0x7f47daa66590, method_name=0x7f47df4d886c "_getselectcolumn", method_len=16, method_key=16594755089970257330,
param_count=1, ap=0x7fff526fd708) at /home/vladimir/workspace/cphalcon/ext/kernel/fcall.c:255
#11 0x00007f47df01bc45 in phalcon_call_method_params (return_value=0x7f47daa6ace0, return_value_ptr=0x0, object=0x7f47daa66590, method_name=0x7f47df4d886c "_getselectcolumn", method_len=16, method_key=16594755089970257330,
param_count=1) at /home/vladimir/workspace/cphalcon/ext/kernel/fcall.c:391
#12 0x00007f47df16a0a2 in zim_Phalcon_Mvc_Model_Query__prepareSelect (ht=0, return_value=0x7f47daa69d58, return_value_ptr=0x7fff526fdc20, this_ptr=0x7f47daa66590, return_value_used=1)
at /home/vladimir/workspace/cphalcon/ext/mvc/model/query.c:2613
#13 0x00007f47df03c31e in phalcon_alt_call_method (fci=0x7fff526fdc70, ce=0x33ac140, hash_key=5007302758549953425, method_name=0x7f47df4d8935 "_prepareselect", method_len=14, method_key=11087669581410963027)
at /home/vladimir/workspace/cphalcon/ext/kernel/alternative/fcall.c:831
#14 0x00007f47df03c985 in phalcon_alt_call_user_method (ce=0x33ac140, object_pp=0x7fff526fdd08, method_name=0x7f47df4d8935 "_prepareselect", method_len=14, retval_ptr=0x7f47daa64e08, retval_ptr_ptr=0x0, param_count=0, params=0xeed4f8,
method_key=11087669581410963027) at /home/vladimir/workspace/cphalcon/ext/kernel/alternative/fcall.c:959
#15 0x00007f47df01b505 in phalcon_call_method_vparams (return_value=0x7f47daa64e08, return_value_ptr=0x0, object=0x7f47daa66590, method_name=0x7f47df4d8935 "_prepareselect", method_len=14, method_key=11087669581410963027,
param_count=0, ap=0x7fff526fddf8) at /home/vladimir/workspace/cphalcon/ext/kernel/fcall.c:255
#16 0x00007f47df01bc45 in phalcon_call_method_params (return_value=0x7f47daa64e08, return_value_ptr=0x0, object=0x7f47daa66590, method_name=0x7f47df4d8935 "_prepareselect", method_len=14, method_key=11087669581410963027, param_count=0)
at /home/vladimir/workspace/cphalcon/ext/kernel/fcall.c:391
#17 0x00007f47df16fdec in zim_Phalcon_Mvc_Model_Query_parse (ht=0, return_value=0x7f47daa638a8, return_value_ptr=0x7f47eb59ff70, this_ptr=0x7f47daa66590, return_value_used=1)
at /home/vladimir/workspace/cphalcon/ext/mvc/model/query.c:3408
#18 0x00007f47df0171ac in phalcon_execute_internal (execute_data_ptr=0x7f47eb5a10e8, fci=0x0, return_value_used=1) at /home/vladimir/workspace/cphalcon/ext/phalcon.c:371
#19 0x00000000009cc6c9 in zend_do_fcall_common_helper_SPEC (execute_data=0x7f47eb5a10e8) at /tmp/php-build/source/5.5.0/Zend/zend_vm_execute.h:545
#20 0x00000000009cce6b in ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER (execute_data=0x7f47eb5a10e8) at /tmp/php-build/source/5.5.0/Zend/zend_vm_execute.h:678
#21 0x00000000009cbd8a in execute_ex (execute_data=0x7f47eb5a10e8) at /tmp/php-build/source/5.5.0/Zend/zend_vm_execute.h:356
#22 0x00000000009cbe12 in zend_execute (op_array=0x7f47eb5bffc8) at /tmp/php-build/source/5.5.0/Zend/zend_vm_execute.h:381
#23 0x000000000098d6f4 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /tmp/php-build/source/5.5.0/Zend/zend.c:1316
#24 0x00000000008f5783 in php_execute_script (primary_file=0x7fff52700590) at /tmp/php-build/source/5.5.0/main/main.c:2481
#25 0x0000000000a3bbaf in do_cli (argc=4, argv=0x2fdc600) at /tmp/php-build/source/5.5.0/sapi/cli/php_cli.c:993
#26 0x0000000000a3ceed in main (argc=4, argv=0x2fdc600) at /tmp/php-build/source/5.5.0/sapi/cli/php_cli.c:1377
```

This happened for this case:
```
$ $(phpenv which php) unit-tests/manual-unit.php ModelsQueryParsingTest.php ModelsQueryParsingTest
Testing ModelsQueryParsingTest SQLSTATE[HY000] [2002] No such file or directory
#0 [internal function]: PDO->__construct('mysql:host=loca...', 'root', 'M1dn19ht', Array)
#1 [internal function]: Phalcon\Db\Adapter\Pdo->connect(Array)
#2 /home/vladimir/workspace/cphalcon/unit-tests/ModelsQueryParsingTest.php(62): Phalcon\Db\Adapter\Pdo->__construct(Array)
#3 [internal function]: ModelsQueryParsingTest->{closure}()
#4 [internal function]: Phalcon\DI\Service->resolve(NULL, Object(Phalcon\DI))
#5 [internal function]: Phalcon\DI->get('db', NULL)
#6 [internal function]: Phalcon\DI->getShared('db')
#7 [internal function]: Phalcon\Mvc\Model\Manager->getReadConnection(Object(Robots))
#8 [internal function]: Phalcon\Mvc\Model->getReadConnection()
#9 [internal function]: Phalcon\Mvc\Model\MetaData\Strategy\Introspection->getMetaData(Object(Robots), Object(Phalcon\DI))
#10 [internal function]: Phalcon\Mvc\Model\MetaData->_initialize(Object(Robots), 'robots-robots', 'robots', NULL)
#11 [internal function]: Phalcon\Mvc\Model\MetaData->readMetaData(Object(Robots))
#12 [internal function]: Phalcon\Mvc\Model\MetaData->hasAttribute(Object(Robots), 'id')
#13 [internal function]: Phalcon\Mvc\Model\Query->_getQualified(Array)
#14 [internal function]: Phalcon\Mvc\Model\Query->_getExpression(Array)
#15 [internal function]: Phalcon\Mvc\Model\Query->_getSelectColumn(Array)
#16 [internal function]: Phalcon\Mvc\Model\Query->_prepareSelect()
#17 /home/vladimir/workspace/cphalcon/unit-tests/ModelsQueryParsingTest.php(262): Phalcon\Mvc\Model\Query->parse()
#18 /home/vladimir/workspace/cphalcon/unit-tests/manual-unit.php(119): ModelsQueryParsingTest->testSelectParsing()
#19 /home/vladimir/workspace/cphalcon/unit-tests/manual-unit.php(154): PHPUnit_Framework_TestCase::main('ModelsQueryPars...')
#20 {main}
```

**This is a temporary fix** as it only covers the case when the methods are called by Phalcon using its phalcon_call_XXX() functions. It does **not** cover the scenario when SomeClass::someMethod() is called from the userspace.