Edit report at http://bugs.php.net/bug.php?id=51329&edit=1

 ID:               51329
 Comment by:       denis at bitrix dot ru
 Reported by:      gergely dot fabian at radix-technologies dot com
 Summary:          call_user_func_array() crashes with autoload in
                   recursive calls
 Status:           Bogus
 Type:             Bug
 Package:          Reproducible crash
 Operating System: Ubuntu
 PHP Version:      5.2.13

 New Comment:

I have the same problem. Why is it bogus? There is no unlimit
recursion!

The only workaround I found is not to use autoload.


Previous Comments:
------------------------------------------------------------------------
[2010-03-22 07:40:00] gergely dot fabian at radix-technologies dot com

I have to emphasize that the use case where this bug came out was not
infinite recursion. 

It is in an MVC web application framework (symfony) that a given amount
of filters (let's say 15) are one-by-one called by the filterChain's
execute() method, and then call back to filterChain->execute() (thus
making a sort of indirect recursion).

In our case if we have certain conditions true and have a 7th filter,
then a later call_user_func_array call will cause a segfault. Having
less number of filters (disabling any of them) "fixes" the bug (not
reaching that amount of recursion), as also having one more filter
(making an additional recursion step).

The second testcase reproduces this with plain PHP code.

------------------------------------------------------------------------
[2010-03-22 07:24:26] gergely dot fabian at radix-technologies dot com

The infinite recursion that you mentioned also causes segfault, but it's
another case. If I remove the call_user_func_array call, and the limit
of 50, then it will segfault after around 14860 recursive calls (on my
machine).

My original code (and the second version I posted) segfaults at 25/31st
recursion. That's a different amount I'd say.

If I change the second version of my testcase to jump
call_user_func_array call at 25th recursion, then it runs until 208th
recursion and dies again on call_user_func_array.

If enable though class_exists() before call_user_func_array(), then
recursion is successful for both 25th and 208th.

------------------------------------------------------------------------
[2010-03-21 21:59:57] gergely dot fabian at radix-technologies dot com

This is not infinite recursion (is 31/25 recursion too deep?).

See my comment with putting one element to call stack "fixing" later
autoloading (2010-03-19 09:38 UTC).

This is an autoloading/call_user_func_array bug imho. Otherwise if it
would be normal for this to happen, why does class_exists() call right
before the segfaulting place fix it?

------------------------------------------------------------------------
[2010-03-21 19:24:32] johan...@php.net

Infinite recursion is known to segfault and expected behavior. See other
reports about it.

------------------------------------------------------------------------
[2010-03-19 11:38:45] gergely dot fabian at radix-technologies dot com

I managed to reproduce this bug (I guess it's the same) in another way,
which is a lot closer to our original test case (that was about having a
given number of calls in the call stack causing later autoload of
call_user_func_array() to fail, but if we had more number of calls in
call stack, then there was no segfault).

This code will have a segfault in the 25th call (it mainly depends on
the number of parameters given to "callback"). If we miss calling
call_user_func_array() in the 25th recursion (and simply make another
recursion) then later call_user_func_array() calls will be ok. I guess
making a simple recursion at 25th steps mask (or fixes) the bug in the
call stack.



<?php

$limit = 25; // till when to autoload classes

// change $limit2 to 25, and P25's autoload will be missed (and an
additional callback will be called before next autoloading)

// then there is no segmentation fault, and it runs till 50

$limit2 = 24; // re-enable autoloading after this limit

$limit3 = 50; // iterate till this

for($i = 1; $i <= $limit3; $i++){

  $f = "<?php

echo \"P$i loaded\\n\";

class P$i{

  public static function execute_me(){

    return \"P$i executed\\n\";

  }

}";

  file_put_contents("P$i.class.php", $f);

}

function __autoload($class_name) {

    require_once $class_name . '.class.php';

}

function callback($limit, $limit2, $i = 1){

  global $limit3;

  echo "Calling callback $i\n";

  if ($i < $limit || $i > $limit2)  // enable some $i where we won't
autoload

  {

    //class_exists("P$i");

    echo call_user_func_array(array("P$i", 'execute_me'), array());

  }

  if ($i < $limit3) callback($limit, $limit2, $i+1);

}

callback($limit, $limit2);

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    http://bugs.php.net/bug.php?id=51329


-- 
Edit this bug report at http://bugs.php.net/bug.php?id=51329&edit=1

Reply via email to