From: whatthejeff at gmail dot com Operating system: All PHP version: Irrelevant Package: Scripting Engine problem Bug Type: Bug Bug description:zend_do_fcall_common_helper_SPEC does not handle exceptions properly
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 bug report at https://bugs.php.net/bug.php?id=63914&edit=1 -- Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=63914&r=trysnapshot54 Try a snapshot (PHP 5.3): https://bugs.php.net/fix.php?id=63914&r=trysnapshot53 Try a snapshot (trunk): https://bugs.php.net/fix.php?id=63914&r=trysnapshottrunk Fixed in SVN: https://bugs.php.net/fix.php?id=63914&r=fixed Fixed in release: https://bugs.php.net/fix.php?id=63914&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=63914&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=63914&r=needscript Try newer version: https://bugs.php.net/fix.php?id=63914&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=63914&r=support Expected behavior: https://bugs.php.net/fix.php?id=63914&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=63914&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=63914&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=63914&r=globals PHP 4 support discontinued: https://bugs.php.net/fix.php?id=63914&r=php4 Daylight Savings: https://bugs.php.net/fix.php?id=63914&r=dst IIS Stability: https://bugs.php.net/fix.php?id=63914&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=63914&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=63914&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=63914&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=63914&r=mysqlcfg