8000 Fix bug #81237 comparison of fake closures doesn't work · php/php-src@6a9daaf · GitHub
[go: up one dir, main page]

Skip to content

Commit 6a9daaf

Browse files
committed
Fix bug #81237 comparison of fake closures doesn't work
1 parent 5e0874f commit 6a9daaf

File tree

3 files changed

+148
-1
lines changed

3 files changed

+148
-1
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ PHP NEWS
44

55
- Core:
66
. Fixed bug #81238 (Fiber support missing for Solaris Sparc). (trowski)
7+
. Fixed bug #81237 (Comparison of fake closures doesn't work). (krakjoe)
78

89
- Reflection:
910
. Fixed bug #80097 (ReflectionAttribute is not a Reflector). (beberlei)

Zend/tests/closure_compare.phpt

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
--TEST--
2+
Closure comparison
3+
--FILE--
4+
<?php
5+
function foo() {
6+
static $var;
7+
}
8+
9+
$closures[0] = Closure::fromCallable('foo');
10+
$closures[1] = Closure::fromCallable('foo');
11+
12+
printf("foo == foo: %s\n", $closures[0] == $closures[1] ? "OK" : "FAIL");
13+
14+
$closures[0] = Closure::fromCallable('strlen');
15+
$closures[1] = Closure::fromCallable('strlen');
16+
17+
printf("strlen == strlen: %s\n", $closures[0] == $closures[1] ? "OK" : "FAIL");
18+
19+
$closures[0] = Closure::fromCallable('strlen');
20+
$closures[1] = Closure::fromCallable('strrev');
21+
22+
printf("strlen != strrev: %s\n", $closures[0] != $closures[1] ? "OK" : "FAIL");
23+
24+
trait MethodTrait {
25+
public function traitMethod(){}
26+
}
27+
28+
class Foo {
29+
use MethodTrait {
30+
MethodTrait::traitMethod as aliasMethod;
31+
}
32+
33+
public function __call($method, $args) {
34+
35+
}
36+
37+
public function exists() {}
38+
39+
public static function existsStatic() {}
40+
}
41+
42+
class Bar extends Foo {}
43+
44+
class Baz {
45+
use MethodTrait;
46+
}
47+
48+
$closures[0] = Closure::fromCallable([Foo::class, "existsStatic"]);
49+
$closures[1] = Closure::fromCallable([Bar::class, "existsStatic"]);
50+
51+
printf("foo::existsStatic != bar::existsStatic: %s\n", $closures[0] != $closures[1] ? "OK" : "FAIL");
52+
53+
$foo = new Foo;
54+
55+
$closures[0] = Closure::fromCallable([$foo, "exists"]);
56+
$closures[1] = $closures[0]->bindTo(new Foo);
57+
58+
printf("foo#0::exists != foo#1::exists: %s\n", $closures[0] != $closures[1] ? "OK" : "FAIL");
59+
60+
$baz = new Baz;
61+
62+
$closures[0] = Closure::fromCallable([$foo, "traitMethod"]);
63+
$closures[1] = Closure::fromCallable([$baz, "traitMethod"]);
64+
65+
printf("foo::traitMethod != baz::traitMethod: %s\n", $closures[0] != $closures[1] ? "OK" : "FAIL");
66+
67+
$closures[0] = Closure::fromCallable([$foo, "traitMethod"]);
68+
$closures[1] = Closure::fromCallable([$foo, "aliasMethod"]);
69+
70+
printf("foo::traitMethod != foo::aliasMethod: %s\n", $closures[0] != $closures[1] ? "OK" : "FAIL");
71+
72+
$closures[0] = Closure::fromCallable([$foo, "exists"]);
73+
$closures[1] = Closure::fromCallable([$foo, "exists"]);
74+
75+
printf("foo::exists == foo::exists: %s\n", $closures[0] == $closures[1] ? "OK" : "FAIL");
76+
77+
$closures[0] = Closure::fromCallable([$foo, "method"]);
78+
$closures[1] = Closure::fromCallable([$foo, "method"]);
79+
80+
printf("foo::method == foo::method: %s\n", $closures[0] == $closures[1] ? "OK" : "FAIL");
81+
82+
$closures[1] = $closures[1]->bindTo(new Bar);
83+
84+
printf("foo::method != bar::method: %s\n", $closures[0] != $closures[1] ? "OK" : "FAIL");
85+
86+
$closures[0] = Closure::fromCallable([$foo, "method"]);
87+
$closures[1] = Closure::fromCallable([$foo, "method2"]);
88+
89+
printf("foo::method != foo::method2: %s\n", $closures[0] != $closures[1] ? "OK" : "FAIL");
90+
91+
$closures[2] = Closure::fromCallable([$closures[0], "__invoke"]);
92+
$closures[3] = Closure::fromCallable([$closures[1], "__invoke"]);
93+
94+
printf("Closure[0]::invoke != Closure[1]::invoke: %s\n", $closures[2] != $closures[3] ? "OK" : "FAIL");
95+
96+
$closures[2] = Closure::fromCallable([$closures[0], "__invoke"]);
97+
$closures[3] = Closure::fromCallable([$closures[0], "__invoke"]);
98+
99+
printf("Closure[0]::invoke == Closure[0]::invoke: %s\n", $closures[2] == $closures[3] ? "OK" : "FAIL");
100+
?>
101+
--EXPECT--
102+
foo == foo: OK
103+
strlen == strlen: OK
104+
strlen != strrev: OK
105+
foo::existsStatic != bar::existsStatic: OK
106+
foo#0::exists != foo#1::exists: OK
107+
foo::traitMethod != baz::traitMethod: OK
108+
foo::traitMethod != foo::aliasMethod: OK
109+
foo::exists == foo::exists: OK
110+
foo::method == foo::method: OK
111+
foo::method != bar::method: OK
112+
foo::method != foo::method2: OK
113+
Closure[0]::invoke != Closure[1]::invoke: OK
114+
Closure[0]::invoke == Closure[0]::invoke: OK

Zend/zend_closures.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,39 @@ static ZEND_COLD zend_function *zend_closure_get_constructor(zend_object *object
381381
static int zend_closure_compare(zval *o1, zval *o2) /* {{{ */
382382
{
383383
ZEND_COMPARE_OBJECTS_FALLBACK(o1, o2);
384-
return Z_OBJ_P(o1) != Z_OBJ_P(o2);
384+
385+
zend_closure *lhs = (zend_closure*) Z_OBJ_P(o1);
386+
zend_closure *rhs = (zend_closure*) Z_OBJ_P(o2);
387+
388+
if (!((lhs->func.common.fn_flags & ZEND_ACC_FAKE_CLOSURE) && (rhs->func.common.fn_flags & ZEND_ACC_FAKE_CLOSURE))) {
389+
return ZEND_UNCOMPARABLE;
390+
}
391+
392+
if (Z_TYPE(lhs->this_ptr) != Z_TYPE(rhs->this_ptr)) {
393+
return ZEND_UNCOMPARABLE;
394+
}
395+
396+
if (Z_TYPE(lhs->this_ptr) == IS_OBJECT && Z_OBJ(lhs->this_ptr) != Z_OBJ(rhs->this_ptr)) {
397+
return ZEND_UNCOMPARABLE;
398+
}
399+
400+
if (lhs->called_scope != rhs->called_scope) {
401+
return ZEND_UNCOMPARABLE;
402+
}
403+
404+
if (lhs->func.type != rhs->func.type) {
405+
return ZEND_UNCOMPARABLE;
406+
}
407+
408+
if (lhs->func.common.scope != rhs->func.common.scope) {
409+
return ZEND_UNCOMPARABLE;
410+
}
411+
412+
if (!zend_string_equals(lhs->func.common.function_name, rhs->func.common.function_name)) {
413+
return ZEND_UNCOMPARABLE;
414+
}
415+
416+
return 0;
385417
}
386418
/* }}} */
387419

0 commit comments

Comments
 (0)
0