Skip to content

Commit e486982

Browse files
committed
- MFH Allow multiple exceptions in spl's autoload
1 parent 61a808d commit e486982

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

ext/spl/php_spl.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,14 +379,22 @@ PHP_FUNCTION(spl_autoload_call)
379379

380380
if (SPL_G(autoload_functions)) {
381381
int l_autoload_running = SPL_G(autoload_running);
382+
zval *exception = NULL;
382383
SPL_G(autoload_running) = 1;
383384
class_name_len = Z_STRLEN_P(class_name);
384385
lc_name = zend_str_tolower_dup(Z_STRVAL_P(class_name), class_name_len);
385386
zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &function_pos);
386-
while(zend_hash_has_more_elements_ex(SPL_G(autoload_functions), &function_pos) == SUCCESS && !EG(exception)) {
387+
while(zend_hash_has_more_elements_ex(SPL_G(autoload_functions), &function_pos) == SUCCESS) {
387388
zend_hash_get_current_key_ex(SPL_G(autoload_functions), &func_name, &func_name_len, &dummy, 0, &function_pos);
388389
zend_hash_get_current_data_ex(SPL_G(autoload_functions), (void **) &alfi, &function_pos);
389390
zend_call_method(alfi->obj ? &alfi->obj : NULL, alfi->ce, &alfi->func_ptr, func_name, func_name_len, &retval, 1, class_name, NULL TSRMLS_CC);
391+
if (EG(exception)) {
392+
if (exception) {
393+
zend_update_property(zend_exception_get_default(TSRMLS_C), EG(exception), "previous", sizeof("previous")-1, exception TSRMLS_CC);
394+
}
395+
exception = EG(exception);
396+
EG(exception) = NULL;
397+
}
390398
if (retval) {
391399
zval_ptr_dtor(&retval);
392400
}
@@ -395,6 +403,7 @@ PHP_FUNCTION(spl_autoload_call)
395403
}
396404
zend_hash_move_forward_ex(SPL_G(autoload_functions), &function_pos);
397405
}
406+
EG(exception) = exception;
398407
efree(lc_name);
399408
SPL_G(autoload_running) = l_autoload_running;
400409
} else {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
SPL: spl_autoload() capturing multiple Exceptions in __autoload
3+
--FILE--
4+
<?php
5+
6+
function autoload_first($name)
7+
{
8+
echo __METHOD__ . "\n";
9+
throw new Exception('first');
10+
}
11+
12+
function autoload_second($name)
13+
{
14+
echo __METHOD__ . "\n";
15+
throw new Exception('second');
16+
}
17+
18+
spl_autoload_register('autoload_first');
19+
spl_autoload_register('autoload_second');
20+
21+
class_exists('ThisClassDoesNotExist');
22+
23+
?>
24+
===DONE===
25+
--EXPECTF--
26+
autoload_first
27+
autoload_second
28+
29+
Fatal error: Uncaught exception 'Exception' with message 'first' in %sspl_autoload_012.php:%d
30+
Stack trace:
31+
#0 [internal function]: autoload_first('ThisClassDoesNo...')
32+
#1 [internal function]: spl_autoload_call('ThisClassDoesNo...')
33+
#2 %sspl_autoload_012.php(%d): class_exists('ThisClassDoesNo...')
34+
#3 {main}
35+
36+
Next exception 'Exception' with message 'second' in %sspl_autoload_012.php:%d
37+
Stack trace:
38+
#0 [internal function]: autoload_second('ThisClassDoesNo...')
39+
#1 [internal function]: spl_autoload_call('ThisClassDoesNo...')
40+
#2 %sspl_autoload_012.php(%d): class_exists('ThisClassDoesNo...')
41+
#3 {main}
42+
thrown in %sspl_autoload_012.php on line %d

0 commit comments

Comments
 (0)