Edit report at https://bugs.php.net/bug.php?id=63914&edit=1
ID: 63914
Comment by: whatthejeff at gmail dot com
Reported by: whatthejeff at gmail dot com
Summary: zend_do_fcall_common_helper_SPEC does not handle
exceptions properly
Status: Open
Type: Bug
Package: Scripting Engine problem
Operating System: All
PHP Version: Irrelevant
Block user comment: N
Private report: N
New Comment:
Pull request added: https://github.com/php/php-src/pull/250
Previous Comments:
------------------------------------------------------------------------
[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