Skip to content

Commit de4e7e7

Browse files
committed
Always throw a TypeError with invalid callable in spl_autoload_register
This also provides more useful information as to why the callable is invalid. Adds a warning mentioning that the second parameter is ignored when passed false.
1 parent 556573b commit de4e7e7

7 files changed

+58
-84
lines changed

Zend/tests/bug78868.phpt

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ $props[0]->setValue(2); //causes constant resolving, which runs autoload, all wi
2929

3030
echo "OK\n";
3131
?>
32-
--EXPECT--
32+
--EXPECTF--
33+
Warning: spl_autoload_register(): spl_autoload_register will always throw,the second argument has been ignored in %s on line %d
3334
OK

ext/spl/php_spl.c

+17-49
Original file line numberDiff line numberDiff line change
@@ -515,65 +515,33 @@ PHP_FUNCTION(spl_autoload_register)
515515
RETURN_THROWS();
516516
}
517517

518+
if (!do_throw) {
519+
php_error_docref(NULL, E_WARNING, "spl_autoload_register will always throw,"
520+
"the second argument has been ignored");
521+
}
522+
518523
if (ZEND_NUM_ARGS()) {
519524
if (!zend_is_callable_ex(zcallable, NULL, 0, &func_name, &fcc, &error)) {
520-
alfi.ce = fcc.calling_scope;
521-
alfi.func_ptr = fcc.function_handler;
522-
obj_ptr = fcc.object;
523-
if (Z_TYPE_P(zcallable) == IS_ARRAY) {
524-
if (!obj_ptr && alfi.func_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
525-
if (do_throw) {
526-
zend_throw_exception_ex(spl_ce_LogicException, 0, "Passed array specifies a non static method but no object (%s)", error);
527-
}
528-
if (error) {
529-
efree(error);
530-
}
531-
zend_string_release_ex(func_name, 0);
532-
RETURN_FALSE;
533-
} else if (do_throw) {
534-
zend_throw_exception_ex(spl_ce_LogicException, 0, "Passed array does not specify %s %smethod (%s)", alfi.func_ptr ? "a callable" : "an existing", !obj_ptr ? "static " : "", error);
535-
}
536-
if (error) {
537-
efree(error);
538-
}
539-
zend_string_release_ex(func_name, 0);
540-
RETURN_FALSE;
541-
} else if (Z_TYPE_P(zcallable) == IS_STRING) {
542-
if (do_throw) {
543-
zend_throw_exception_ex(spl_ce_LogicException, 0, "Function '%s' not %s (%s)", ZSTR_VAL(func_name), alfi.func_ptr ? "callable" : "found", error);
544-
}
545-
if (error) {
546-
efree(error);
547-
}
548-
zend_string_release_ex(func_name, 0);
549-
RETURN_FALSE;
550-
} else {
551-
if (do_throw) {
552-
zend_throw_exception_ex(spl_ce_LogicException, 0, "Illegal value passed (%s)", error);
553-
}
554-
if (error) {
555-
efree(error);
556-
}
557-
zend_string_release_ex(func_name, 0);
558-
RETURN_FALSE;
559-
}
560-
} else if (fcc.function_handler->type == ZEND_INTERNAL_FUNCTION &&
561-
fcc.function_handler->internal_function.handler == zif_spl_autoload_call) {
562-
if (do_throw) {
563-
zend_throw_exception_ex(spl_ce_LogicException, 0, "Function spl_autoload_call() cannot be registered");
564-
}
525+
zend_argument_type_error(1, "must be a valid callback, %s", error);
565526
if (error) {
566527
efree(error);
567528
}
568529
zend_string_release_ex(func_name, 0);
569-
RETURN_FALSE;
530+
RETURN_THROWS();
531+
}
532+
533+
ZEND_ASSERT(!error);
534+
535+
if (fcc.function_handler->type == ZEND_INTERNAL_FUNCTION &&
536+
fcc.function_handler->internal_function.handler == zif_spl_autoload_call) {
537+
zend_argument_value_error(1, "the spl_autoload_call() function cannot be registered");
538+
zend_string_release_ex(func_name, 0);
539+
RETURN_THROWS();
570540
}
541+
571542
alfi.ce = fcc.calling_scope;
572543
alfi.func_ptr = fcc.function_handler;
573544
obj_ptr = fcc.object;
574-
if (error) {
575-
efree(error);
576-
}
577545

578546
if (Z_TYPE_P(zcallable) == IS_OBJECT) {
579547
ZVAL_COPY(&alfi.closure, zcallable);

ext/spl/tests/spl_autoload_001.phpt

+4-7
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,10 @@ var_dump(class_exists("TestClass", true));
6464

6565
echo "===NOFUNCTION===\n";
6666

67-
try
68-
{
67+
try {
6968
spl_autoload_register("unavailable_autoload_function");
70-
}
71-
catch(Exception $e)
72-
{
73-
echo 'Exception: ' . $e->getMessage() . "\n";
69+
} catch(\TypeError $e) {
70+
echo $e->getMessage() . \PHP_EOL;
7471
}
7572

7673
?>
@@ -103,4 +100,4 @@ TestFunc2(TestClass)
103100
%stestclass.class.inc
104101
bool(true)
105102
===NOFUNCTION===
106-
Exception: Function 'unavailable_autoload_function' not found (function 'unavailable_autoload_function' not found or invalid function name)
103+
spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, function 'unavailable_autoload_function' not found or invalid function name

ext/spl/tests/spl_autoload_005.phpt

+4-7
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,10 @@ class MyAutoLoader {
1919
}
2020
}
2121

22-
try
23-
{
22+
try {
2423
spl_autoload_register(array('MyAutoLoader', 'autoLoad'), true);
25-
}
26-
catch(Exception $e)
27-
{
28-
echo 'Exception: ' . $e->getMessage() . "\n";
24+
} catch(\TypeError $e) {
25+
echo $e->getMessage() . \PHP_EOL;
2926
}
3027

3128
// and
@@ -46,7 +43,7 @@ catch(Exception $e)
4643

4744
?>
4845
--EXPECT--
49-
Exception: Passed array specifies a non static method but no object (non-static method MyAutoLoader::autoLoad() cannot be called statically)
46+
spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, non-static method MyAutoLoader::autoLoad() cannot be called statically
5047
MyAutoLoader::autoLoad(TestClass)
5148
MyAutoLoader::autoThrow(TestClass)
5249
Exception: Unavailable

ext/spl/tests/spl_autoload_007.phpt

+11-14
Original file line numberDiff line numberDiff line change
@@ -40,47 +40,44 @@ $funcs = array(
4040
foreach($funcs as $idx => $func)
4141
{
4242
if ($idx) echo "\n";
43-
try
44-
{
43+
try {
4544
var_dump($func);
4645
spl_autoload_register($func);
4746
echo "ok\n";
48-
}
49-
catch (Exception $e)
50-
{
51-
echo $e->getMessage() . "\n";
47+
} catch(\TypeError $e) {
48+
echo $e->getMessage() . \PHP_EOL;
5249
}
5350
}
5451

5552
?>
5653
--EXPECTF--
5754
string(22) "MyAutoLoader::notExist"
58-
Function 'MyAutoLoader::notExist' not found (class 'MyAutoLoader' does not have a method 'notExist')
55+
spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, class 'MyAutoLoader' does not have a method 'notExist'
5956

6057
string(22) "MyAutoLoader::noAccess"
61-
Function 'MyAutoLoader::noAccess' not callable (cannot access protected method MyAutoLoader::noAccess())
58+
spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, cannot access protected method MyAutoLoader::noAccess()
6259

6360
string(22) "MyAutoLoader::autoLoad"
6461
ok
6562

6663
string(22) "MyAutoLoader::dynaLoad"
67-
Function 'MyAutoLoader::dynaLoad' not callable (non-static method MyAutoLoader::dynaLoad() cannot be called statically)
64+
spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, non-static method MyAutoLoader::dynaLoad() cannot be called statically
6865

6966
array(2) {
7067
[0]=>
7168
string(12) "MyAutoLoader"
7269
[1]=>
7370
string(8) "notExist"
7471
}
75-
Passed array does not specify an existing static method (class 'MyAutoLoader' does not have a method 'notExist')
72+
spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, class 'MyAutoLoader' does not have a method 'notExist'
7673

7774
array(2) {
7875
[0]=>
7976
string(12) "MyAutoLoader"
8077
[1]=>
8178
string(8) "noAccess"
8279
}
83-
Passed array does not specify a callable static method (cannot access protected method MyAutoLoader::noAccess())
80+
spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, cannot access protected method MyAutoLoader::noAccess()
8481

8582
array(2) {
8683
[0]=>
@@ -96,7 +93,7 @@ array(2) {
9693
[1]=>
9794
string(8) "dynaLoad"
9895
}
99-
Passed array specifies a non static method but no object (non-static method MyAutoLoader::dynaLoad() cannot be called statically)
96+
spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, non-static method MyAutoLoader::dynaLoad() cannot be called statically
10097

10198
array(2) {
10299
[0]=>
@@ -105,7 +102,7 @@ array(2) {
105102
[1]=>
106103
string(8) "notExist"
107104
}
108-
Passed array does not specify an existing method (class 'MyAutoLoader' does not have a method 'notExist')
105+
spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, class 'MyAutoLoader' does not have a method 'notExist'
109106

110107
array(2) {
111108
[0]=>
@@ -114,7 +111,7 @@ array(2) {
114111
[1]=>
115112
string(8) "noAccess"
116113
}
117-
Passed array does not specify a callable static method (cannot access protected method MyAutoLoader::noAccess())
114+
spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, cannot access protected method MyAutoLoader::noAccess()
118115

119116
array(2) {
120117
[0]=>

ext/spl/tests/spl_autoload_008.phpt

+4-6
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,8 @@ foreach($funcs as $idx => $func)
5252

5353
var_dump(class_exists("NoExistingTestClass", true));
5454
}
55-
}
56-
catch (Exception $e)
57-
{
58-
echo get_class($e) . ": " . $e->getMessage() . "\n";
55+
} catch(\TypeError|\Exception $e) {
56+
echo get_class($e) . ': ' . $e->getMessage() . \PHP_EOL;
5957
}
6058

6159
spl_autoload_unregister($func);
@@ -78,7 +76,7 @@ Exception: Bla
7876
int(0)
7977
====2====
8078
string(22) "MyAutoLoader::dynaLoad"
81-
LogicException: Function 'MyAutoLoader::dynaLoad' not callable (non-static method MyAutoLoader::dynaLoad() cannot be called statically)
79+
TypeError: spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, non-static method MyAutoLoader::dynaLoad() cannot be called statically
8280
int(0)
8381
====3====
8482
array(2) {
@@ -98,7 +96,7 @@ array(2) {
9896
[1]=>
9997
string(8) "dynaLoad"
10098
}
101-
LogicException: Passed array specifies a non static method but no object (non-static method MyAutoLoader::dynaLoad() cannot be called statically)
99+
TypeError: spl_autoload_register(): Argument #1 ($autoload_function) must be a valid callback, non-static method MyAutoLoader::dynaLoad() cannot be called statically
102100
int(0)
103101
====5====
104102
array(2) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
spl_autoload_call() function - warn when using false as second argument for spl_autoload_call()
3+
--FILE--
4+
<?php
5+
function customAutolader($class) {
6+
require_once __DIR__ . '/testclass.class.inc';
7+
}
8+
spl_autoload_register('customAutolader', false);
9+
10+
spl_autoload_call('TestClass');
11+
var_dump(class_exists('TestClass', false));
12+
?>
13+
--EXPECTF--
14+
Warning: spl_autoload_register(): spl_autoload_register will always throw,the second argument has been ignored in %s on line %d
15+
%stestclass.class.inc
16+
bool(true)

0 commit comments

Comments
 (0)