From fa120845ccbf34587ffe31da1cf2a0b00b414d9f Mon Sep 17 00:00:00 2001 From: rjhdby Date: Mon, 28 Jan 2019 17:57:45 +0300 Subject: [PATCH 01/12] Optimizing checks. Reorder conditions and "if else" blocks. More light and probable to top. Join nested "if"s to parent "if" or "else" if no branching. --- Zend/zend_compile.c | 294 ++++++++++++++++++++------------------------ 1 file changed, 130 insertions(+), 164 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 01c90559db7a..dd0ca5433b32 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -986,10 +986,9 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */ if (op_array->refcount) { (*op_array->refcount)++; } - if (op_array->static_variables) { - if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(op_array->static_variables); - } + if (op_array->static_variables + && !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(op_array->static_variables); } ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*))); @@ -1232,7 +1231,7 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i if (c && ( ((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) - && (!(ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE) || !(CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) + && !((ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE) && (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) || (Z_TYPE(c->value) < IS_OBJECT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) )) { ZVAL_COPY_OR_DUP(zv, &c->value); @@ -2366,8 +2365,7 @@ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t if (dim_ast == NULL) { if (type == BP_VAR_R || type == BP_VAR_IS) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading"); - } - if (type == BP_VAR_UNSET) { + } else if (type == BP_VAR_UNSET) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting"); } dim_node.op_type = IS_UNUSED; @@ -2949,26 +2947,26 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */ } arg_count++; - if (zend_is_variable_or_call(arg)) { - if (zend_is_call(arg)) { - zend_compile_var(&arg_node, arg, BP_VAR_R, 0); - if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) { - /* Function call was converted into builtin instruction */ - opcode = ZEND_SEND_VAL; - } else { - if (fbc) { - if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) { - opcode = ZEND_SEND_VAR_NO_REF; - } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) { - opcode = ZEND_SEND_VAL; - } else { - opcode = ZEND_SEND_VAR; - } + if (zend_is_call(arg)) { + zend_compile_var(&arg_node, arg, BP_VAR_R, 0); + if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) { + /* Function call was converted into builtin instruction */ + opcode = ZEND_SEND_VAL; + } else { + if (fbc) { + if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) { + opcode = ZEND_SEND_VAR_NO_REF; + } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) { + opcode = ZEND_SEND_VAL; } else { - opcode = ZEND_SEND_VAR_NO_REF_EX; + opcode = ZEND_SEND_VAR; } + } else { + opcode = ZEND_SEND_VAR_NO_REF_EX; } - } else if (fbc) { + } + } else if (zend_is_variable(arg)) { + if (fbc) { if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) { zend_compile_var(&arg_node, arg, BP_VAR_W, 1); opcode = ZEND_SEND_REF; @@ -3369,9 +3367,9 @@ int zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcna zend_bool is_fully_qualified; zend_string *name = zend_resolve_function_name(orig_name, args->child[1]->child[0]->attr, &is_fully_qualified); - if (zend_string_equals_literal_ci(name, "array_slice") - && list->children == 3 - && list->child[1]->kind == ZEND_AST_ZVAL) { + if (list->children == 3 + && list->child[1]->kind == ZEND_AST_ZVAL + && zend_string_equals_literal_ci(name, "array_slice")) { zval *zv = zend_ast_get_zval(list->child[1]); if (Z_TYPE_P(zv) == IS_LONG @@ -3671,10 +3669,10 @@ int zend_compile_func_array_slice(znode *result, zend_ast_list *args) /* {{{ */ zval *zv = zend_ast_get_zval(args->child[1]); znode first; - if (zend_string_equals_literal_ci(name, "func_get_args") - && list->children == 0 + if (list->children == 0 && Z_TYPE_P(zv) == IS_LONG - && Z_LVAL_P(zv) >= 0) { + && Z_LVAL_P(zv) >= 0 + && zend_string_equals_literal_ci(name, "func_get_args")) { first.op_type = IS_CONST; ZVAL_LONG(&first.u.constant, Z_LVAL_P(zv)); zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, &first, NULL); @@ -3704,69 +3702,70 @@ int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_l if (zend_args_contain_unpack(args)) { return FAILURE; } - - if (zend_string_equals_literal(lcname, "strlen")) { + /* Ordered according to usage frequency on github (millions results) + * search query "func_name language:PHP stars:>1000 extension:php" */ + if (zend_string_equals_literal(lcname, "is_array")) { //40 + return zend_compile_func_typecheck(result, args, IS_ARRAY); + } else if (zend_string_equals_literal(lcname, "in_array")) { //36 + return zend_compile_func_in_array(result, args); + } else if (zend_string_equals_literal(lcname, "strlen")) { //32 return zend_compile_func_strlen(result, args); - } else if (zend_string_equals_literal(lcname, "is_null")) { + } else if (zend_string_equals_literal(lcname, "is_string")) { //24 + return zend_compile_func_typecheck(result, args, IS_STRING); + } else if (zend_string_equals_literal(lcname, "is_object")) { //17 + return zend_compile_func_typecheck(result, args, IS_OBJECT); + } else if (zend_string_equals_literal(lcname, "array_key_exists")) { //16 + return zend_compile_func_array_key_exists(result, args); + } else if (zend_string_equals_literal(lcname, "is_null")) { //15 return zend_compile_func_typecheck(result, args, IS_NULL); - } else if (zend_string_equals_literal(lcname, "is_bool")) { - return zend_compile_func_typecheck(result, args, _IS_BOOL); - } else if (zend_string_equals_literal(lcname, "is_long") - || zend_string_equals_literal(lcname, "is_int") - || zend_string_equals_literal(lcname, "is_integer") + } else if (zend_string_equals_literal(lcname, "intval")) { //14 + return zend_compile_func_cast(result, args, IS_LONG); + } else if (zend_string_equals_literal(lcname, "call_user_func")) { //11 + return zend_compile_func_cuf(result, args, lcname); + } else if (zend_string_equals_literal(lcname, "call_user_func_array")) { //9 + return zend_compile_func_cufa(result, args, lcname); + } else if (zend_string_equals_literal(lcname, "count")) { //very many + return zend_compile_func_count(result, args); + } else if (zend_string_equals_literal(lcname, "defined")) { //very many + return zend_compile_func_defined(result, args); + } else if (zend_string_equals_literal(lcname, "chr") && type == BP_VAR_R) { //9 + return zend_compile_func_chr(result, args); + } else if (zend_string_equals_literal(lcname, "func_get_args")) { //8 + return zend_compile_func_get_args(result, args); + } else if (zend_string_equals_literal(lcname, "is_int") //7 + || zend_string_equals_literal(lcname, "is_integer") //1 + || zend_string_equals_literal(lcname, "is_long") //0.09 ) { return zend_compile_func_typecheck(result, args, IS_LONG); - } else if (zend_string_equals_literal(lcname, "is_float") - || zend_string_equals_literal(lcname, "is_double") - || zend_string_equals_literal(lcname, "is_real") + } else if (zend_string_equals_literal(lcname, "array_slice")) { //6 + return zend_compile_func_array_slice(result, args); + } else if (zend_string_equals_literal(lcname, "ord") && type == BP_VAR_R) { //6 + return zend_compile_func_ord(result, args); + } else if (zend_string_equals_literal(lcname, "is_resource")) { //6 + return zend_compile_func_typecheck(result, args, IS_RESOURCE); + } else if (zend_string_equals_literal(lcname, "is_bool")) { //5 + return zend_compile_func_typecheck(result, args, _IS_BOOL); + } else if (zend_string_equals_literal(lcname, "func_num_args")) { //3 + return zend_compile_func_num_args(result, args); + } else if (zend_string_equals_literal(lcname, "is_float") //2 + || zend_string_equals_literal(lcname, "is_double") //0.3 + || zend_string_equals_literal(lcname, "is_real") //0.05 ) { return zend_compile_func_typecheck(result, args, IS_DOUBLE); - } else if (zend_string_equals_literal(lcname, "is_string")) { - return zend_compile_func_typecheck(result, args, IS_STRING); - } else if (zend_string_equals_literal(lcname, "is_array")) { - return zend_compile_func_typecheck(result, args, IS_ARRAY); - } else if (zend_string_equals_literal(lcname, "is_object")) { - return zend_compile_func_typecheck(result, args, IS_OBJECT); - } else if (zend_string_equals_literal(lcname, "is_resource")) { - return zend_compile_func_typecheck(result, args, IS_RESOURCE); - } else if (zend_string_equals_literal(lcname, "boolval")) { - return zend_compile_func_cast(result, args, _IS_BOOL); - } else if (zend_string_equals_literal(lcname, "intval")) { - return zend_compile_func_cast(result, args, IS_LONG); - } else if (zend_string_equals_literal(lcname, "floatval") - || zend_string_equals_literal(lcname, "doubleval") + } else if (zend_string_equals_literal(lcname, "strval")) { //2 + return zend_compile_func_cast(result, args, IS_STRING); + } else if (zend_string_equals_literal(lcname, "floatval") //2 + || zend_string_equals_literal(lcname, "doubleval") //0.2 ) { return zend_compile_func_cast(result, args, IS_DOUBLE); - } else if (zend_string_equals_literal(lcname, "strval")) { - return zend_compile_func_cast(result, args, IS_STRING); - } else if (zend_string_equals_literal(lcname, "defined")) { - return zend_compile_func_defined(result, args); - } else if (zend_string_equals_literal(lcname, "chr") && type == BP_VAR_R) { - return zend_compile_func_chr(result, args); - } else if (zend_string_equals_literal(lcname, "ord") && type == BP_VAR_R) { - return zend_compile_func_ord(result, args); - } else if (zend_string_equals_literal(lcname, "call_user_func_array")) { - return zend_compile_func_cufa(result, args, lcname); - } else if (zend_string_equals_literal(lcname, "call_user_func")) { - return zend_compile_func_cuf(result, args, lcname); - } else if (zend_string_equals_literal(lcname, "in_array")) { - return zend_compile_func_in_array(result, args); - } else if (zend_string_equals_literal(lcname, "count")) { - return zend_compile_func_count(result, args); - } else if (zend_string_equals_literal(lcname, "get_class")) { + } else if (zend_string_equals_literal(lcname, "boolval")) { //0.05 + return zend_compile_func_cast(result, args, _IS_BOOL); + } else if (zend_string_equals_literal(lcname, "get_class")) { //mainly in tests return zend_compile_func_get_class(result, args); - } else if (zend_string_equals_literal(lcname, "get_called_class")) { + } else if (zend_string_equals_literal(lcname, "get_called_class")) { //mainly in tests return zend_compile_func_get_called_class(result, args); - } else if (zend_string_equals_literal(lcname, "gettype")) { + } else if (zend_string_equals_literal(lcname, "gettype")) { //mainly in tests return zend_compile_func_gettype(result, args); - } else if (zend_string_equals_literal(lcname, "func_num_args")) { - return zend_compile_func_num_args(result, args); - } else if (zend_string_equals_literal(lcname, "func_get_args")) { - return zend_compile_func_get_args(result, args); - } else if (zend_string_equals_literal(lcname, "array_slice")) { - return zend_compile_func_array_slice(result, args); - } else if (zend_string_equals_literal(lcname, "array_key_exists")) { - return zend_compile_func_array_key_exists(result, args); } else { return FAILURE; } @@ -3952,16 +3951,15 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{ if (ce) { zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1); fbc = zend_hash_find_ptr(&ce->function_table, lcname); - if (fbc && !(fbc->common.fn_flags & ZEND_ACC_PUBLIC)) { - if (ce != CG(active_class_entry) - && ((fbc->common.fn_flags & ZEND_ACC_PRIVATE) - || !(fbc->common.scope->ce_flags & ZEND_ACC_LINKED) - || (CG(active_class_entry) - && !(CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) - || !zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry)))) { + if (fbc + && !(fbc->common.fn_flags & ZEND_ACC_PUBLIC) + && (ce != CG(active_class_entry)) + && ((fbc->common.fn_flags & ZEND_ACC_PRIVATE) + || !(fbc->common.scope->ce_flags & ZEND_ACC_LINKED) + || (CG(active_class_entry) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) + || !zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry)))) { /* incompatibe function */ fbc = NULL; - } } } } @@ -5397,8 +5395,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ "with callable type can only be NULL"); } } - } else { - if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { + } else if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { if (ZEND_TYPE_IS_CLASS(arg_info->type)) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with a class type can only be NULL"); @@ -5430,21 +5427,16 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ } break; } - } } /* Allocate cache slot to speed-up run-time class resolution */ - if (opline->opcode == ZEND_RECV_INIT) { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - opline->extended_value = zend_alloc_cache_slot(); - } + if (opline->opcode == ZEND_RECV_INIT && ZEND_TYPE_IS_CLASS(arg_info->type)) { + opline->extended_value = zend_alloc_cache_slot(); + } else if (ZEND_TYPE_IS_CLASS(arg_info->type)) { + opline->op2.num = op_array->cache_size; + op_array->cache_size += sizeof(void*); } else { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - opline->op2.num = op_array->cache_size; - op_array->cache_size += sizeof(void*); - } else { - opline->op2.num = -1; - } + opline->op2.num = -1; } } else { if (opline->opcode != ZEND_RECV_INIT) { @@ -5584,50 +5576,34 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo if (in_interface) { if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { /* pass */ - } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - if (!is_public || is_static) { + } else if(!is_public || is_static){ + if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { zend_error(E_WARNING, "The magic method __call() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - if (!is_public || !is_static) { + "public visibility and cannot be static"); + } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { zend_error(E_WARNING, "The magic method __callStatic() must have " - "public visibility and be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - if (!is_public || is_static) { + "public visibility and be static"); + } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { zend_error(E_WARNING, "The magic method __get() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - if (!is_public || is_static) { + "public visibility and cannot be static"); + } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { zend_error(E_WARNING, "The magic method __set() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - if (!is_public || is_static) { + "public visibility and cannot be static"); + } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { zend_error(E_WARNING, "The magic method __unset() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - if (!is_public || is_static) { + "public visibility and cannot be static"); + } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { zend_error(E_WARNING, "The magic method __isset() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - if (!is_public || is_static) { + "public visibility and cannot be static"); + } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { zend_error(E_WARNING, "The magic method __toString() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - if (!is_public || is_static) { + "public visibility and cannot be static"); + } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { zend_error(E_WARNING, "The magic method __invoke() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - if (!is_public || is_static) { + "public visibility and cannot be static"); + } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { zend_error(E_WARNING, "The magic method __debugInfo() must have " - "public visibility and cannot be static"); + "public visibility and cannot be static"); } } } else { @@ -5920,15 +5896,13 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) / zend_const_expr_to_zval(&value_zv, value_ast); if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)) { - if (Z_TYPE(value_zv) == IS_NULL) { - if (!ZEND_TYPE_ALLOW_NULL(type)) { - const char *name = ZEND_TYPE_IS_CLASS(type) - ? ZSTR_VAL(ZEND_TYPE_NAME(type)) : zend_get_type_by_const(ZEND_TYPE_CODE(type)); - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s may not be null. " - "Use the nullable type ?%s to allow null default value", - name, name); - } + if (Z_TYPE(value_zv) == IS_NULL && !ZEND_TYPE_ALLOW_NULL(type)) { + const char *name = ZEND_TYPE_IS_CLASS(type) + ? ZSTR_VAL(ZEND_TYPE_NAME(type)) : zend_get_type_by_const(ZEND_TYPE_CODE(type)); + zend_error_noreturn(E_COMPILE_ERROR, + "Default value for property of type %s may not be null. " + "Use the nullable type ?%s to allow null default value", + name, name); } else if (ZEND_TYPE_IS_CLASS(type)) { zend_error_noreturn(E_COMPILE_ERROR, "Property of type %s may not have default value", ZSTR_VAL(ZEND_TYPE_NAME(type))); @@ -6327,13 +6301,11 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ return; } } - } else { - if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { + } else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { zend_string_release(lcname); zend_build_properties_info_table(ce); ce->ce_flags |= ZEND_ACC_LINKED; return; - } } } @@ -6504,10 +6476,8 @@ void zend_compile_use(zend_ast *ast) /* {{{ */ } zend_string_efree(ns_name); - } else { - if (zend_have_seen_symbol(lookup_name, type)) { + } else if (zend_have_seen_symbol(lookup_name, type)) { zend_check_already_in_use(type, old_name, new_name, lookup_name); - } } zend_string_addref(old_name); @@ -6923,12 +6893,10 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type"); break; } - } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) { + } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) { zval_ptr_dtor_nogc(value); zval_ptr_dtor(result); return 0; - } } } @@ -7056,12 +7024,11 @@ void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */ zend_compile_expr(&expr_node, expr_ast); - if (expr_node.op_type == IS_CONST) { - if (zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) { + if (expr_node.op_type == IS_CONST + && zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) { result->op_type = IS_CONST; zval_ptr_dtor(&expr_node.u.constant); return; - } } lefthand_node.op_type = IS_CONST; @@ -8483,11 +8450,10 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ int i; for (i = 0; i <= 1; i++) { zend_eval_const_expr(&ast->child[i]); - if (ast->child[i]->kind == ZEND_AST_ZVAL) { - if (zend_is_true(zend_ast_get_zval(ast->child[i])) == (ast->kind == ZEND_AST_OR)) { - ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR); - return; - } + if (ast->child[i]->kind == ZEND_AST_ZVAL + && zend_is_true(zend_ast_get_zval(ast->child[i])) == (ast->kind == ZEND_AST_OR)) { + ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR); + return; } } From be48d59a5557686ad21552df77811e7d366d04ec Mon Sep 17 00:00:00 2001 From: rjhdby Date: Thu, 31 Jan 2019 12:55:56 +0300 Subject: [PATCH 02/12] Remove wrong replacement --- Zend/zend_compile.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 74d5c144ec4e..6b77864daaea 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5430,8 +5430,10 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ } /* Allocate cache slot to speed-up run-time class resolution */ - if (opline->opcode == ZEND_RECV_INIT && ZEND_TYPE_IS_CLASS(arg_info->type)) { - opline->extended_value = zend_alloc_cache_slot(); + if (opline->opcode == ZEND_RECV_INIT) { + if (ZEND_TYPE_IS_CLASS(arg_info->type)) { + opline->extended_value = zend_alloc_cache_slot(); + } } else if (ZEND_TYPE_IS_CLASS(arg_info->type)) { opline->op2.num = op_array->cache_size; op_array->cache_size += sizeof(void*); From 87f1f3d65c4d8bc588df41a83e109a81f84da703 Mon Sep 17 00:00:00 2001 From: rjhdby Date: Thu, 14 Feb 2019 11:16:41 +0300 Subject: [PATCH 03/12] zend_get_compatible_func_or_null --- Zend/zend_compile.c | 340 ++++++++++++++++++++------------------------ 1 file changed, 158 insertions(+), 182 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c0f842b3973e..512b94fce618 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2343,7 +2343,8 @@ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t if (dim_ast == NULL) { if (type == BP_VAR_R || type == BP_VAR_IS) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading"); - } else if (type == BP_VAR_UNSET) { + } + if (type == BP_VAR_UNSET) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting"); } dim_node.op_type = IS_UNUSED; @@ -3665,70 +3666,69 @@ int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_l if (zend_args_contain_unpack(args)) { return FAILURE; } - /* Ordered according to usage frequency on github (millions results) - * search query "func_name language:PHP stars:>1000 extension:php" */ - if (zend_string_equals_literal(lcname, "is_array")) { //40 - return zend_compile_func_typecheck(result, args, IS_ARRAY); - } else if (zend_string_equals_literal(lcname, "in_array")) { //36 - return zend_compile_func_in_array(result, args); - } else if (zend_string_equals_literal(lcname, "strlen")) { //32 + + if (zend_string_equals_literal(lcname, "strlen")) { return zend_compile_func_strlen(result, args); - } else if (zend_string_equals_literal(lcname, "is_string")) { //24 - return zend_compile_func_typecheck(result, args, IS_STRING); - } else if (zend_string_equals_literal(lcname, "is_object")) { //17 - return zend_compile_func_typecheck(result, args, IS_OBJECT); - } else if (zend_string_equals_literal(lcname, "array_key_exists")) { //16 - return zend_compile_func_array_key_exists(result, args); - } else if (zend_string_equals_literal(lcname, "is_null")) { //15 + } else if (zend_string_equals_literal(lcname, "is_null")) { return zend_compile_func_typecheck(result, args, IS_NULL); - } else if (zend_string_equals_literal(lcname, "intval")) { //14 - return zend_compile_func_cast(result, args, IS_LONG); - } else if (zend_string_equals_literal(lcname, "call_user_func")) { //11 - return zend_compile_func_cuf(result, args, lcname); - } else if (zend_string_equals_literal(lcname, "call_user_func_array")) { //9 - return zend_compile_func_cufa(result, args, lcname); - } else if (zend_string_equals_literal(lcname, "count")) { //very many - return zend_compile_func_count(result, args); - } else if (zend_string_equals_literal(lcname, "defined")) { //very many - return zend_compile_func_defined(result, args); - } else if (zend_string_equals_literal(lcname, "chr") && type == BP_VAR_R) { //9 - return zend_compile_func_chr(result, args); - } else if (zend_string_equals_literal(lcname, "func_get_args")) { //8 - return zend_compile_func_get_args(result, args); - } else if (zend_string_equals_literal(lcname, "is_int") //7 - || zend_string_equals_literal(lcname, "is_integer") //1 - || zend_string_equals_literal(lcname, "is_long") //0.09 + } else if (zend_string_equals_literal(lcname, "is_bool")) { + return zend_compile_func_typecheck(result, args, _IS_BOOL); + } else if (zend_string_equals_literal(lcname, "is_long") + || zend_string_equals_literal(lcname, "is_int") + || zend_string_equals_literal(lcname, "is_integer") ) { return zend_compile_func_typecheck(result, args, IS_LONG); - } else if (zend_string_equals_literal(lcname, "array_slice")) { //6 - return zend_compile_func_array_slice(result, args); - } else if (zend_string_equals_literal(lcname, "ord") && type == BP_VAR_R) { //6 - return zend_compile_func_ord(result, args); - } else if (zend_string_equals_literal(lcname, "is_resource")) { //6 - return zend_compile_func_typecheck(result, args, IS_RESOURCE); - } else if (zend_string_equals_literal(lcname, "is_bool")) { //5 - return zend_compile_func_typecheck(result, args, _IS_BOOL); - } else if (zend_string_equals_literal(lcname, "func_num_args")) { //3 - return zend_compile_func_num_args(result, args); - } else if (zend_string_equals_literal(lcname, "is_float") //2 - || zend_string_equals_literal(lcname, "is_double") //0.3 - || zend_string_equals_literal(lcname, "is_real") //0.05 + } else if (zend_string_equals_literal(lcname, "is_float") + || zend_string_equals_literal(lcname, "is_double") + || zend_string_equals_literal(lcname, "is_real") ) { return zend_compile_func_typecheck(result, args, IS_DOUBLE); - } else if (zend_string_equals_literal(lcname, "strval")) { //2 - return zend_compile_func_cast(result, args, IS_STRING); - } else if (zend_string_equals_literal(lcname, "floatval") //2 - || zend_string_equals_literal(lcname, "doubleval") //0.2 + } else if (zend_string_equals_literal(lcname, "is_string")) { + return zend_compile_func_typecheck(result, args, IS_STRING); + } else if (zend_string_equals_literal(lcname, "is_array")) { + return zend_compile_func_typecheck(result, args, IS_ARRAY); + } else if (zend_string_equals_literal(lcname, "is_object")) { + return zend_compile_func_typecheck(result, args, IS_OBJECT); + } else if (zend_string_equals_literal(lcname, "is_resource")) { + return zend_compile_func_typecheck(result, args, IS_RESOURCE); + } else if (zend_string_equals_literal(lcname, "boolval")) { + return zend_compile_func_cast(result, args, _IS_BOOL); + } else if (zend_string_equals_literal(lcname, "intval")) { + return zend_compile_func_cast(result, args, IS_LONG); + } else if (zend_string_equals_literal(lcname, "floatval") + || zend_string_equals_literal(lcname, "doubleval") ) { return zend_compile_func_cast(result, args, IS_DOUBLE); - } else if (zend_string_equals_literal(lcname, "boolval")) { //0.05 - return zend_compile_func_cast(result, args, _IS_BOOL); - } else if (zend_string_equals_literal(lcname, "get_class")) { //mainly in tests + } else if (zend_string_equals_literal(lcname, "strval")) { + return zend_compile_func_cast(result, args, IS_STRING); + } else if (zend_string_equals_literal(lcname, "defined")) { + return zend_compile_func_defined(result, args); + } else if (zend_string_equals_literal(lcname, "chr") && type == BP_VAR_R) { + return zend_compile_func_chr(result, args); + } else if (zend_string_equals_literal(lcname, "ord") && type == BP_VAR_R) { + return zend_compile_func_ord(result, args); + } else if (zend_string_equals_literal(lcname, "call_user_func_array")) { + return zend_compile_func_cufa(result, args, lcname); + } else if (zend_string_equals_literal(lcname, "call_user_func")) { + return zend_compile_func_cuf(result, args, lcname); + } else if (zend_string_equals_literal(lcname, "in_array")) { + return zend_compile_func_in_array(result, args); + } else if (zend_string_equals_literal(lcname, "count")) { + return zend_compile_func_count(result, args); + } else if (zend_string_equals_literal(lcname, "get_class")) { return zend_compile_func_get_class(result, args); - } else if (zend_string_equals_literal(lcname, "get_called_class")) { //mainly in tests + } else if (zend_string_equals_literal(lcname, "get_called_class")) { return zend_compile_func_get_called_class(result, args); - } else if (zend_string_equals_literal(lcname, "gettype")) { //mainly in tests + } else if (zend_string_equals_literal(lcname, "gettype")) { return zend_compile_func_gettype(result, args); + } else if (zend_string_equals_literal(lcname, "func_num_args")) { + return zend_compile_func_num_args(result, args); + } else if (zend_string_equals_literal(lcname, "func_get_args")) { + return zend_compile_func_get_args(result, args); + } else if (zend_string_equals_literal(lcname, "array_slice")) { + return zend_compile_func_array_slice(result, args); + } else if (zend_string_equals_literal(lcname, "array_key_exists")) { + return zend_compile_func_array_key_exists(result, args); } else { return FAILURE; } @@ -3863,6 +3863,24 @@ static zend_bool zend_is_constructor(zend_string *name) /* {{{ */ } /* }}} */ +zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_string *lcname) /* {{{ */ +{ + zend_function *fbc = zend_hash_find_ptr(&ce->function_table, lcname); + if(!fbc || fbc->common.fn_flags & ZEND_ACC_PUBLIC || ce == CG(active_class_entry)){ + return fbc; + } + + if (!(fbc->common.fn_flags & ZEND_ACC_PRIVATE) + && (fbc->common.scope->ce_flags & ZEND_ACC_LINKED) + && !(CG(active_class_entry) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) + && zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry))) { + return fbc; + } + + return NULL; +} +/* }}} */ + void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { zend_ast *class_ast = ast->child[0]; @@ -3921,17 +3939,7 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{ } if (ce) { zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1); - fbc = zend_hash_find_ptr(&ce->function_table, lcname); - if (fbc - && !(fbc->common.fn_flags & ZEND_ACC_PUBLIC) - && (ce != CG(active_class_entry)) - && ((fbc->common.fn_flags & ZEND_ACC_PRIVATE) - || !(fbc->common.scope->ce_flags & ZEND_ACC_LINKED) - || (CG(active_class_entry) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) - || !zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry)))) { - /* incompatibe function */ - fbc = NULL; - } + fbc = zend_get_compatible_func_or_null(ce, lcname); } } @@ -5367,37 +5375,37 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ } } } else if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a class type can only be NULL"); - } else switch (ZEND_TYPE_CODE(arg_info->type)) { - case IS_DOUBLE: - if (Z_TYPE(default_node.u.constant) != IS_DOUBLE && Z_TYPE(default_node.u.constant) != IS_LONG) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a float type can only be float, integer, or NULL"); - } - break; - - case IS_ITERABLE: - if (Z_TYPE(default_node.u.constant) != IS_ARRAY) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with iterable type can only be an array or NULL"); - } - break; + if (ZEND_TYPE_IS_CLASS(arg_info->type)) { + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with a class type can only be NULL"); + } else switch (ZEND_TYPE_CODE(arg_info->type)) { + case IS_DOUBLE: + if (Z_TYPE(default_node.u.constant) != IS_DOUBLE && Z_TYPE(default_node.u.constant) != IS_LONG) { + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with a float type can only be float, integer, or NULL"); + } + break; - case IS_OBJECT: + case IS_ITERABLE: + if (Z_TYPE(default_node.u.constant) != IS_ARRAY) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with an object type can only be NULL"); - break; + "with iterable type can only be an array or NULL"); + } + break; - default: - if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(arg_info->type), Z_TYPE(default_node.u.constant))) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a %s type can only be %s or NULL", - zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)), zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type))); - } - break; - } + case IS_OBJECT: + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with an object type can only be NULL"); + break; + + default: + if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(arg_info->type), Z_TYPE(default_node.u.constant))) { + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with a %s type can only be %s or NULL", + zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)), zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type))); + } + break; + } } /* Allocate cache slot to speed-up run-time class resolution */ @@ -5500,6 +5508,16 @@ void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ } /* }}} */ +void zend_check_magic_modifiers(zend_bool condition, const char* func_name, zend_bool is_static){ /* {{{ */ + if(condition){ + zend_error(E_WARNING, + "The magic method %s() must have public visibility and %sbe static", + func_name, + is_static ? "" : "cannot "); + } +} +/* }}} */ + void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_bool has_body) /* {{{ */ { zend_class_entry *ce = CG(active_class_entry); @@ -5545,40 +5563,7 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo ZSTR_VAL(ce->name), ZSTR_VAL(name)); } - if (in_interface) { - if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { - /* pass */ - } else if(!is_public || is_static){ - if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - zend_error(E_WARNING, "The magic method __call() must have " - "public visibility and cannot be static"); - } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - zend_error(E_WARNING, "The magic method __callStatic() must have " - "public visibility and be static"); - } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - zend_error(E_WARNING, "The magic method __get() must have " - "public visibility and cannot be static"); - } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - zend_error(E_WARNING, "The magic method __set() must have " - "public visibility and cannot be static"); - } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - zend_error(E_WARNING, "The magic method __unset() must have " - "public visibility and cannot be static"); - } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - zend_error(E_WARNING, "The magic method __isset() must have " - "public visibility and cannot be static"); - } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - zend_error(E_WARNING, "The magic method __toString() must have " - "public visibility and cannot be static"); - } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - zend_error(E_WARNING, "The magic method __invoke() must have " - "public visibility and cannot be static"); - } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - zend_error(E_WARNING, "The magic method __debugInfo() must have " - "public visibility and cannot be static"); - } - } - } else if (ZSTR_VAL(lcname)[0] == '_' && ZSTR_VAL(lcname)[1] == '_') { + if (ZSTR_VAL(lcname)[0] == '_' && ZSTR_VAL(lcname)[1] == '_') { if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { ce->constructor = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) { @@ -5586,62 +5571,51 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { ce->clone = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __call() must have " - "public visibility and cannot be static"); + zend_check_magic_modifiers(!is_public || is_static, "__call", 0); + if (!in_interface){ + ce->__call = (zend_function *) op_array; } - ce->__call = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - if (!is_public || !is_static) { - zend_error(E_WARNING, "The magic method __callStatic() must have " - "public visibility and be static"); + zend_check_magic_modifiers(!is_public || !is_static, "__callStatic", 1); + if (!in_interface){ + ce->__callstatic = (zend_function *) op_array; } - ce->__callstatic = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __get() must have " - "public visibility and cannot be static"); + zend_check_magic_modifiers(!is_public || is_static, "__get", 0); + if (!in_interface){ + ce->__get = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; } - ce->__get = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __set() must have " - "public visibility and cannot be static"); + zend_check_magic_modifiers(!is_public || is_static, "__set", 0); + if (!in_interface){ + ce->__set = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; } - ce->__set = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __unset() must have " - "public visibility and cannot be static"); + zend_check_magic_modifiers(!is_public || is_static, "__unset", 0); + if (!in_interface){ + ce->__unset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; } - ce->__unset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __isset() must have " - "public visibility and cannot be static"); + zend_check_magic_modifiers(!is_public || is_static, "__isset", 0); + if (!in_interface){ + ce->__isset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; } - ce->__isset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __toString() must have " - "public visibility and cannot be static"); + zend_check_magic_modifiers(!is_public || is_static, "__toString", 0); + if (!in_interface){ + ce->__tostring = (zend_function *) op_array; } - ce->__tostring = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __invoke() must have " - "public visibility and cannot be static"); - } + zend_check_magic_modifiers(!is_public || is_static, "__invoke", 0); } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __debugInfo() must have " - "public visibility and cannot be static"); + zend_check_magic_modifiers(!is_public || is_static, "__debugInfo", 0); + if (!in_interface){ + ce->__debugInfo = (zend_function *) op_array; } - ce->__debugInfo = (zend_function *) op_array; } } @@ -5862,13 +5836,15 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) / zend_const_expr_to_zval(&value_zv, value_ast); if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)) { - if (Z_TYPE(value_zv) == IS_NULL && !ZEND_TYPE_ALLOW_NULL(type)) { - const char *name = ZEND_TYPE_IS_CLASS(type) - ? ZSTR_VAL(ZEND_TYPE_NAME(type)) : zend_get_type_by_const(ZEND_TYPE_CODE(type)); - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s may not be null. " - "Use the nullable type ?%s to allow null default value", - name, name); + if (Z_TYPE(value_zv) == IS_NULL) { + if (!ZEND_TYPE_ALLOW_NULL(type)) { + const char *name = ZEND_TYPE_IS_CLASS(type) + ? ZSTR_VAL(ZEND_TYPE_NAME(type)) : zend_get_type_by_const(ZEND_TYPE_CODE(type)); + zend_error_noreturn(E_COMPILE_ERROR, + "Default value for property of type %s may not be null. " + "Use the nullable type ?%s to allow null default value", + name, name); + } } else if (ZEND_TYPE_IS_CLASS(type)) { zend_error_noreturn(E_COMPILE_ERROR, "Property of type %s may not have default value", ZSTR_VAL(ZEND_TYPE_NAME(type))); @@ -6263,10 +6239,10 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ } } } else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { - zend_string_release(lcname); - zend_build_properties_info_table(ce); - ce->ce_flags |= ZEND_ACC_LINKED; - return; + zend_string_release(lcname); + zend_build_properties_info_table(ce); + ce->ce_flags |= ZEND_ACC_LINKED; + return; } } @@ -6438,7 +6414,7 @@ void zend_compile_use(zend_ast *ast) /* {{{ */ zend_string_efree(ns_name); } else if (zend_have_seen_symbol(lookup_name, type)) { - zend_check_already_in_use(type, old_name, new_name, lookup_name); + zend_check_already_in_use(type, old_name, new_name, lookup_name); } zend_string_addref(old_name); @@ -6858,9 +6834,9 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ break; } } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) { - zval_ptr_dtor_nogc(value); - zval_ptr_dtor(result); - return 0; + zval_ptr_dtor_nogc(value); + zval_ptr_dtor(result); + return 0; } } From 676060f0921354a053313aff2184705317ea8cf9 Mon Sep 17 00:00:00 2001 From: rjhdby Date: Fri, 15 Feb 2019 13:12:57 +0300 Subject: [PATCH 04/12] zend_check_modifiers --- Zend/zend_compile.c | 109 +++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 57 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 512b94fce618..ab562ac7cb09 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3337,9 +3337,9 @@ int zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcna zend_bool is_fully_qualified; zend_string *name = zend_resolve_function_name(orig_name, args->child[1]->child[0]->attr, &is_fully_qualified); - if (list->children == 3 - && list->child[1]->kind == ZEND_AST_ZVAL - && zend_string_equals_literal_ci(name, "array_slice")) { + if (zend_string_equals_literal_ci(name, "array_slice") + && list->children == 3 + && list->child[1]->kind == ZEND_AST_ZVAL) { zval *zv = zend_ast_get_zval(list->child[1]); if (Z_TYPE_P(zv) == IS_LONG @@ -3637,10 +3637,10 @@ int zend_compile_func_array_slice(znode *result, zend_ast_list *args) /* {{{ */ zval *zv = zend_ast_get_zval(args->child[1]); znode first; - if (list->children == 0 + if (zend_string_equals_literal_ci(name, "func_get_args") + && list->children == 0 && Z_TYPE_P(zv) == IS_LONG - && Z_LVAL_P(zv) >= 0 - && zend_string_equals_literal_ci(name, "func_get_args")) { + && Z_LVAL_P(zv) >= 0) { first.op_type = IS_CONST; ZVAL_LONG(&first.u.constant, Z_LVAL_P(zv)); zend_emit_op_tmp(result, ZEND_FUNC_GET_ARGS, &first, NULL); @@ -3872,7 +3872,7 @@ zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_strin if (!(fbc->common.fn_flags & ZEND_ACC_PRIVATE) && (fbc->common.scope->ce_flags & ZEND_ACC_LINKED) - && !(CG(active_class_entry) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) + && (!CG(active_class_entry) || (CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) && zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry))) { return fbc; } @@ -5249,6 +5249,14 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null } } /* }}} */ +zend_bool zend_is_null_const(zval constant) /* {{{ */ +{ + return Z_TYPE(constant) == IS_NULL + || (Z_TYPE(constant) == IS_CONSTANT_AST + && Z_ASTVAL(constant)->kind == ZEND_AST_CONSTANT + && strcasecmp(ZSTR_VAL(zend_ast_get_constant_name(Z_ASTVAL(constant))), "NULL") == 0); +} +/* }}} */ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ { @@ -5346,11 +5354,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ arg_info->type = ZEND_TYPE_ENCODE(0, 1); if (type_ast) { - zend_bool has_null_default = default_ast - && (Z_TYPE(default_node.u.constant) == IS_NULL - || (Z_TYPE(default_node.u.constant) == IS_CONSTANT_AST - && Z_ASTVAL(default_node.u.constant)->kind == ZEND_AST_CONSTANT - && strcasecmp(ZSTR_VAL(zend_ast_get_constant_name(Z_ASTVAL(default_node.u.constant))), "NULL") == 0)); + zend_bool has_null_default = default_ast && zend_is_null_const(default_node.u.constant); op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; arg_info->type = zend_compile_typename(type_ast, has_null_default); @@ -5358,24 +5362,16 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ if (ZEND_TYPE_CODE(arg_info->type) == IS_VOID) { zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type"); } - - if (type_ast->kind == ZEND_AST_TYPE) { - if (ZEND_TYPE_CODE(arg_info->type) == IS_ARRAY) { - if (default_ast && !has_null_default - && Z_TYPE(default_node.u.constant) != IS_ARRAY - && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST - ) { + if(default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST){ + if (type_ast->kind == ZEND_AST_TYPE) { + if (ZEND_TYPE_CODE(arg_info->type) == IS_ARRAY && Z_TYPE(default_node.u.constant) != IS_ARRAY) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with array type can only be an array or NULL"); - } - } else if (ZEND_TYPE_CODE(arg_info->type) == IS_CALLABLE && default_ast) { - if (!has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { + } else if (ZEND_TYPE_CODE(arg_info->type) == IS_CALLABLE) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with callable type can only be NULL"); } - } - } else if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { + } else if (ZEND_TYPE_IS_CLASS(arg_info->type)) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with a class type can only be NULL"); } else switch (ZEND_TYPE_CODE(arg_info->type)) { @@ -5508,12 +5504,24 @@ void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ } /* }}} */ -void zend_check_magic_modifiers(zend_bool condition, const char* func_name, zend_bool is_static){ /* {{{ */ - if(condition){ - zend_error(E_WARNING, - "The magic method %s() must have public visibility and %sbe static", - func_name, - is_static ? "" : "cannot "); +void zend_check_modifiers(uint32_t mask, uint32_t modifiers, const char* entity){ /* {{{ */ + if (entity[0] == '_' && entity[1] == '_'){ + /* magic methods */ + if((mask & ZEND_ACC_PUBLIC) != (modifiers & ZEND_ACC_PUBLIC) + || (mask & ZEND_ACC_STATIC) != (modifiers & ZEND_ACC_STATIC)){ + zend_error(E_WARNING, + "The magic method %s() must have public visibility and %s", + entity, + mask & ZEND_ACC_STATIC ? "be static" : "cannot be static"); + } + } else if(strcmp(entity, "constant") || strcmp(entity, "method")){ + if ((mask & ZEND_ACC_STATIC) != (modifiers & ZEND_ACC_STATIC)){ + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as %s modifier", entity); + } else if ((mask & ZEND_ACC_ABSTRACT) != (modifiers & ZEND_ACC_ABSTRACT)){ + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as %s modifier", entity); + } else if ((mask & ZEND_ACC_FINAL) != (modifiers & ZEND_ACC_FINAL)){ + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as %s modifier", entity); + } } } /* }}} */ @@ -5522,13 +5530,12 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo { zend_class_entry *ce = CG(active_class_entry); zend_bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0; - zend_bool is_public = (op_array->fn_flags & ZEND_ACC_PUBLIC) != 0; - zend_bool is_static = (op_array->fn_flags & ZEND_ACC_STATIC) != 0; + uint32_t fn_flags = op_array->fn_flags; zend_string *lcname; if (in_interface) { - if (!is_public || (op_array->fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { + if (!(fn_flags & ZEND_ACC_PUBLIC) || (op_array->fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method " "%s::%s() must be omitted", ZSTR_VAL(ce->name), ZSTR_VAL(name)); } @@ -5571,48 +5578,48 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { ce->clone = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - zend_check_magic_modifiers(!is_public || is_static, "__call", 0); + zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__call"); if (!in_interface){ ce->__call = (zend_function *) op_array; } } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - zend_check_magic_modifiers(!is_public || !is_static, "__callStatic", 1); + zend_check_modifiers(ZEND_ACC_PUBLIC | ZEND_ACC_STATIC, fn_flags, "__callStatic"); if (!in_interface){ ce->__callstatic = (zend_function *) op_array; } } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - zend_check_magic_modifiers(!is_public || is_static, "__get", 0); + zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__get"); if (!in_interface){ ce->__get = (zend_function *) op_array; ce->ce_flags |= ZEND_ACC_USE_GUARDS; } } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - zend_check_magic_modifiers(!is_public || is_static, "__set", 0); + zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__set"); if (!in_interface){ ce->__set = (zend_function *) op_array; ce->ce_flags |= ZEND_ACC_USE_GUARDS; } } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - zend_check_magic_modifiers(!is_public || is_static, "__unset", 0); + zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__unset"); if (!in_interface){ ce->__unset = (zend_function *) op_array; ce->ce_flags |= ZEND_ACC_USE_GUARDS; } } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - zend_check_magic_modifiers(!is_public || is_static, "__isset", 0); + zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__isset"); if (!in_interface){ ce->__isset = (zend_function *) op_array; ce->ce_flags |= ZEND_ACC_USE_GUARDS; } } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - zend_check_magic_modifiers(!is_public || is_static, "__toString", 0); + zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__toString"); if (!in_interface){ ce->__tostring = (zend_function *) op_array; } } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - zend_check_magic_modifiers(!is_public || is_static, "__invoke", 0); + zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__invoke"); } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - zend_check_magic_modifiers(!is_public || is_static, "__debugInfo", 0); + zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__debugInfo"); if (!in_interface){ ce->__debugInfo = (zend_function *) op_array; } @@ -5907,13 +5914,7 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zval value_zv; if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { - if (ast->attr & ZEND_ACC_STATIC) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as constant modifier"); - } else if (ast->attr & ZEND_ACC_ABSTRACT) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as constant modifier"); - } else if (ast->attr & ZEND_ACC_FINAL) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as constant modifier"); - } + zend_check_modifiers(!(ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL), ast->attr, "constant"); } zend_const_expr_to_zval(&value_zv, value_ast); @@ -5965,13 +5966,7 @@ static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */ zend_trait_alias *alias; - if (modifiers == ZEND_ACC_STATIC) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier"); - } else if (modifiers == ZEND_ACC_ABSTRACT) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier"); - } else if (modifiers == ZEND_ACC_FINAL) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier"); - } + zend_check_modifiers(!(ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL), modifiers, "method"); alias = emalloc(sizeof(zend_trait_alias)); zend_compile_method_ref(method_ref_ast, &alias->trait_method); From a5b5ff31ef66ccd1467554d858d71af9721da2e7 Mon Sep 17 00:00:00 2001 From: rjhdby Date: Fri, 15 Feb 2019 14:49:21 +0300 Subject: [PATCH 05/12] rename zend_check_modifiers --- Zend/zend_compile.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ab562ac7cb09..4b0a031c7282 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5504,22 +5504,22 @@ void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ } /* }}} */ -void zend_check_modifiers(uint32_t mask, uint32_t modifiers, const char* entity){ /* {{{ */ +void zend_check_attr(uint32_t mask, uint32_t attr, const char* entity){ /* {{{ */ if (entity[0] == '_' && entity[1] == '_'){ /* magic methods */ - if((mask & ZEND_ACC_PUBLIC) != (modifiers & ZEND_ACC_PUBLIC) - || (mask & ZEND_ACC_STATIC) != (modifiers & ZEND_ACC_STATIC)){ + if((mask & ZEND_ACC_PUBLIC) != (attr & ZEND_ACC_PUBLIC) + || (mask & ZEND_ACC_STATIC) != (attr & ZEND_ACC_STATIC)){ zend_error(E_WARNING, "The magic method %s() must have public visibility and %s", entity, mask & ZEND_ACC_STATIC ? "be static" : "cannot be static"); } } else if(strcmp(entity, "constant") || strcmp(entity, "method")){ - if ((mask & ZEND_ACC_STATIC) != (modifiers & ZEND_ACC_STATIC)){ + if (attr & ZEND_ACC_STATIC){ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as %s modifier", entity); - } else if ((mask & ZEND_ACC_ABSTRACT) != (modifiers & ZEND_ACC_ABSTRACT)){ + } else if (attr & ZEND_ACC_ABSTRACT){ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as %s modifier", entity); - } else if ((mask & ZEND_ACC_FINAL) != (modifiers & ZEND_ACC_FINAL)){ + } else if (attr & ZEND_ACC_FINAL){ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as %s modifier", entity); } } @@ -5578,48 +5578,48 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { ce->clone = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__call"); + zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__call"); if (!in_interface){ ce->__call = (zend_function *) op_array; } } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - zend_check_modifiers(ZEND_ACC_PUBLIC | ZEND_ACC_STATIC, fn_flags, "__callStatic"); + zend_check_attr(ZEND_ACC_PUBLIC | ZEND_ACC_STATIC, fn_flags, "__callStatic"); if (!in_interface){ ce->__callstatic = (zend_function *) op_array; } } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__get"); + zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__get"); if (!in_interface){ ce->__get = (zend_function *) op_array; ce->ce_flags |= ZEND_ACC_USE_GUARDS; } } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__set"); + zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__set"); if (!in_interface){ ce->__set = (zend_function *) op_array; ce->ce_flags |= ZEND_ACC_USE_GUARDS; } } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__unset"); + zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__unset"); if (!in_interface){ ce->__unset = (zend_function *) op_array; ce->ce_flags |= ZEND_ACC_USE_GUARDS; } } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__isset"); + zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__isset"); if (!in_interface){ ce->__isset = (zend_function *) op_array; ce->ce_flags |= ZEND_ACC_USE_GUARDS; } } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__toString"); + zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__toString"); if (!in_interface){ ce->__tostring = (zend_function *) op_array; } } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__invoke"); + zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__invoke"); } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - zend_check_modifiers(ZEND_ACC_PUBLIC, fn_flags, "__debugInfo"); + zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__debugInfo"); if (!in_interface){ ce->__debugInfo = (zend_function *) op_array; } @@ -5914,7 +5914,7 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zval value_zv; if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { - zend_check_modifiers(!(ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL), ast->attr, "constant"); + zend_check_attr(!(ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL), ast->attr, "constant"); } zend_const_expr_to_zval(&value_zv, value_ast); @@ -5966,7 +5966,7 @@ static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */ zend_trait_alias *alias; - zend_check_modifiers(!(ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL), modifiers, "method"); + zend_check_attr(!(ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL), modifiers, "method"); alias = emalloc(sizeof(zend_trait_alias)); zend_compile_method_ref(method_ref_ast, &alias->trait_method); From 2554ec4a8e4db989432b594f572999ab154a3107 Mon Sep 17 00:00:00 2001 From: rjhdby Date: Mon, 18 Feb 2019 10:50:16 +0300 Subject: [PATCH 06/12] final --- Zend/zend_compile.c | 193 ++++++++++++++++---------------------------- 1 file changed, 70 insertions(+), 123 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 9829d6c07a8f..2caaf8b649fc 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5504,17 +5504,17 @@ void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ } /* }}} */ -void zend_check_attr(uint32_t mask, uint32_t attr, const char* entity){ /* {{{ */ - if (entity[0] == '_' && entity[1] == '_'){ - /* magic methods */ - if((mask & ZEND_ACC_PUBLIC) != (attr & ZEND_ACC_PUBLIC) - || (mask & ZEND_ACC_STATIC) != (attr & ZEND_ACC_STATIC)){ - zend_error(E_WARNING, - "The magic method %s() must have public visibility and %s", - entity, - mask & ZEND_ACC_STATIC ? "be static" : "cannot be static"); - } - } else if(strcmp(entity, "constant") || strcmp(entity, "method")){ +void zend_check_attr(uint32_t attr, const char* entity){ /* {{{ */ + if (memcmp(entity, "__callStatic", 12) == 0){ + if(!(attr & ZEND_ACC_PUBLIC) || !(attr & ZEND_ACC_STATIC)){ + zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static"); + } + } else if (entity[0] == '_' && entity[1] == '_' + && (!(attr & ZEND_ACC_PUBLIC) || (attr & ZEND_ACC_STATIC))){ + zend_error(E_WARNING, + "The magic method %s() must have public visibility and cannot be static", + entity); + } else if(memcmp(entity, "constant", 8) == 0|| memcmp(entity, "method", 6) == 0){ if (attr & ZEND_ACC_STATIC){ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as %s modifier", entity); } else if (attr & ZEND_ACC_ABSTRACT){ @@ -5570,116 +5570,63 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo ZSTR_VAL(ce->name), ZSTR_VAL(name)); } - if (ZSTR_VAL(lcname)[0] == '_' && ZSTR_VAL(lcname)[1] == '_') { - if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { - if (in_interface) { - if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { - /* pass */ - } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __call() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - if (!is_public || !is_static) { - zend_error(E_WARNING, "The magic method __callStatic() must have " - "public visibility and be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __get() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __set() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __unset() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __isset() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __toString() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __invoke() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __debugInfo() must have " - "public visibility and cannot be static"); - } - } - } else { - if (zend_string_equals_literal(lcname, "serialize")) { - ce->serialize_func = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, "unserialize")) { - ce->unserialize_func = (zend_function *) op_array; - } else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { - /* pass */ - } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { - ce->constructor = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) { - ce->destructor = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { - ce->clone = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__call"); - if (!in_interface){ - ce->__call = (zend_function *) op_array; - } - } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - zend_check_attr(ZEND_ACC_PUBLIC | ZEND_ACC_STATIC, fn_flags, "__callStatic"); - if (!in_interface){ - ce->__callstatic = (zend_function *) op_array; - } - } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__get"); - if (!in_interface){ - ce->__get = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } - } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__set"); - if (!in_interface){ - ce->__set = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } - } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__unset"); - if (!in_interface){ - ce->__unset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } - } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__isset"); - if (!in_interface){ - ce->__isset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } - } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__toString"); - if (!in_interface){ - ce->__tostring = (zend_function *) op_array; - } - } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__invoke"); - } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - zend_check_attr(ZEND_ACC_PUBLIC, fn_flags, "__debugInfo"); - if (!in_interface){ - ce->__debugInfo = (zend_function *) op_array; - } + if (zend_string_equals_literal(lcname, "serialize")) { + ce->serialize_func = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, "unserialize")) { + ce->unserialize_func = (zend_function *) op_array; + } else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { + /* pass */ + } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { + ce->constructor = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) { + ce->destructor = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { + ce->clone = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { + zend_check_attr(fn_flags, "__call"); + if (!in_interface){ + ce->__call = (zend_function *) op_array; + } + } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { + zend_check_attr(fn_flags, "__callStatic"); + if (!in_interface){ + ce->__callstatic = (zend_function *) op_array; + } + } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { + zend_check_attr(fn_flags, "__get"); + if (!in_interface){ + ce->__get = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } + } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { + zend_check_attr(fn_flags, "__set"); + if (!in_interface){ + ce->__set = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } + } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { + zend_check_attr(fn_flags, "__unset"); + if (!in_interface){ + ce->__unset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } + } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { + zend_check_attr(fn_flags, "__isset"); + if (!in_interface){ + ce->__isset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } + } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { + zend_check_attr(fn_flags, "__toString"); + if (!in_interface){ + ce->__tostring = (zend_function *) op_array; + } + } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { + zend_check_attr(fn_flags, "__invoke"); + } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { + zend_check_attr(fn_flags, "__debugInfo"); + if (!in_interface){ + ce->__debugInfo = (zend_function *) op_array; } } @@ -5971,7 +5918,7 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zval value_zv; if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { - zend_check_attr(!(ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL), ast->attr, "constant"); + zend_check_attr(ast->attr, "constant"); } zend_const_expr_to_zval(&value_zv, value_ast); @@ -6023,7 +5970,7 @@ static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */ zend_trait_alias *alias; - zend_check_attr(!(ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL), modifiers, "method"); + zend_check_attr(modifiers, "method"); alias = emalloc(sizeof(zend_trait_alias)); zend_compile_method_ref(method_ref_ast, &alias->trait_method); From 6c8b80761c405f782229e916647f18358470023a Mon Sep 17 00:00:00 2001 From: rjhdby Date: Tue, 19 Feb 2019 17:37:20 +0300 Subject: [PATCH 07/12] work on remarks --- Zend/zend_compile.c | 117 ++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 69 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 35dc84b5b4b8..8eaee248e353 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3863,10 +3863,10 @@ static zend_bool zend_is_constructor(zend_string *name) /* {{{ */ } /* }}} */ -zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_string *lcname) /* {{{ */ +static zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_string *lcname) /* {{{ */ { zend_function *fbc = zend_hash_find_ptr(&ce->function_table, lcname); - if(!fbc || fbc->common.fn_flags & ZEND_ACC_PUBLIC || ce == CG(active_class_entry)){ + if (!fbc || (fbc->common.fn_flags & ZEND_ACC_PUBLIC) || ce == CG(active_class_entry)) { return fbc; } @@ -5248,15 +5248,6 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null } } } -/* }}} */ -zend_bool zend_is_null_const(zval constant) /* {{{ */ -{ - return Z_TYPE(constant) == IS_NULL - || (Z_TYPE(constant) == IS_CONSTANT_AST - && Z_ASTVAL(constant)->kind == ZEND_AST_CONSTANT - && strcasecmp(ZSTR_VAL(zend_ast_get_constant_name(Z_ASTVAL(constant))), "NULL") == 0); -} -/* }}} */ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ { @@ -5354,7 +5345,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ arg_info->type = ZEND_TYPE_ENCODE(0, 1); if (type_ast) { - zend_bool has_null_default = default_ast && zend_is_null_const(default_node.u.constant); + zend_bool has_null_default = default_ast && Z_TYPE(default_node.u.constant) == IS_NULL; op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; arg_info->type = zend_compile_typename(type_ast, has_null_default); @@ -5362,7 +5353,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ if (ZEND_TYPE_CODE(arg_info->type) == IS_VOID) { zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type"); } - if(default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST){ + if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { if (type_ast->kind == ZEND_AST_TYPE) { if (ZEND_TYPE_CODE(arg_info->type) == IS_ARRAY && Z_TYPE(default_node.u.constant) != IS_ARRAY) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " @@ -5504,24 +5495,16 @@ void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ } /* }}} */ -void zend_check_attr(uint32_t attr, const char* entity){ /* {{{ */ - if (memcmp(entity, "__callStatic", 12) == 0){ - if(!(attr & ZEND_ACC_PUBLIC) || !(attr & ZEND_ACC_STATIC)){ +static void zend_check_magic_method_attr(uint32_t attr, const char* entity) /* {{{ */ +{ + if (memcmp(entity, "__callStatic", 12) == 0) { + if (!(attr & ZEND_ACC_PUBLIC) || !(attr & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static"); } - } else if (entity[0] == '_' && entity[1] == '_' - && (!(attr & ZEND_ACC_PUBLIC) || (attr & ZEND_ACC_STATIC))){ + } else if (!(attr & ZEND_ACC_PUBLIC) || (attr & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "The magic method %s() must have public visibility and cannot be static", entity); - } else if(memcmp(entity, "constant", 8) == 0|| memcmp(entity, "method", 6) == 0){ - if (attr & ZEND_ACC_STATIC){ - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as %s modifier", entity); - } else if (attr & ZEND_ACC_ABSTRACT){ - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as %s modifier", entity); - } else if (attr & ZEND_ACC_FINAL){ - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as %s modifier", entity); - } } } /* }}} */ @@ -5535,7 +5518,7 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo zend_string *lcname; if (in_interface) { - if (!(fn_flags & ZEND_ACC_PUBLIC) || (op_array->fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { + if (!(fn_flags & ZEND_ACC_PUBLIC) || (fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method " "%s::%s() must be omitted", ZSTR_VAL(ce->name), ZSTR_VAL(name)); } @@ -5583,51 +5566,35 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { ce->clone = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - zend_check_attr(fn_flags, "__call"); - if (!in_interface){ - ce->__call = (zend_function *) op_array; - } + zend_check_magic_method_attr(fn_flags, "__call"); + ce->__call = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - zend_check_attr(fn_flags, "__callStatic"); - if (!in_interface){ - ce->__callstatic = (zend_function *) op_array; - } + zend_check_magic_method_attr(fn_flags, "__callStatic"); + ce->__callstatic = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - zend_check_attr(fn_flags, "__get"); - if (!in_interface){ - ce->__get = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } + zend_check_magic_method_attr(fn_flags, "__get"); + ce->__get = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - zend_check_attr(fn_flags, "__set"); - if (!in_interface){ - ce->__set = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } + zend_check_magic_method_attr(fn_flags, "__set"); + ce->__set = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - zend_check_attr(fn_flags, "__unset"); - if (!in_interface){ - ce->__unset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } + zend_check_magic_method_attr(fn_flags, "__unset"); + ce->__unset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - zend_check_attr(fn_flags, "__isset"); - if (!in_interface){ - ce->__isset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } + zend_check_magic_method_attr(fn_flags, "__isset"); + ce->__isset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - zend_check_attr(fn_flags, "__toString"); - if (!in_interface){ - ce->__tostring = (zend_function *) op_array; - } + zend_check_magic_method_attr(fn_flags, "__toString"); + ce->__tostring = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - zend_check_attr(fn_flags, "__invoke"); + zend_check_magic_method_attr(fn_flags, "__invoke"); } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - zend_check_attr(fn_flags, "__debugInfo"); - if (!in_interface){ - ce->__debugInfo = (zend_function *) op_array; - } + zend_check_magic_method_attr(fn_flags, "__debugInfo"); + ce->__debugInfo = (zend_function *) op_array; } zend_string_release_ex(lcname, 0); @@ -5897,6 +5864,18 @@ void zend_compile_prop_group(zend_ast *list) /* {{{ */ } /* }}} */ +static void zend_check_const_and_trait_alias_attr(uint32_t attr, const char* entity) /* {{{ */ +{ + if (attr & ZEND_ACC_STATIC) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as %s modifier", entity); + } else if (attr & ZEND_ACC_ABSTRACT) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as %s modifier", entity); + } else if (attr & ZEND_ACC_FINAL) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as %s modifier", entity); + } +} +/* }}} */ + void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); @@ -5918,7 +5897,7 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zval value_zv; if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { - zend_check_attr(ast->attr, "constant"); + zend_check_const_and_trait_alias_attr(ast->attr, "constant"); } zend_const_expr_to_zval(&value_zv, value_ast); @@ -5970,7 +5949,7 @@ static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */ zend_trait_alias *alias; - zend_check_attr(modifiers, "method"); + zend_check_const_and_trait_alias_attr(modifiers, "method"); alias = emalloc(sizeof(zend_trait_alias)); zend_compile_method_ref(method_ref_ast, &alias->trait_method); @@ -6967,9 +6946,9 @@ void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */ if (expr_node.op_type == IS_CONST && zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) { - result->op_type = IS_CONST; - zval_ptr_dtor(&expr_node.u.constant); - return; + result->op_type = IS_CONST; + zval_ptr_dtor(&expr_node.u.constant); + return; } lefthand_node.op_type = IS_CONST; From d4f794777433e224bd9bd3852024605e037c4487 Mon Sep 17 00:00:00 2001 From: rjhdby Date: Wed, 20 Feb 2019 15:33:12 +0300 Subject: [PATCH 08/12] zend_compile_params --- Zend/zend_compile.c | 48 ++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 8eaee248e353..8ad7fd3ff69c 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5345,36 +5345,42 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ arg_info->type = ZEND_TYPE_ENCODE(0, 1); if (type_ast) { - zend_bool has_null_default = default_ast && Z_TYPE(default_node.u.constant) == IS_NULL; + uint32_t default_type, arg_type; - op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; - arg_info->type = zend_compile_typename(type_ast, has_null_default); + default_type = Z_TYPE(default_node.u.constant); - if (ZEND_TYPE_CODE(arg_info->type) == IS_VOID) { + op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; + arg_info->type = zend_compile_typename(type_ast, default_ast && default_type == IS_NULL); + + arg_type = ZEND_TYPE_CODE(arg_info->type); + + if (arg_type == IS_VOID) { zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type"); } - if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { - if (type_ast->kind == ZEND_AST_TYPE) { - if (ZEND_TYPE_CODE(arg_info->type) == IS_ARRAY && Z_TYPE(default_node.u.constant) != IS_ARRAY) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with array type can only be an array or NULL"); - } else if (ZEND_TYPE_CODE(arg_info->type) == IS_CALLABLE) { + + if (default_ast && default_type != IS_NULL && default_type != IS_CONSTANT_AST) { + switch (arg_type) { + case IS_CALLABLE: zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with callable type can only be NULL"); - } - } else if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a class type can only be NULL"); - } else switch (ZEND_TYPE_CODE(arg_info->type)) { + break; + + case IS_ARRAY: + if (default_type != IS_ARRAY) { + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with array type can only be an array or NULL"); + } + break; + case IS_DOUBLE: - if (Z_TYPE(default_node.u.constant) != IS_DOUBLE && Z_TYPE(default_node.u.constant) != IS_LONG) { + if (default_type != IS_DOUBLE && default_type != IS_LONG) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with a float type can only be float, integer, or NULL"); } break; case IS_ITERABLE: - if (Z_TYPE(default_node.u.constant) != IS_ARRAY) { + if (default_type != IS_ARRAY) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with iterable type can only be an array or NULL"); } @@ -5386,12 +5392,14 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ break; default: - if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(arg_info->type), Z_TYPE(default_node.u.constant))) { + if (ZEND_TYPE_IS_CLASS(arg_info->type)) { + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with a class type can only be NULL"); + } else if (!ZEND_SAME_FAKE_TYPE(arg_type, default_type)) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with a %s type can only be %s or NULL", - zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)), zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type))); + zend_get_type_by_const(arg_type), zend_get_type_by_const(arg_type)); } - break; } } From e4352155e5ac587e60f23904b5bdbd63c73c90fd Mon Sep 17 00:00:00 2001 From: rjhdby Date: Fri, 22 Feb 2019 14:31:17 +0300 Subject: [PATCH 09/12] merge from master --- Zend/zend_compile.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 4231d614e886..f428b0bb8328 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5248,6 +5248,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null } } } +/* }}} */ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ { From b873e1dfea6a7be939cab1a43c1ff3346d8ff551 Mon Sep 17 00:00:00 2001 From: rjhdby Date: Sat, 2 Mar 2019 10:13:56 +0300 Subject: [PATCH 10/12] recommended corrections --- Zend/zend_compile.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f428b0bb8328..55066c83eaa3 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2945,7 +2945,7 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */ } } } else if (zend_is_variable(arg)) { - if (fbc) { + if (fbc) { if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) { zend_compile_var(&arg_node, arg, BP_VAR_W, 1); opcode = ZEND_SEND_REF; @@ -5346,13 +5346,15 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ arg_info->type = ZEND_TYPE_ENCODE(0, 1); if (type_ast) { - uint32_t default_type, arg_type; + uint32_t default_type = Z_TYPE(default_node.u.constant); - default_type = Z_TYPE(default_node.u.constant); + uint32_t arg_type; + zend_bool is_class; op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; arg_info->type = zend_compile_typename(type_ast, default_ast && default_type == IS_NULL); + is_class = ZEND_TYPE_IS_CLASS(arg_info->type); arg_type = ZEND_TYPE_CODE(arg_info->type); if (arg_type == IS_VOID) { @@ -5360,7 +5362,10 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ } if (default_ast && default_type != IS_NULL && default_type != IS_CONSTANT_AST) { - switch (arg_type) { + if (is_class) { + zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " + "with a class type can only be NULL"); + } else switch (arg_type) { case IS_CALLABLE: zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with callable type can only be NULL"); @@ -5393,10 +5398,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ break; default: - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a class type can only be NULL"); - } else if (!ZEND_SAME_FAKE_TYPE(arg_type, default_type)) { + if (!ZEND_SAME_FAKE_TYPE(arg_type, default_type)) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with a %s type can only be %s or NULL", zend_get_type_by_const(arg_type), zend_get_type_by_const(arg_type)); @@ -5406,10 +5408,10 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ /* Allocate cache slot to speed-up run-time class resolution */ if (opline->opcode == ZEND_RECV_INIT) { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { + if (is_class) { opline->extended_value = zend_alloc_cache_slot(); } - } else if (ZEND_TYPE_IS_CLASS(arg_info->type)) { + } else if (is_class) { opline->op2.num = op_array->cache_size; op_array->cache_size += sizeof(void*); } else { @@ -5504,16 +5506,16 @@ void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_check_magic_method_attr(uint32_t attr, const char* entity) /* {{{ */ +static void zend_check_magic_method_attr(uint32_t attr, const char* method) /* {{{ */ { - if (memcmp(entity, "__callStatic", 12) == 0) { + if (memcmp(method, "__callStatic", sizeof("__callStatic") - 1) == 0) { if (!(attr & ZEND_ACC_PUBLIC) || !(attr & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static"); } } else if (!(attr & ZEND_ACC_PUBLIC) || (attr & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "The magic method %s() must have public visibility and cannot be static", - entity); + method); } } /* }}} */ From 9f6e8fb0a8ebd531256ceef1cd3d7aa4c9163feb Mon Sep 17 00:00:00 2001 From: rjhdby Date: Sat, 2 Mar 2019 10:36:34 +0300 Subject: [PATCH 11/12] recommended corrections --- Zend/zend_compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index b362d0288992..d64fb28876fe 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6228,7 +6228,7 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ zend_string_release(lcname); zend_build_properties_info_table(ce); ce->ce_flags |= ZEND_ACC_LINKED; - return; + return NULL; } } From 95e6599fadc41c2448678fe40f46462438110ace Mon Sep 17 00:00:00 2001 From: rjhdby Date: Sat, 2 Mar 2019 10:52:18 +0300 Subject: [PATCH 12/12] missed break --- Zend/zend_compile.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d64fb28876fe..095dd6f80d5e 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5398,6 +5398,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ "with a %s type can only be %s or NULL", zend_get_type_by_const(arg_type), zend_get_type_by_const(arg_type)); } + break; } }