summaryrefslogtreecommitdiff
path: root/Zend/zend_execute.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-06-06 13:05:11 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-06-17 11:46:28 +0200
commit4d90848d68c4e9a07f8c687f781ae8843d4f64d3 (patch)
treeb66351de514352ebc031b5a8b0a92464b3e5f5e9 /Zend/zend_execute.c
parentbe6c083f28c27a3db1456edaa3be38063d4e7bc9 (diff)
downloadphp-git-4d90848d68c4e9a07f8c687f781ae8843d4f64d3.tar.gz
Don't verify arginfo types for internal functions
To avoid duplicate type checks. In debug builds arginfo is still checked and will generate an assertions if the function doesn't subsequently throw an exception. Some test results change due to differences in zpp and arginfo error messages.
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r--Zend/zend_execute.c70
1 files changed, 52 insertions, 18 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 06baae76e4..7a57a2c403 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -888,6 +888,34 @@ static zend_bool zend_verify_weak_scalar_type_hint(zend_uchar type_hint, zval *a
}
}
+#if ZEND_DEBUG
+/* Used to sanity-check internal arginfo types without performing any actual type conversions. */
+static zend_bool zend_verify_weak_scalar_type_hint_no_sideeffect(zend_uchar type_hint, zval *arg)
+{
+ switch (type_hint) {
+ case _IS_BOOL: {
+ zend_bool dest;
+ return zend_parse_arg_bool_weak(arg, &dest);
+ }
+ case IS_LONG: {
+ zend_long dest;
+ return zend_parse_arg_long_weak(arg, &dest);
+ }
+ case IS_DOUBLE: {
+ double dest;
+ return zend_parse_arg_double_weak(arg, &dest);
+ }
+ case IS_STRING:
+ /* We don't call cast_object here, because this check must be side-effect free. As this
+ * is only used for a sanity check of arginfo/zpp consistency, it's okay if we accept
+ * more than actually allowed here. */
+ return Z_TYPE_P(arg) < IS_STRING || Z_TYPE_P(arg) == IS_OBJECT;
+ default:
+ return 0;
+ }
+}
+#endif
+
static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict, zend_bool is_internal_arg)
{
if (UNEXPECTED(strict)) {
@@ -903,6 +931,11 @@ static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, z
}
return 0;
}
+#if ZEND_DEBUG
+ if (is_internal_arg) {
+ return zend_verify_weak_scalar_type_hint_no_sideeffect(type_hint, arg);
+ }
+#endif
return zend_verify_weak_scalar_type_hint(type_hint, arg);
}
@@ -1083,7 +1116,7 @@ static zend_always_inline zend_bool zend_check_type(
* because this case is already checked at compile-time. */
}
-static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot, zend_bool is_internal)
+static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)
{
zend_arg_info *cur_arg_info;
zend_class_entry *ce;
@@ -1097,7 +1130,7 @@ static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t a
}
ce = NULL;
- if (UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &ce, cache_slot, default_value, zf->common.scope, 0, is_internal))) {
+ if (UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &ce, cache_slot, default_value, zf->common.scope, 0, 0))) {
zend_verify_arg_error(zf, cur_arg_info, arg_num, ce, arg);
return 0;
}
@@ -1140,21 +1173,29 @@ static zend_always_inline int zend_verify_variadic_arg_type(zend_function *zf, u
return 1;
}
-static zend_never_inline int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call)
+static zend_never_inline ZEND_ATTRIBUTE_UNUSED int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call)
{
uint32_t i;
uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
- zval *p = ZEND_CALL_ARG(call, 1);
- void *dummy_cache_slot;
+ zval *arg = ZEND_CALL_ARG(call, 1);
for (i = 0; i < num_args; ++i) {
- dummy_cache_slot = NULL;
- if (UNEXPECTED(!zend_verify_arg_type(fbc, i + 1, p, NULL, &dummy_cache_slot, 1))) {
- EG(current_execute_data) = call->prev_execute_data;
- zend_vm_stack_free_args(call);
+ zend_arg_info *cur_arg_info;
+ zend_class_entry *ce = NULL;
+ void *dummy_cache_slot = NULL;
+
+ if (EXPECTED(i < fbc->common.num_args)) {
+ cur_arg_info = &fbc->common.arg_info[i];
+ } else if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
+ cur_arg_info = &fbc->common.arg_info[fbc->common.num_args];
+ } else {
+ break;
+ }
+
+ if (UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &ce, &dummy_cache_slot, NULL, fbc->common.scope, 0, /* is_internal_arg */ 1))) {
return 0;
}
- p++;
+ arg++;
}
return 1;
}
@@ -4444,14 +4485,7 @@ ZEND_API zval *zend_get_zval_ptr(const zend_op *opline, int op_type, const znode
return ret;
}
-ZEND_API void ZEND_FASTCALL zend_check_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
-{
- void *dummy_cache_slot = NULL;
-
- zend_verify_arg_type(zf, arg_num, arg, NULL, &dummy_cache_slot, 1);
-}
-
ZEND_API int ZEND_FASTCALL zend_check_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)
{
- return zend_verify_arg_type(zf, arg_num, arg, default_value, cache_slot, 0);
+ return zend_verify_arg_type(zf, arg_num, arg, default_value, cache_slot);
}