Skip to content

Commit 3bae179

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Fixed bug #78989
2 parents 9a5ea0d + 1146bdb commit 3bae179

File tree

4 files changed

+78
-8
lines changed

4 files changed

+78
-8
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Early binding should be prevented if property types cannot be checked
3+
--FILE--
4+
<?php
5+
6+
class X {}
7+
class_alias('X', 'Y');
8+
9+
class A {
10+
public X $prop;
11+
}
12+
class B extends A {
13+
public Y $prop;
14+
}
15+
16+
?>
17+
===DONE===
18+
--EXPECT--
19+
===DONE===
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Trait delayed variance check fails
3+
--FILE--
4+
<?php
5+
6+
// Taken from bug #78989.
7+
8+
class X {
9+
function method($a): A {}
10+
}
11+
trait T {
12+
function method($r): B {}
13+
}
14+
class U extends X {
15+
use T;
16+
}
17+
18+
?>
19+
--EXPECTF--
20+
Fatal error: Could not check compatibility between T::method($r): B and X::method($a): A, because class B is not available in %s on line %d
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Trait delayed variance check succeeds
3+
--FILE--
4+
<?php
5+
6+
// Taken from bug #79179.
7+
8+
spl_autoload_register(function() {
9+
interface InterfaceB extends InterfaceA {}
10+
});
11+
12+
interface InterfaceA {}
13+
14+
trait SomeTrait {
15+
abstract public function func(): ?InterfaceA;
16+
}
17+
18+
class Foo {
19+
public function func(): ?InterfaceB {}
20+
}
21+
22+
class Bar extends Foo {
23+
use SomeTrait;
24+
}
25+
26+
?>
27+
===DONE===
28+
--EXPECT--
29+
===DONE===

Zend/zend_inheritance.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2210,8 +2210,10 @@ typedef struct {
22102210
union {
22112211
zend_class_entry *dependency_ce;
22122212
struct {
2213-
const zend_function *parent_fn;
2214-
const zend_function *child_fn;
2213+
/* Traits may use temporary on-stack functions during inheritance checks,
2214+
* so use copies of functions here as well. */
2215+
zend_function parent_fn;
2216+
zend_function child_fn;
22152217
};
22162218
struct {
22172219
const zend_property_info *parent_prop;
@@ -2263,8 +2265,8 @@ static void add_compatibility_obligation(
22632265
HashTable *obligations = get_or_init_obligations_for_class(ce);
22642266
variance_obligation *obligation = emalloc(sizeof(variance_obligation));
22652267
obligation->type = OBLIGATION_COMPATIBILITY;
2266-
obligation->child_fn = child_fn;
2267-
obligation->parent_fn = parent_fn;
2268+
obligation->child_fn = *child_fn;
2269+
obligation->parent_fn = *parent_fn;
22682270
zend_hash_next_index_insert_ptr(obligations, obligation);
22692271
}
22702272

@@ -2293,13 +2295,13 @@ static int check_variance_obligation(zval *zv) {
22932295
}
22942296
} else if (obligation->type == OBLIGATION_COMPATIBILITY) {
22952297
inheritance_status status = zend_do_perform_implementation_check(
2296-
obligation->child_fn, obligation->parent_fn);
2298+
&obligation->child_fn, &obligation->parent_fn);
22972299
if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
22982300
if (EXPECTED(status == INHERITANCE_UNRESOLVED)) {
22992301
return ZEND_HASH_APPLY_KEEP;
23002302
}
23012303
ZEND_ASSERT(status == INHERITANCE_ERROR);
2302-
emit_incompatible_method_error(obligation->child_fn, obligation->parent_fn, status);
2304+
emit_incompatible_method_error(&obligation->child_fn, &obligation->parent_fn, status);
23032305
}
23042306
/* Either the compatibility check was successful or only threw a warning. */
23052307
} else {
@@ -2366,10 +2368,10 @@ static void report_variance_errors(zend_class_entry *ce) {
23662368
/* Just used to populate the delayed_autoloads table,
23672369
* which will be used when printing the "unresolved" error. */
23682370
inheritance_status status = zend_do_perform_implementation_check(
2369-
obligation->child_fn, obligation->parent_fn);
2371+
&obligation->child_fn, &obligation->parent_fn);
23702372
ZEND_ASSERT(status == INHERITANCE_UNRESOLVED);
23712373
emit_incompatible_method_error(
2372-
obligation->child_fn, obligation->parent_fn, status);
2374+
&obligation->child_fn, &obligation->parent_fn, status);
23732375
} else if (obligation->type == OBLIGATION_PROPERTY_COMPATIBILITY) {
23742376
emit_incompatible_property_error(obligation->child_prop, obligation->parent_prop);
23752377
} else {

0 commit comments

Comments
 (0)