Skip to content

Commit 403396e

Browse files
committed
Merge branch 'PHP-7.4'
2 parents 7992a71 + 270e5e3 commit 403396e

File tree

6 files changed

+47
-9
lines changed

6 files changed

+47
-9
lines changed

Zend/tests/bug30922.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ var_dump($a instanceOf A);
1010
echo "ok\n";
1111
?>
1212
--EXPECTF--
13-
Fatal error: Interface RecurisiveFooFar cannot implement itself in %s on line %d
13+
Fatal error: Interface 'RecurisiveFooFar' not found in %s on line %d
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Using an unlinked parent class
3+
--FILE--
4+
<?php
5+
6+
spl_autoload_register(function($class) {
7+
class X extends B {}
8+
});
9+
10+
class B extends A {
11+
}
12+
13+
?>
14+
--EXPECTF--
15+
Fatal error: Class 'B' not found in %s on line %d
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Using an unlinked parent interface
3+
--FILE--
4+
<?php
5+
6+
spl_autoload_register(function($class) {
7+
class X implements B {}
8+
});
9+
10+
interface B extends A {
11+
}
12+
13+
?>
14+
--EXPECTF--
15+
Fatal error: Interface 'B' not found in %s on line %d

Zend/zend_compile.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ typedef struct _zend_oparray_context {
229229
/* op_array or class is preloaded | | | */
230230
#define ZEND_ACC_PRELOADED (1 << 10) /* X | X | | */
231231
/* | | | */
232-
/* Class Flags (unused: 22...) | | | */
232+
/* Class Flags (unused: 23...) | | | */
233233
/* =========== | | | */
234234
/* | | | */
235235
/* Special class types | | | */
@@ -278,6 +278,9 @@ typedef struct _zend_oparray_context {
278278
/* Class has unresolved variance obligations. | | | */
279279
#define ZEND_ACC_UNRESOLVED_VARIANCE (1 << 21) /* X | | | */
280280
/* | | | */
281+
/* Class is linked apart from variance obligations. | | | */
282+
#define ZEND_ACC_NEARLY_LINKED (1 << 22) /* X | | | */
283+
/* | | | */
281284
/* Function Flags (unused: 17, 23, 26) | | | */
282285
/* ============== | | | */
283286
/* | | | */
@@ -860,6 +863,7 @@ void zend_assert_valid_class_name(const zend_string *const_name);
860863
#define ZEND_FETCH_CLASS_SILENT 0x0100
861864
#define ZEND_FETCH_CLASS_EXCEPTION 0x0200
862865
#define ZEND_FETCH_CLASS_ALLOW_UNLINKED 0x0400
866+
#define ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED 0x0800
863867

864868
#define ZEND_PARAM_REF (1<<0)
865869
#define ZEND_PARAM_VARIADIC (1<<1)

Zend/zend_execute_API.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,8 +863,12 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *
863863
zend_string_release_ex(lc_name, 0);
864864
}
865865
ce = (zend_class_entry*)Z_PTR_P(zv);
866-
if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_LINKED)) &&
867-
!(flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED)) {
866+
if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_LINKED))) {
867+
if ((flags & ZEND_FETCH_CLASS_ALLOW_UNLINKED) ||
868+
((flags & ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED) &&
869+
(ce->ce_flags & ZEND_ACC_NEARLY_LINKED))) {
870+
return ce;
871+
}
868872
return NULL;
869873
}
870874
return ce;

Zend/zend_inheritance.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -975,9 +975,8 @@ static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry
975975
if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce) == FAILURE) {
976976
zend_error_noreturn(E_CORE_ERROR, "Class %s could not implement interface %s", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
977977
}
978-
if (UNEXPECTED(ce == iface)) {
979-
zend_error_noreturn(E_ERROR, "Interface %s cannot implement itself", ZSTR_VAL(ce->name));
980-
}
978+
/* This should be prevented by the class lookup logic. */
979+
ZEND_ASSERT(ce != iface);
981980
}
982981
/* }}} */
983982

@@ -1427,7 +1426,7 @@ static void zend_do_implement_interfaces(zend_class_entry *ce) /* {{{ */
14271426
for (i = 0; i < ce->num_interfaces; i++) {
14281427
iface = zend_fetch_class_by_name(
14291428
ce->interface_names[i].name, ce->interface_names[i].lc_name,
1430-
ZEND_FETCH_CLASS_INTERFACE|ZEND_FETCH_CLASS_ALLOW_UNLINKED);
1429+
ZEND_FETCH_CLASS_INTERFACE|ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED);
14311430
if (!(iface->ce_flags & ZEND_ACC_LINKED)) {
14321431
add_dependency_obligation(ce, iface);
14331432
}
@@ -2324,7 +2323,7 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_na
23242323
{
23252324
if (ce->parent_name) {
23262325
zend_class_entry *parent = zend_fetch_class_by_name(
2327-
ce->parent_name, lc_parent_name, ZEND_FETCH_CLASS_ALLOW_UNLINKED);
2326+
ce->parent_name, lc_parent_name, ZEND_FETCH_CLASS_ALLOW_NEARLY_LINKED);
23282327
if (!(parent->ce_flags & ZEND_ACC_LINKED)) {
23292328
add_dependency_obligation(ce, parent);
23302329
}
@@ -2347,6 +2346,7 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_na
23472346
return;
23482347
}
23492348

2349+
ce->ce_flags |= ZEND_ACC_NEARLY_LINKED;
23502350
load_delayed_classes();
23512351
if (ce->ce_flags & ZEND_ACC_UNRESOLVED_VARIANCE) {
23522352
resolve_delayed_variance_obligations(ce);

0 commit comments

Comments
 (0)