Skip to content

Commit 35353dc

Browse files
committed
Fixed bug #76980
If we perform a class fetch that is not marked as exception safe, convert exceptions thrown by autoloaders into a fatal error. Ideally fetching the interfaces would be exception safe, but as it isn't right now, we must abort at this point.
1 parent 4fa32d6 commit 35353dc

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? 2019, PHP 7.2.20
44

5+
- Core:
6+
. Fixed bug #76980 (Interface gets skipped if autoloader throws an exception).
7+
(Nikita)
58

69
30 May 2019, PHP 7.2.19
710

Zend/tests/bug49908.phpt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,22 @@ spl_autoload_register(function ($className) {
1313
}
1414
});
1515

16-
new Foo;
16+
try {
17+
new Foo();
18+
} catch (Exception $e) { }
19+
20+
// We never reach here.
21+
var_dump(new Foo());
1722

1823
?>
1924
--EXPECTF--
2025
string(3) "Foo"
2126
string(3) "Bar"
2227

23-
Fatal error: Uncaught Exception: Bar in %s:%d
28+
Fatal error: During class fetch: Uncaught Exception: Bar in %s:%d
2429
Stack trace:
2530
#0 [internal function]: {closure}('Bar')
2631
#1 %s(%d): spl_autoload_call('Bar')
2732
#2 [internal function]: {closure}('Foo')
2833
#3 %s(%d): spl_autoload_call('Foo')
29-
#4 {main}
30-
thrown in %s on line %d
34+
#4 {main} in %s on line %d

Zend/zend_execute_API.c

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,14 +1424,28 @@ zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, const zval *
14241424
if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
14251425
return zend_lookup_class_ex(class_name, key, 0);
14261426
} else if ((ce = zend_lookup_class_ex(class_name, key, 1)) == NULL) {
1427-
if ((fetch_type & ZEND_FETCH_CLASS_SILENT) == 0 && !EG(exception)) {
1428-
if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
1429-
zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
1430-
} else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
1431-
zend_throw_or_error(fetch_type, NULL, "Trait '%s' not found", ZSTR_VAL(class_name));
1432-
} else {
1433-
zend_throw_or_error(fetch_type, NULL, "Class '%s' not found", ZSTR_VAL(class_name));
1427+
if (fetch_type & ZEND_FETCH_CLASS_SILENT) {
1428+
return NULL;
1429+
}
1430+
if (EG(exception)) {
1431+
if (!(fetch_type & ZEND_FETCH_CLASS_EXCEPTION)) {
1432+
zend_string *exception_str;
1433+
zval exception_zv;
1434+
ZVAL_OBJ(&exception_zv, EG(exception));
1435+
Z_ADDREF(exception_zv);
1436+
zend_clear_exception();
1437+
exception_str = zval_get_string(&exception_zv);
1438+
zend_error_noreturn(E_ERROR,
1439+
"During class fetch: Uncaught %s", ZSTR_VAL(exception_str));
14341440
}
1441+
return NULL;
1442+
}
1443+
if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_INTERFACE) {
1444+
zend_throw_or_error(fetch_type, NULL, "Interface '%s' not found", ZSTR_VAL(class_name));
1445+
} else if ((fetch_type & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_TRAIT) {
1446+
zend_throw_or_error(fetch_type, NULL, "Trait '%s' not found", ZSTR_VAL(class_name));
1447+
} else {
1448+
zend_throw_or_error(fetch_type, NULL, "Class '%s' not found", ZSTR_VAL(class_name));
14351449
}
14361450
return NULL;
14371451
}

0 commit comments

Comments
 (0)