Skip to content

Commit 0061db5

Browse files
committed
Fix #77291: magic methods inherited from a trait may be ignored
When adding methods from a trait, we must not assume that a method name with the same length as the name of the using class is either a PHP 4 style constructor, or not a magic method at all – it may well be another magic method. We mostly preserve the spirit of the optimization which caused this regression, and avoid string comparisons for all method names which can never be magic methods.
1 parent 54739c7 commit 0061db5

File tree

3 files changed

+56
-12
lines changed

3 files changed

+56
-12
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ PHP NEWS
88
(Valentin V. Bartenev)
99
. Fixed bug #76046 (PHP generates "FE_FREE" opcode on the wrong line).
1010
(Nikita)
11+
. Fixed bug #77291 (magic methods inherited from a trait may be ignored).
12+
(cmb)
1113

1214
- CURL:
1315
. Fixed bug #77264 (curl_getinfo returning microseconds, not seconds).

Zend/tests/bug77291.phpt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
Bug #77291 (magic methods inherited from a trait may be ignored)
3+
--FILE--
4+
<?php
5+
6+
trait AccessibleProperties
7+
{
8+
public function __isset($property)
9+
{
10+
return property_exists($this, $property);
11+
}
12+
13+
public function __get($property)
14+
{
15+
if (property_exists($this, $property)) {
16+
return $this->$property;
17+
}
18+
}
19+
}
20+
21+
class Foo4567 {
22+
use AccessibleProperties;
23+
24+
protected $a = 'Some value';
25+
}
26+
27+
class Foo45 {
28+
use AccessibleProperties;
29+
30+
protected $a = 'Some value';
31+
}
32+
33+
$foo = new Foo4567;
34+
var_dump(isset($foo->a));
35+
$foo = new Foo45;
36+
var_dump($foo->a);
37+
?>
38+
===DONE===
39+
--EXPECT--
40+
bool(true)
41+
string(10) "Some value"
42+
===DONE===

Zend/zend_inheritance.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,18 +1126,7 @@ static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_
11261126

11271127
static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zend_function* fe) /* {{{ */
11281128
{
1129-
if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) {
1130-
zend_string *lowercase_name = zend_string_tolower(ce->name);
1131-
lowercase_name = zend_new_interned_string(lowercase_name);
1132-
if (!memcmp(ZSTR_VAL(mname), ZSTR_VAL(lowercase_name), ZSTR_LEN(mname))) {
1133-
if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
1134-
zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name));
1135-
}
1136-
ce->constructor = fe;
1137-
fe->common.fn_flags |= ZEND_ACC_CTOR;
1138-
}
1139-
zend_string_release_ex(lowercase_name, 0);
1140-
} else if (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_') {
1129+
if (ZSTR_LEN(ce->name) != ZSTR_LEN(mname) && (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_')) {
11411130
/* pass */
11421131
} else if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) {
11431132
ce->clone = fe;
@@ -1168,6 +1157,17 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen
11681157
ce->__tostring = fe;
11691158
} else if (zend_string_equals_literal(mname, ZEND_DEBUGINFO_FUNC_NAME)) {
11701159
ce->__debugInfo = fe;
1160+
} else if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) {
1161+
zend_string *lowercase_name = zend_string_tolower(ce->name);
1162+
lowercase_name = zend_new_interned_string(lowercase_name);
1163+
if (!memcmp(ZSTR_VAL(mname), ZSTR_VAL(lowercase_name), ZSTR_LEN(mname))) {
1164+
if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
1165+
zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name));
1166+
}
1167+
ce->constructor = fe;
1168+
fe->common.fn_flags |= ZEND_ACC_CTOR;
1169+
}
1170+
zend_string_release_ex(lowercase_name, 0);
11711171
}
11721172
}
11731173
/* }}} */

0 commit comments

Comments
 (0)