Edit report at https://bugs.php.net/bug.php?id=63914&edit=1
ID: 63914 Updated by: dmi...@php.net Reported by: whatthejeff at gmail dot com Summary: zend_do_fcall_common_helper_SPEC does not handle exceptions properly -Status: Assigned +Status: Closed Type: Bug Package: Scripting Engine problem Operating System: All PHP Version: Irrelevant Assigned To: dmitry Block user comment: N Private report: N New Comment: Automatic comment on behalf of dmi...@zend.com Revision: http://git.php.net/?p=php-src.git;a=commit;h=c4686b4de93a89e8265331b0d4a6a7954ccbae95 Log: Fixed bug #63914 (zend_do_fcall_common_helper_SPEC does not handle exceptions properly). (Jeff Welch) Previous Comments: ------------------------------------------------------------------------ [2013-03-25 03:16:54] s...@php.net Dmitry, could you review the proposed patch? ------------------------------------------------------------------------ [2013-01-06 01:27:33] whatthejeff at gmail dot com Pull request added: https://github.com/php/php-src/pull/250 ------------------------------------------------------------------------ [2013-01-06 00:35:00] whatthejeff at gmail dot com Description: ------------ The `zend_verify_arg_type` check in `zend_do_fcall_common_helper_SPEC` can generate unhanded exceptions when a user-defined error handler is set. This can lead to the following unexpected behaviors: * xdebug (and similar extensions using `execute_internal`) with PHP <= 5.4 will segfault (http://bugs.xdebug.org/view.php?id=897) * xdebug (and similar extensions using `execute_internal`) with PHP 5.5+ will continue to execute the internal function in an inconsistant state. * PHP without xdebug-like extensions will continue to execute the internal function, even though it's unnecessary. --- NOTE: I will send a pull request on github shortly. Test script: --------------- <?php class PHPUnit_Util_ErrorHandler { public static function handleError($errno, $errstr, $errfile, $errline) { throw new Exception; } } set_error_handler( array('PHPUnit_Util_ErrorHandler', 'handleError'), E_ALL | E_STRICT ); $dom = new DOMDocument; $dom->saveXML('foo'); Expected result: ---------------- Fatal error: Uncaught exception 'Exception' in /home/whatthejeff/php2/segfault.php:6 Stack trace: #0 [internal function]: PHPUnit_Util_ErrorHandler::handleError(4096, 'Argument 1 pass...', '/home/whattheje...', 16, Array) #1 /home/whatthejeff/php2/segfault.php(16): DOMDocument->saveXML('foo') #2 {main} thrown in /home/whatthejeff/php2/segfault.php on line 6 Actual result: -------------- GDB session with PHP 5.4 / xdebug (edited for brevity): ------------------------------------------------------- [whatthejeff@xdebug php2]$ gdb php ... (gdb) break zend_vm_execute.h:628 Breakpoint 1 at 0x870e1d: file /home/whatthejeff/php2/Zend/zend_vm_execute.h, line 628. (gdb) break zend_vm_execute.h:639 Breakpoint 2 at 0x870eb8: file /home/whatthejeff/php2/Zend/zend_vm_execute.h, line 639. (gdb) run segfault.php Starting program: /usr/local/bin/php segfault.php ... Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac0f8, tsrm_ls=0xff0090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:629 629 if (fbc->common.arg_info) { Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6_3.6.x86_64 nss-softokn-freebl-3.12.9-11.el6.x86_64 zlib-1.2.3-27.el6.x86_64 (gdb) c Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac0f8, tsrm_ls=0xff0090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:640 640 if (!zend_execute_internal) { (gdb) Continuing. Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac0f8, tsrm_ls=0xff0090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:629 629 if (fbc->common.arg_info) { (gdb) Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac0f8, tsrm_ls=0xff0090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:640 640 if (!zend_execute_internal) { (gdb) Continuing. Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac0f8, tsrm_ls=0xff0090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:629 629 if (fbc->common.arg_info) { (gdb) Continuing. Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac310, tsrm_ls=0xff0090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:629 629 if (fbc->common.arg_info) { (gdb) Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac310, tsrm_ls=0xff0090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:640 640 if (!zend_execute_internal) { (gdb) Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac0f8, tsrm_ls=0xff0090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:640 640 if (!zend_execute_internal) { (gdb) step 644 zend_execute_internal(execute_data, RETURN_VALUE_USED(opline) TSRMLS_CC); (gdb) xdebug_execute_internal (current_execute_data=0x7ffff7fac0f8, return_value_used=0, tsrm_ls=0xff0090) at /home/whatthejeff/xdebug/xdebug.c:1506 ... (gdb) 1547 execute_internal(current_execute_data, return_value_used TSRMLS_CC); (gdb) step execute_internal (execute_data_ptr=0x7ffff7fac0f8, return_value_used=0, tsrm_ls=0xff0090) at /home/whatthejeff/php2/Zend/zend_execute.c:1479 1479 zval **return_value_ptr = &(*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.var)).var.ptr; (gdb) 1480 ((zend_internal_function *) execute_data_ptr- >function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, (execute_data_ptr->function_state.function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC); (gdb) step zif_dom_document_savexml (ht=0, return_value=0x0, return_value_ptr=0x0, this_ptr=0x7ffff7fe5e00, return_value_used=0, tsrm_ls=0xff0090) at /home/whatthejeff/php2/ext/dom/document.c:1790 ... 1842 xmlDocDumpFormatMemory(docp, &mem, &size, format); (gdb) 1843 if (options & LIBXML_SAVE_NOEMPTYTAG) { (gdb) 1846 if (!size) { (gdb) 1849 RETVAL_STRINGL(mem, size, 1); (gdb) Program received signal SIGSEGV, Segmentation fault. 0x00000000005778de in zif_dom_document_savexml (ht=0, return_value=0x0, return_value_ptr=0x0, this_ptr=0x7ffff7fe5e00, return_value_used=0, tsrm_ls=0xff0090) at /home/whatthejeff/php2/ext/dom/document.c:1849 1849 RETVAL_STRINGL(mem, size, 1); GDB session with PHP 5.5 / xdebug (edited for brevity): ------------------------------------------------------- whatthejeff@xdebug php2]$ gdb php ... (gdb) break zend_vm_execute.h:532 Breakpoint 1 at 0x87a1b0: file /home/whatthejeff/php2/Zend/zend_vm_execute.h, line 532. (gdb) break zend_vm_execute.h:543 Breakpoint 2 at 0x87a24b: file /home/whatthejeff/php2/Zend/zend_vm_execute.h, line 543. (gdb) run segfault.php Starting program: /usr/local/bin/php segfault.php ... Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:533 533 if (fbc->common.arg_info) { (gdb) c Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:544 544 if (!zend_execute_internal) { (gdb) c Continuing. Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:533 533 if (fbc->common.arg_info) { (gdb) c Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:544 544 if (!zend_execute_internal) { (gdb) c Continuing. Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:533 533 if (fbc->common.arg_info) { (gdb) c Continuing. Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac380, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:533 533 if (fbc->common.arg_info) { (gdb) c Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac380, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:544 544 if (!zend_execute_internal) { (gdb) c Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:544 544 if (!zend_execute_internal) { (gdb) n 548 zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); (gdb) step xdebug_execute_internal (current_execute_data=0x7ffff7fac238, fci=0x0, return_value_used=0, tsrm_ls=0x100f090) at /home/whatthejeff/xdebug/xdebug.c:1506 ... 1553 execute_internal(current_execute_data, fci, return_value_used TSRMLS_CC); (gdb) step execute_internal (execute_data_ptr=0x7ffff7fac238, fci=0x0, return_value_used=0, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_execute.c:1481 ... 1487 ((zend_internal_function *) execute_data_ptr- >function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, (gdb) step zif_dom_document_savexml (ht=0, return_value=0x10917c0, return_value_ptr=0x0, this_ptr=0x7ffff7fe3cc8, return_value_used=0, tsrm_ls=0x100f090) at /home/whatthejeff/php2/ext/dom/document.c:1790 ... 1800 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|O!l", &id, dom_document_class_entry, &nodep, dom_node_class_entry, &options) == FAILURE) { (gdb) step zend_parse_method_parameters (num_args=0, tsrm_ls=0x100f090, this_ptr=0x7ffff7fe3cc8, type_spec=0xa76075 "O|O!l") at /home/whatthejeff/php2/Zend/zend_API.c:906 ... zif_dom_document_savexml (ht=0, return_value=0x10917c0, return_value_ptr=0x0, this_ptr=0x7ffff7fe3cc8, return_value_used=0, tsrm_ls=0x100f090) at /home/whatthejeff/php2/ext/dom/document.c:1804 1804 DOM_GET_OBJ(docp, id, xmlDocPtr, intern); (gdb) ... (gdb) 1849 RETVAL_STRINGL(mem, size, 1); (gdb) 1850 xmlFree(mem); GDB session with PHP 5.5 (edited for brevity): ---------------------------------------------- [whatthejeff@xdebug php2]$ gdb php ... (gdb) break zend_vm_execute.h:532 Breakpoint 1 at 0x87a1b0: file /home/whatthejeff/php2/Zend/zend_vm_execute.h, line 532. (gdb) break zend_vm_execute.h:543 Breakpoint 2 at 0x87a24b: file /home/whatthejeff/php2/Zend/zend_vm_execute.h, line 543. (gdb) run segfault.php Starting program: /usr/local/bin/php segfault.php ... Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:533 533 if (fbc->common.arg_info) { Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.80.el6_3.6.x86_64 nss-softokn-freebl-3.12.9-11.el6.x86_64 zlib-1.2.3-27.el6.x86_64 (gdb) c Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:544 544 if (!zend_execute_internal) { (gdb) c Continuing. Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:533 533 if (fbc->common.arg_info) { (gdb) c Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:544 544 if (!zend_execute_internal) { (gdb) c Continuing. Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:533 533 if (fbc->common.arg_info) { (gdb) c Continuing. Breakpoint 1, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac380, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:533 533 if (fbc->common.arg_info) { (gdb) c Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac380, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:544 544 if (!zend_execute_internal) { (gdb) c Continuing. Breakpoint 2, zend_do_fcall_common_helper_SPEC (execute_data=0x7ffff7fac238, tsrm_ls=0x100f090) at /home/whatthejeff/php2/Zend/zend_vm_execute.h:544 544 if (!zend_execute_internal) { (gdb) step 546 fbc->internal_function.handler(opline- >extended_value, ret->var.ptr, (fbc->common.fn_flags & >ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); (gdb) zif_dom_document_savexml (ht=1, return_value=0x7ffff7fe3918, return_value_ptr=0x0, this_ptr=0x7ffff7fe4e30, return_value_used=0, tsrm_ls=0x100f090) at /home/whatthejeff/php2/ext/dom/document.c:1790 ... (gdb) 1800 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|O!l", &id, dom_document_class_entry, &nodep, dom_node_class_entry, &options) == FAILURE) { (gdb) 1801 return; ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=63914&edit=1