php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63914 zend_do_fcall_common_helper_SPEC does not handle exceptions properly
Submitted: 2013-01-06 00:35 UTC Modified: 2013-03-25 03:16 UTC
Votes:1
Avg. Score:2.0 ± 0.0
Reproduced:0 of 1 (0.0%)
From: whatthejeff at gmail dot com Assigned: dmitry
Status: Closed Package: Scripting Engine problem
PHP Version: Irrelevant OS: All
Private report: No CVE-ID:
 [2013-01-06 00:35 UTC] 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;


Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-01-06 01:27 UTC] whatthejeff at gmail dot com
Pull request added: https://github.com/php/php-src/pull/250
 [2013-03-25 03:16 UTC] stas@php.net
Dmitry, could you review the proposed patch?
 [2013-03-25 03:16 UTC] stas@php.net
-Assigned To: +Assigned To: dmitry
 [2013-03-25 11:48 UTC] dmitry@php.net
Automatic comment on behalf of dmitry@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)
 [2013-03-25 11:48 UTC] dmitry@php.net
-Status: Assigned +Status: Closed
 [2013-03-25 11:49 UTC] dmitry@php.net
Automatic comment on behalf of dmitry@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)
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Wed Apr 23 07:02:14 2014 UTC