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

Reply via email to