php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48770 call_user_func_array() fails to call parent from inheriting class
Submitted: 2009-07-02 07:28 UTC Modified: 2017-05-14 16:40 UTC
Votes:22
Avg. Score:4.3 ± 0.9
Reproduced:18 of 19 (94.7%)
Same Version:13 (72.2%)
Same OS:6 (33.3%)
From: lumeet at yahoo dot com Assigned: pollita (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5.3, 6 (2009-08-01) OS: *
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: lumeet at yahoo dot com
New email:
PHP Version: OS:

 

 [2009-07-02 07:28 UTC] lumeet at yahoo dot com
Description:
------------
When class C extends B, which extends A, calls from B to its parent 
methods fail when using call_user_func_array(). Using parent::func()
works just fine.

Reproduce code:
---------------
class A {
  function func( $str ) {
    echo $str;
  }
}

class B extends A {
  public function func( $str ) {
    call_user_func_array( array( $this, 'parent::func' ), array( $str ) );
  }
}

class C extends B {
  public function func( $str ) {
    parent::func( $str );
  }
}

$c = new C;
$c->func( 'This should work!' );

Expected result:
----------------
The code should output "This should work!".

Actual result:
--------------
PHP crashes with backtrace (yes, only one line):

Function     Arg 1     Arg 2     Arg 3   Source 
php5ts!zend_is_callable_ex+61e     011f0780     00000006     003228e0    

Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-07-02 07:38 UTC] sjoerd-php at linuxonly dot nl
Thank you for your bug report. I could reproduce it and added some more data:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7d03b80 (LWP 6726)]
0x082dee15 in zend_is_callable_ex (callable=0x9e3cdc0, object_ptr=0x0, 
    check_flags=0, callable_name=0x0, callable_name_len=0x0, fcc=0xbf49d190, 
    error=0xbf49d0e8) at /home/sjoerd/dev/php/trunk/php5/Zend/zend_API.c:2624
2624	{
#0  0x082dee15 in zend_is_callable_ex (callable=0x9e3cdc0, object_ptr=0x0, 
    check_flags=0, callable_name=0x0, callable_name_len=0x0, fcc=0xbf49d190, 
    error=0xbf49d0e8) at /home/sjoerd/dev/php/trunk/php5/Zend/zend_API.c:2624
#1  0x082df489 in zend_fcall_info_init (callable=0x9e3cdc0, check_flags=0, 
    fci=0xbf49d16c, fcc=0xbf49d190, callable_name=0x0, error=0xbf49d0e8)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_API.c:2858
#2  0x082e35a2 in zend_parse_va_args (num_args=2, type_spec=0x85b0091 "a/", 
    va=0xbf49d13c, flags=0)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_API.c:592
#3  0x082e3d12 in zend_parse_parameters (num_args=2, type_spec=0xbf49d0e8 "")
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_API.c:870
#4  0x08220dd1 in zif_call_user_func_array (ht=2, return_value=0x9e3ce7c, 
    return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)
    at /home/sjoerd/dev/php/trunk/php5/ext/standard/basic_functions.c:4748
#5  0x083259b9 in zend_do_fcall_common_helper_SPEC (execute_data=0x9de07bc)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_vm_execute.h:313
#6  0x08302dbe in execute (op_array=0x9448e90)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_vm_execute.h:104
#7  0x082d0c77 in zend_call_function (fci=0xbf49d37c, fci_cache=0xbf49d3a0)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_execute_API.c:936
#8  0x08220df7 in zif_call_user_func_array (ht=2, return_value=0x9e3ccb0, 
    return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)
    at /home/sjoerd/dev/php/trunk/php5/ext/standard/basic_functions.c:4755
#9  0x083259b9 in zend_do_fcall_common_helper_SPEC (execute_data=0x9de06fc)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_vm_execute.h:313
#10 0x08302dbe in execute (op_array=0x9448e90)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_vm_execute.h:104
#11 0x082d0c77 in zend_call_function (fci=0xbf49d58c, fci_cache=0xbf49d5b0)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_execute_API.c:936
#12 0x08220df7 in zif_call_user_func_array (ht=2, return_value=0x9e3cae4, 
    return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)
    at /home/sjoerd/dev/php/trunk/php5/ext/standard/basic_functions.c:4755

...

#11213 0x083259b9 in zend_do_fcall_common_helper_SPEC (execute_data=0x9c1d004)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_vm_execute.h:313
#11214 0x08302dbe in execute (op_array=0x9448e90)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_vm_execute.h:104
#11215 0x082d0c77 in zend_call_function (fci=0xbf60669c, fci_cache=0xbf6066c0)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_execute_API.c:936
#11216 0x08220df7 in zif_call_user_func_array (ht=2, return_value=0x9c822d4, 
    return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)
    at /home/sjoerd/dev/php/trunk/php5/ext/standard/basic_functions.c:4755
#11217 0x083259b9 in zend_do_fcall_common_helper_SPEC (execute_data=0x9c1cf44)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_vm_execute.h:313
#11218 0x08302dbe in execute (op_array=0x9448e90)
    at /home/sjoerd/dev/php/trunk/php5/Zend/zend_vm_execute.h:104
etc. etc.
 [2009-08-01 01:51 UTC] jani@php.net
Also note: This works fine with PHP_5_2 :)
 [2009-09-25 08:08 UTC] dmitry dot revenko at businessmedia dot ru
I also used this pattern in some critical moments, and it proved to be very useful.
Yes, I know about PHP 3's "call_user_func() now propagates $this even if the callee is the parent class". But I don't know - why? Why so simple working logic was ruined in new version? Isn't it straght that call_user_func_array(array( $this, 'parent::func' ), $args) should call first found parent method func?
 [2009-09-25 12:12 UTC] dmitry dot revenko at businessmedia dot ru
I'm sorry.
The solution is:

call_user_func_array('parent::func', $args);

instead of

call_user_func_array(array($this, 'parent::func'), $args);
 [2011-09-05 07:32 UTC] tyrael@php.net
for the record: the segfault is caused by an infinite recursion (B->func), and 
that happens, because the $this in the B->func() points to C, which causes 
parent::func to point to itself.
btw. I find it really unintentional that call_user_func can be used with both 
passing an object instance and a static call reference as a method name.
we also have failing tests for this particular bug:
Zend/tests/bug48770.phpt
Zend/tests/bug48770_2.phpt
Zend/tests/bug48770_3.phpt

imo as we have this behavior for some time now, I think we should keep it, and 
update the tests.

Tyrael
 [2015-07-17 12:30 UTC] mbrodala at pagemachine dot de
I stumbled upon a similar error while trying to use a trait to make static method calls mockable in tests:

http://3v4l.org/s5t3s

The issue can be avoided here by not using the "StaticCall" trait in subclasses of "ChildClass" but in reality classes should just use the traits they need and not rely on the trait usage of a parent class.

Is there an error on my side?
 [2017-05-14 16:40 UTC] pollita@php.net
-Status: Verified +Status: Closed -Assigned To: +Assigned To: pollita
 [2017-05-14 16:40 UTC] pollita@php.net
Basically, what tyrael said.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 28 19:01:28 2024 UTC