Skip to content

Commit

Permalink
Fixed bug #52339
Browse files Browse the repository at this point in the history
Autoloader 101: Don't throw if you fail. PHP will throw for you.
  • Loading branch information
nikic committed Mar 18, 2016
1 parent a2522ef commit 8023204
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 71 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ PHP NEWS
- SPL:
. Fixed bug #71838 (Deserializing serialized SPLObjectStorage-Object can't
access properties in PHP). (Nikita)
. Fixed bug #52339 (SPL autoloader breaks class_exists()). (Nikita)

- Standard:
. Fixed bug #71837 (Wrong arrays behaviour). (Laruence)
Expand Down
22 changes: 1 addition & 21 deletions ext/spl/php_spl.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ static int spl_autoload(zend_string *class_name, zend_string *lc_name, const cha
Default implementation for __autoload() */
PHP_FUNCTION(spl_autoload)
{
int found = 0, pos_len, pos1_len;
int pos_len, pos1_len;
char *pos, *pos1;
zend_string *class_name, *lc_name, *file_exts = SPL_G(autoload_extensions);

Expand All @@ -333,32 +333,12 @@ PHP_FUNCTION(spl_autoload)
pos1_len = pos_len;
}
if (spl_autoload(class_name, lc_name, pos, pos1_len)) {
found = 1;
break; /* loaded */
}
pos = pos1 ? pos1 + 1 : NULL;
pos_len = pos1? pos_len - pos1_len - 1 : 0;
}
zend_string_free(lc_name);

if (!found && !SPL_G(autoload_running)) {
/* For internal errors, we generate E_ERROR, for direct calls an exception is thrown.
* The "scope" is determined by an opcode, if it is ZEND_FETCH_CLASS we know function was called indirectly by
* the Zend engine.
*/
zend_execute_data *ex = EX(prev_execute_data);

while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
ex = ex->prev_execute_data;
}
if (ex &&
ex->opline->opcode != ZEND_FETCH_CLASS &&
ex->opline->opcode != ZEND_NEW) {
zend_throw_exception_ex(spl_ce_LogicException, 0, "Class %s could not be loaded", ZSTR_VAL(class_name));
} else {
php_error_docref(NULL, E_ERROR, "Class %s could not be loaded", ZSTR_VAL(class_name));
}
}
} /* }}} */

/* {{{ proto string spl_autoload_extensions([string file_extensions])
Expand Down
5 changes: 4 additions & 1 deletion ext/spl/tests/bug38325.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ spl_autoload_register();
new ThisClassDoesNotExistEverFoo();
?>
--EXPECTF--
Fatal error: spl_autoload(): Class ThisClassDoesNotExistEverFoo could not be loaded in %s on line 3
Fatal error: Uncaught Error: Class 'ThisClassDoesNotExistEverFoo' not found in %s:%d
Stack trace:
#0 {main}
thrown in %s on line 3
11 changes: 11 additions & 0 deletions ext/spl/tests/bug52339.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
Bug #52339: SPL autoloader breaks class_exists()
--FILE--
<?php
var_dump(class_exists('asdfasdf'));
spl_autoload_register();
var_dump(class_exists('asdfasdf'));
?>
--EXPECT--
bool(false)
bool(false)
71 changes: 22 additions & 49 deletions ext/spl/tests/spl_autoload_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,25 @@ echo "===EMPTY===\n";

var_dump(spl_autoload_extensions());

try
{
spl_autoload("TestClass");
}
catch(Exception $e)
{
echo 'Exception: ' . $e->getMessage() . "\n";
spl_autoload("TestClass");
if (!class_exists("TestClass")) {
echo "Class TestClass could not be loaded\n";
}

$test_exts = array(NULL, "1", ".inc,,.php.inc", "");

foreach($test_exts as $exts)
{
foreach($test_exts as $exts) {
echo "===($exts)===\n";
try
{
spl_autoload("TestClass", $exts);
}
catch(Exception $e)
{
echo 'Exception: ' . $e->getMessage() . "\n";
}
spl_autoload("TestClass", $exts);
if (!class_exists("TestClass")) {
echo "Class TestClass could not be loaded\n";
}
}

try
{
spl_autoload_extensions(".inc,.php.inc");
spl_autoload("TestClass");
}
catch(Exception $e)
{
echo 'Exception: ' . $e->getMessage() . "\n";
spl_autoload_extensions(".inc,.php.inc");
spl_autoload("TestClass");
if (!class_exists("TestClass")) {
echo "Class TestClass could not be loaded\n";
}

function TestFunc1($classname)
Expand All @@ -57,15 +44,8 @@ echo "===SPL_AUTOLOAD()===\n";

spl_autoload_register();

try
{
var_dump(spl_autoload_extensions(".inc"));
var_dump(class_exists("TestClass", true));
}
catch(Exception $e)
{
echo 'Exception: ' . $e->getMessage() . "\n";
}
var_dump(spl_autoload_extensions(".inc"));
var_dump(class_exists("TestClass", true));

echo "===REGISTER===\n";

Expand All @@ -75,14 +55,7 @@ spl_autoload_register("TestFunc2");
spl_autoload_register("TestFunc2"); /* 2nd call ignored */
spl_autoload_extensions(".inc,.class.inc"); /* we do not have spl_autoload_registered yet */

try
{
var_dump(class_exists("TestClass", true));
}
catch(Exception $e)
{
echo 'Exception: ' . $e->getMessage() . "\n";
}
var_dump(class_exists("TestClass", true));

echo "===LOAD===\n";

Expand All @@ -107,21 +80,21 @@ catch(Exception $e)
===EMPTY===
string(9) ".inc,.php"
%stestclass.inc
Exception: Class TestClass could not be loaded
Class TestClass could not be loaded
===()===
Exception: Class TestClass could not be loaded
Class TestClass could not be loaded
===(1)===
Exception: Class TestClass could not be loaded
Class TestClass could not be loaded
===(.inc,,.php.inc)===
%stestclass
%stestclass.php.inc
Exception: Class TestClass could not be loaded
Class TestClass could not be loaded
===()===
Exception: Class TestClass could not be loaded
Exception: Class TestClass could not be loaded
Class TestClass could not be loaded
Class TestClass could not be loaded
===SPL_AUTOLOAD()===
string(4) ".inc"
Exception: Class TestClass could not be loaded
bool(false)
===REGISTER===
TestFunc1(TestClass)
TestFunc2(TestClass)
Expand Down

0 comments on commit 8023204

Please sign in to comment.