diff options
| author | Christoph M. Becker <cmbecker69@gmx.de> | 2019-09-23 23:48:36 +0200 |
|---|---|---|
| committer | Christoph M. Becker <cmbecker69@gmx.de> | 2019-09-24 16:08:42 +0200 |
| commit | 0c7124e6beff0a7b0540691db370148be06d242a (patch) | |
| tree | b37b67cf5a92c16680c837390a20c9ff52731e5e | |
| parent | 1fe47ad233b45f3313e8942c3190fd5ca03952f0 (diff) | |
| download | php-git-0c7124e6beff0a7b0540691db370148be06d242a.tar.gz | |
Add check_only parameter to get_closure handler
`get_closure` handlers are called to check whether an object is
callable, and to actually get the closure, respectively. The behavior
of the handler might differ for these two cases, particularly the
handler may throw in the latter case, but should not in the former.
Therefore we add a `check_only` parameter, to be able to distinguish
the desired purpose.
| -rw-r--r-- | Zend/zend_API.c | 10 | ||||
| -rw-r--r-- | Zend/zend_closures.c | 2 | ||||
| -rw-r--r-- | Zend/zend_execute.c | 2 | ||||
| -rw-r--r-- | Zend/zend_object_handlers.c | 2 | ||||
| -rw-r--r-- | Zend/zend_object_handlers.h | 4 | ||||
| -rw-r--r-- | ext/ffi/ffi.c | 14 | ||||
| -rw-r--r-- | ext/reflection/php_reflection.c | 4 |
7 files changed, 19 insertions, 19 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 472d886467..34fcf1506a 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3105,7 +3105,7 @@ try_again: zend_object *zobj = Z_OBJ_P(callable); if (zobj->handlers->get_closure - && zobj->handlers->get_closure(zobj, &calling_scope, &fptr, &object) == SUCCESS) { + && zobj->handlers->get_closure(zobj, &calling_scope, &fptr, &object, 1) == SUCCESS) { zend_class_entry *ce = zobj->ce; zend_string *callable_name = zend_string_alloc( ZSTR_LEN(ce->name) + sizeof("::__invoke") - 1, 0); @@ -3230,18 +3230,12 @@ check_func: } return 0; case IS_OBJECT: - if (Z_OBJ_HANDLER_P(callable, get_closure)) { - if (Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object) == SUCCESS) { + if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object, 1) == SUCCESS) { fcc->called_scope = fcc->calling_scope; if (fcc == &fcc_local) { zend_release_fcall_info_cache(fcc); } return 1; - } else { - /* Discard exceptions thrown from Z_OBJ_HANDLER_P(callable, get_closure) - TODO: extend get_closure() with additional argument and prevent exception throwing in the first place */ - zend_clear_exception(); - } } if (error) *error = estrdup("no array or string given"); return 0; diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index d6cb6abc7a..68e698b626 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -490,7 +490,7 @@ static zend_object *zend_closure_clone(zend_object *zobject) /* {{{ */ } /* }}} */ -int zend_closure_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */ +int zend_closure_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, zend_bool check_only) /* {{{ */ { zend_closure *closure = (zend_closure *)obj; *fptr_ptr = &closure->func; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 2c3ed7e5ae..2c7b9f5030 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3956,7 +3956,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_o uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC; if (EXPECTED(function->handlers->get_closure) && - EXPECTED(function->handlers->get_closure(function, &called_scope, &fbc, &object) == SUCCESS)) { + EXPECTED(function->handlers->get_closure(function, &called_scope, &fbc, &object, 0) == SUCCESS)) { object_or_called_scope = called_scope; if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) { diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 6530913174..f60083d858 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1767,7 +1767,7 @@ ZEND_API int zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, } /* }}} */ -ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */ +ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, zend_bool check_only) /* {{{ */ { zval *func; zend_class_entry *ce = obj->ce; diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 05ebb0b1ef..d8d7aca86c 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -135,7 +135,7 @@ typedef int (*zend_object_cast_t)(zend_object *readobj, zval *retval, int type); * Returns FAILURE if the object does not have any sense of overloaded dimensions */ typedef int (*zend_object_count_elements_t)(zend_object *object, zend_long *count); -typedef int (*zend_object_get_closure_t)(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr); +typedef int (*zend_object_get_closure_t)(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, zend_bool check_only); typedef HashTable *(*zend_object_get_gc_t)(zend_object *object, zval **table, int *n); @@ -208,7 +208,7 @@ ZEND_API void zend_std_unset_dimension(zend_object *object, zval *offset); ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key); ZEND_API zend_string *zend_std_get_class_name(const zend_object *zobj); ZEND_API int zend_std_compare_objects(zval *o1, zval *o2); -ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr); +ZEND_API int zend_std_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, zend_bool check_only); ZEND_API void rebuild_object_properties(zend_object *zobj); ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope); diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index aae8b3ab21..c3fbc112bf 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -1984,23 +1984,29 @@ static HashTable *zend_ffi_cdata_get_debug_info(zend_object *obj, int *is_temp) } /* }}} */ -static int zend_ffi_cdata_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr) /* {{{ */ +static int zend_ffi_cdata_get_closure(zend_object *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zend_object **obj_ptr, zend_bool check_only) /* {{{ */ { zend_ffi_cdata *cdata = (zend_ffi_cdata*)obj; zend_ffi_type *type = ZEND_FFI_TYPE(cdata->type); zend_function *func; if (type->kind != ZEND_FFI_TYPE_POINTER) { - zend_throw_error(zend_ffi_exception_ce, "Attempt to call non C function pointer"); + if (!check_only) { + zend_throw_error(zend_ffi_exception_ce, "Attempt to call non C function pointer"); + } return FAILURE; } type = ZEND_FFI_TYPE(type->pointer.type); if (type->kind != ZEND_FFI_TYPE_FUNC) { - zend_throw_error(zend_ffi_exception_ce, "Attempt to call non C function pointer"); + if (!check_only) { + zend_throw_error(zend_ffi_exception_ce, "Attempt to call non C function pointer"); + } return FAILURE; } if (!cdata->ptr) { - zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); + if (!check_only) { + zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); + } return FAILURE; } diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index a6aa982f0d..5c775ed926 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1794,7 +1794,7 @@ ZEND_METHOD(reflection_function, invoke) if (!Z_ISUNDEF(intern->obj)) { Z_OBJ_HT(intern->obj)->get_closure( - Z_OBJ(intern->obj), &fcc.called_scope, &fcc.function_handler, &fcc.object); + Z_OBJ(intern->obj), &fcc.called_scope, &fcc.function_handler, &fcc.object, 0); } result = zend_call_function(&fci, &fcc); @@ -1857,7 +1857,7 @@ ZEND_METHOD(reflection_function, invokeArgs) if (!Z_ISUNDEF(intern->obj)) { Z_OBJ_HT(intern->obj)->get_closure( - Z_OBJ(intern->obj), &fcc.called_scope, &fcc.function_handler, &fcc.object); + Z_OBJ(intern->obj), &fcc.called_scope, &fcc.function_handler, &fcc.object, 0); } result = zend_call_function(&fci, &fcc); |
