Skip to content

Commit 8e0789a

Browse files
committed
Use proper parameter type in Closure::bindTo() signature
1 parent 4c821cf commit 8e0789a

File tree

4 files changed

+47
-42
lines changed

4 files changed

+47
-42
lines changed

Zend/tests/closure_040.phpt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,16 @@ $a = new A(20);
2424
$ca = $a->getIncrementor();
2525
$cas = $a->getStaticIncrementor();
2626

27-
$ca->bindTo($a, array());
27+
try {
28+
$ca->bindTo($a, array());
29+
} catch (TypeError $e) {
30+
echo $e->getMessage(), "\n";
31+
}
2832

2933
$cas->bindTo($a, 'A');
3034

3135
?>
3236
--EXPECTF--
33-
Warning: Array to string conversion in %s on line %d
34-
35-
Warning: Class "Array" not found in %s on line %d
37+
Closure::bindTo(): Argument #2 ($newScope) must be of type object|string|null, array given
3638

3739
Warning: Cannot bind an instance to a static closure in %s on line %d

Zend/zend_closures.c

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -192,30 +192,22 @@ ZEND_METHOD(Closure, call)
192192
}
193193
/* }}} */
194194

195-
static void do_closure_bind(zval *return_value, zval *zclosure, zval *newthis, zval *scope_arg)
195+
static void do_closure_bind(zval *return_value, zval *zclosure, zval *newthis, zend_object *scope_obj, zend_string *scope_str)
196196
{
197197
zend_class_entry *ce, *called_scope;
198198
zend_closure *closure = (zend_closure *) Z_OBJ_P(zclosure);
199199

200-
if (scope_arg != NULL) { /* scope argument was given */
201-
if (Z_TYPE_P(scope_arg) == IS_OBJECT) {
202-
ce = Z_OBJCE_P(scope_arg);
203-
} else if (Z_TYPE_P(scope_arg) == IS_NULL) {
204-
ce = NULL;
205-
} else {
206-
zend_string *tmp_class_name;
207-
zend_string *class_name = zval_get_tmp_string(scope_arg, &tmp_class_name);
208-
if (zend_string_equals_literal(class_name, "static")) {
209-
ce = closure->func.common.scope;
210-
} else if ((ce = zend_lookup_class(class_name)) == NULL) {
211-
zend_error(E_WARNING, "Class \"%s\" not found", ZSTR_VAL(class_name));
212-
zend_tmp_string_release(tmp_class_name);
213-
RETURN_NULL();
214-
}
215-
zend_tmp_string_release(tmp_class_name);
200+
if (scope_obj) {
201+
ce = scope_obj->ce;
202+
} else if (scope_str) {
203+
if (zend_string_equals(scope_str, ZSTR_KNOWN(ZEND_STR_STATIC))) {
204+
ce = closure->func.common.scope;
205+
} else if ((ce = zend_lookup_class(scope_str)) == NULL) {
206+
zend_error(E_WARNING, "Class \"%s\" not found", ZSTR_VAL(scope_str));
207+
RETURN_NULL();
216208
}
217-
} else { /* scope argument not given; do not change the scope by default */
218-
ce = closure->func.common.scope;
209+
} else {
210+
ce = NULL;
219211
}
220212

221213
if (!zend_valid_closure_binding(closure, newthis, ce)) {
@@ -234,25 +226,34 @@ static void do_closure_bind(zval *return_value, zval *zclosure, zval *newthis, z
234226
/* {{{ Create a closure from another one and bind to another object and scope */
235227
ZEND_METHOD(Closure, bind)
236228
{
237-
zval *newthis, *zclosure, *scope_arg = NULL;
238-
239-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) {
240-
RETURN_THROWS();
241-
}
229+
zval *zclosure, *newthis;
230+
zend_object *scope_obj = NULL;
231+
zend_string *scope_str = ZSTR_KNOWN(ZEND_STR_STATIC);
232+
233+
ZEND_PARSE_PARAMETERS_START(2, 3)
234+
Z_PARAM_OBJECT_OF_CLASS(zclosure, zend_ce_closure)
235+
Z_PARAM_OBJECT_OR_NULL(newthis)
236+
Z_PARAM_OPTIONAL
237+
Z_PARAM_OBJ_OR_STR_OR_NULL(scope_obj, scope_str)
238+
ZEND_PARSE_PARAMETERS_END();
242239

243-
do_closure_bind(return_value, zclosure, newthis, scope_arg);
240+
do_closure_bind(return_value, zclosure, newthis, scope_obj, scope_str);
244241
}
245242

246243
/* {{{ Create a closure from another one and bind to another object and scope */
247244
ZEND_METHOD(Closure, bindTo)
248245
{
249-
zval *newthis, *scope_arg = NULL;
250-
251-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!|z", &newthis, &scope_arg) == FAILURE) {
252-
RETURN_THROWS();
253-
}
246+
zval *newthis;
247+
zend_object *scope_obj = NULL;
248+
zend_string *scope_str = ZSTR_KNOWN(ZEND_STR_STATIC);
249+
250+
ZEND_PARSE_PARAMETERS_START(1, 2)
251+
Z_PARAM_OBJECT_OR_NULL(newthis)
252+
Z_PARAM_OPTIONAL
253+
Z_PARAM_OBJ_OR_STR_OR_NULL(scope_obj, scope_str)
254+
ZEND_PARSE_PARAMETERS_END();
254255

255-
do_closure_bind(return_value, getThis(), newthis, scope_arg);
256+
do_closure_bind(return_value, getThis(), newthis, scope_obj, scope_str);
256257
}
257258

258259
static ZEND_NAMED_FUNCTION(zend_closure_call_magic) /* {{{ */ {

Zend/zend_closures.stub.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ final class Closure
66
{
77
private function __construct() {}
88

9-
/** @param object|string|null $newScope */
10-
public static function bind(Closure $closure, ?object $newThis, $newScope = UNKNOWN): ?Closure {}
9+
public static function bind(
10+
Closure $closure,
11+
?object $newThis,
12+
object|string|null $newScope = "static"
13+
): ?Closure {}
1114

12-
/** @param object|string|null $newScope */
13-
public function bindTo(?object $newThis, $newScope = UNKNOWN): ?Closure {}
15+
public function bindTo(?object $newThis, object|string|null $newScope = "static"): ?Closure {}
1416

1517
public function call(object $newThis, mixed ...$arguments): mixed {}
1618

Zend/zend_closures_arginfo.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: abbbe7b04323dc44b0675ad58700e996a6d7c43b */
2+
* Stub hash: 6c9840dd5c2e4c597cd0133bf2d0b523c272d3fe */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Closure___construct, 0, 0, 0)
55
ZEND_END_ARG_INFO()
66

77
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Closure_bind, 0, 2, Closure, 1)
88
ZEND_ARG_OBJ_INFO(0, closure, Closure, 0)
99
ZEND_ARG_TYPE_INFO(0, newThis, IS_OBJECT, 1)
10-
ZEND_ARG_INFO(0, newScope)
10+
ZEND_ARG_TYPE_MASK(0, newScope, MAY_BE_OBJECT|MAY_BE_STRING|MAY_BE_NULL, "\"static\"")
1111
ZEND_END_ARG_INFO()
1212

1313
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Closure_bindTo, 0, 1, Closure, 1)
1414
ZEND_ARG_TYPE_INFO(0, newThis, IS_OBJECT, 1)
15-
ZEND_ARG_INFO(0, newScope)
15+
ZEND_ARG_TYPE_MASK(0, newScope, MAY_BE_OBJECT|MAY_BE_STRING|MAY_BE_NULL, "\"static\"")
1616
ZEND_END_ARG_INFO()
1717

1818
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Closure_call, 0, 1, IS_MIXED, 0)

0 commit comments

Comments
 (0)