php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68648 call_user_func inside __callStatic cause segmentation fault
Submitted: 2014-12-24 15:08 UTC Modified: 2015-01-14 09:31 UTC
From: valentiny510 at gmail dot com Assigned:
Status: Not a bug Package: Reproducible crash
PHP Version: 5.6.4 OS: Windows 8 x64
Private report: No CVE-ID: None
 [2014-12-24 15:08 UTC] valentiny510 at gmail dot com
Description:
------------
This piece of code make my apache to restart with status 3221225477.
One quick search on the web and find that is a segmentation fault on windows.
#define STATUS_ACCESS_VIOLATION  ((NTSTATUS)0xC0000005L)

I tried different combinations, with or without namespace, etc.., but the result is always the same, Ex:

call_user_func(array('X', $method));
call_user_func(__NAMESPACE__ . '\X::exist');
call_user_func(array(__NAMESPACE__ . '\X', 'exist'));

I guess will recursively call the same method over and over but at least php should not crash the apache or throw something


Test script:
---------------
<?php

namespace Y;

class X
{
    public static function __callStatic($method, $args) {
        if (is_callable([__CLASS__, $method])) {
            if (empty($args)) {
                call_user_func([__CLASS__, $method]);
                return;
            }

            call_user_func([__CLASS__, $method], join(',', $args));
            return;
        }

        throw new Exception("The class '" . __CLASS__ . "' does not have a method called '$method'");
    }
}

var_dump(X::exist('la bla'));


Expected result:
----------------
The class 'X' does not have a method called 'exist'


Actual result:
--------------
apache shutdown and restart

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-12-24 22:51 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2014-12-24 22:51 UTC] requinix@php.net
is_callable() will return true because you've implemented __callStatic. You created infinite recursion.
method_exists() won't do that.
 [2014-12-25 05:32 UTC] valentiny510 at gmail dot com
Ok, my bad using is_callable, but even so, the method should have a limit for the recursion or try to detect if the tested callable method is the same method from where was called and this way avoit the problem, in my opinion is still a bug but for is_callable.

Why you cant do something similar to this ?

function is_callable($method)
{
    if ($method == __FUNCTION__) return; break; whatever...

    # Do the loop here...
}

the thing is, php should never have the ability to break other things like in this case the apache, run in some sandbox style, test the code in the background and then push into some opcache 

Cheers !
 [2015-01-07 16:36 UTC] claudiu at paun dot com
Well done requinix, well done, you just solved all the problems by using the button "Not a bug" and washed your hands.

If an internal function can break the server you just call this "Not a bug" ?

Dude, seriously, why dont you studied medicine ?
 [2015-01-07 16:48 UTC] claudiu at paun dot com
BTW, You said the problem is 'is_callable', so in my opinion 'is_callable' should only determine if the method IS CALLABLE and not actually CALL the method and avoiding this way the "infinite recursion"...
 [2015-01-07 17:03 UTC] nikic@php.net
is_callable() does what you says. It does not cause infinite recursion. You are causing infinite recursion, by recursively calling the __callStatic() method.
 [2015-01-07 20:27 UTC] requinix@php.net
> Why you cant do something similar to this ?
It's quite possible that I want the current function to call itself. Rare, I'll admit, but as a developer I wouldn't want PHP to prevent me from doing that.
More likely is that function A calls function B which calls A. Or maybe there's a third function C. Maybe it looks infinitely recursive but there's a condition that will eventually stop it (as happens with typical recursion). It's just not possible for PHP to accurately judge that it should stop executing.

On a related note, the xdebug extension can impose a limit on the call stack with its xdebug.max_nesting_level setting. Default of 100.

> If an internal function can break the server you just call this "Not a bug" ?
PHP crashing randomly is a bug. The developer inadvertently telling PHP to do something bad and thus causing it to crash *might* not be a bug.

In this case it wasn't because PHP dutifully carried out the instructions it was given, which happened simply because the submitter didn't know that is_callable() will accommodate for __callStatic (and __call) as opposed to merely checking that a method exists like, well, method_exists().
 [2015-01-14 07:33 UTC] valentiny510 at gmail dot com
Nikic, I did not called __callStatic( ) method... PHP internally did it

Like Claudiu said, 'is_callable' should only determine if the method IS CALLABLE and not actually CALL him self over and over

Is like asking yourself in front of a mirror.. "I'm a man ?, I'm a man ?, I'm a man ?"

Dude, once you have determined you are a man, just stop...

Requinix, 'PHP crashing randomly is a bug'...
What can I say... read http://en.wikipedia.org/wiki/Software_bug
and seriously.. consider medicine as alternative
 [2015-01-14 09:31 UTC] nikic@php.net
-Block user comment: No +Block user comment: Yes
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Apr 20 10:01:28 2024 UTC