diff --git a/Zend/zend.h b/Zend/zend.h index dd04aab63e934..8eafa8f2fe528 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -189,6 +189,42 @@ struct _zend_class_entry { } info; }; +#define CHECK_NAME_CASE(_type,_name,_len,_ref_name,_ref_len) { \ + char *_tmp_name=_name; \ + size_t _tmp_len=_len; \ + if ((*(_tmp_name))=='\\') { \ + _tmp_name++; \ + _tmp_len--; \ + } \ + if (((_tmp_len)!=(_ref_len)) \ + || memcmp((_tmp_name),(_ref_name),(_tmp_len))) { \ + zend_error(E_STRICT,"Case mismatch in %s name (%s should be %s)" \ + ,_type,(_tmp_name),(_ref_name)); \ + } } + +#define CHECK_CLASS_CASE(_name,_len,_ce) { \ + if (_ce) CHECK_NAME_CASE("class",(_name),(_len) \ + ,(_ce)->name->val,(_ce)->name->len); } + +#define CHECK_FUNCTION_CASE(_name,_len,_fe) { \ + if (_fe) CHECK_NAME_CASE("function",(_name),(_len) \ + ,(_fe)->common.function_name->val \ + ,(_fe)->common.function_name->len); } + +#define CHECK_METHOD_CASE(_name,_len,_fe) { \ + if (_fe) CHECK_NAME_CASE("method",(_name),(_len) \ + ,(_fe)->common.function_name->val \ + ,(_fe)->common.function_name->len); } + +#define CHECK_CLASS_CASE_ZSTR(_zstr,_ce) \ + CHECK_CLASS_CASE((_zstr)->val,(_zstr)->len,(_ce)) + +#define CHECK_FUNCTION_CASE_ZSTR(_zstr,_fe) \ + CHECK_FUNCTION_CASE((_zstr)->val,(_zstr)->len,(_fe)) + +#define CHECK_METHOD_CASE_ZSTR(_zstr,_fe) \ + CHECK_METHOD_CASE((_zstr)->val,(_zstr)->len,(_fe)) + typedef struct _zend_utility_functions { void (*error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0); size_t (*printf_function)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 01d3f9a0602fe..7ed31afb21341 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2751,6 +2751,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca /* Check if function with given name exists. * This may be a compound name that includes namespace name */ if (EXPECTED((fcc->function_handler = zend_hash_find_ptr(EG(function_table), lmname)) != NULL)) { + CHECK_FUNCTION_CASE_ZSTR(Z_STR_P(callable),fcc->function_handler); if (lmname != Z_STR_P(callable)) { STR_ALLOCA_FREE(lmname, use_heap); } @@ -2763,6 +2764,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca } zend_str_tolower(lmname->val, lmname->len); if ((fcc->function_handler = zend_hash_find_ptr(EG(function_table), lmname)) != NULL) { + CHECK_FUNCTION_CASE_ZSTR(Z_STR_P(callable),fcc->function_handler); STR_ALLOCA_FREE(lmname, use_heap); return 1; } @@ -2832,6 +2834,7 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca retval = 1; } } else if ((fcc->function_handler = zend_hash_find_ptr(ftable, lmname)) != NULL) { + CHECK_METHOD_CASE_ZSTR(mname,fcc->function_handler); retval = 1; if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) && !strict_class && EG(scope) && @@ -3942,6 +3945,7 @@ ZEND_API zend_string *zend_resolve_method_name(zend_class_entry *ce, zend_functi } if (name->len == f->common.function_name->len && !strncasecmp(name->val, f->common.function_name->val, f->common.function_name->len)) { + CHECK_METHOD_CASE_ZSTR(name,f); return f->common.function_name; } return zend_find_alias_name(f->common.scope, name); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 32f210e44c37a..fe35ea5fb7512 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1351,6 +1351,7 @@ ZEND_FUNCTION(class_exists) } ce = zend_hash_find_ptr(EG(class_table), lc_name); zend_string_release(lc_name); + CHECK_CLASS_CASE_ZSTR(class_name,ce); RETURN_BOOL(ce && !((ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT)) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)); } @@ -1393,6 +1394,7 @@ ZEND_FUNCTION(interface_exists) } ce = zend_hash_find_ptr(EG(class_table), lc_name); zend_string_release(lc_name); + CHECK_CLASS_CASE_ZSTR(iface_name,ce); RETURN_BOOL(ce && ce->ce_flags & ZEND_ACC_INTERFACE); } @@ -1435,6 +1437,7 @@ ZEND_FUNCTION(trait_exists) } ce = zend_hash_find_ptr(EG(class_table), lc_name); zend_string_release(lc_name); + CHECK_CLASS_CASE_ZSTR(trait_name,ce); RETURN_BOOL(ce && ((ce->ce_flags & ZEND_ACC_TRAIT) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)); } @@ -1475,6 +1478,7 @@ ZEND_FUNCTION(function_exists) func = zend_hash_find_ptr(EG(function_table), lcname); zend_string_release(lcname); + CHECK_FUNCTION_CASE(name,name_len,func); /* * A bit of a hack, but not a bad one: we see if the handler of the function diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c06ebc4595e74..f676021ae786c 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2652,6 +2652,7 @@ static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t lcname = zend_string_tolower(name); fbc = zend_hash_find_ptr(CG(function_table), lcname); + CHECK_FUNCTION_CASE_ZSTR(name,fbc); if (!fbc || (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) ) { @@ -2815,6 +2816,7 @@ void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ lcname = zend_string_tolower(Z_STR_P(name)); fbc = zend_hash_find_ptr(CG(function_table), lcname); + CHECK_FUNCTION_CASE_ZSTR(Z_STR_P(name),fbc); if (!fbc || (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) ) { @@ -4757,6 +4759,7 @@ void zend_compile_use(zend_ast *ast) /* {{{ */ case T_FUNCTION: { zend_function *fn = zend_hash_find_ptr(CG(function_table), lookup_name); + CHECK_FUNCTION_CASE_ZSTR(new_name,fn); if (fn && fn->type == ZEND_USER_FUNCTION && fn->op_array.filename == CG(compiled_filename) ) { diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 14be7d48133d2..3f1b7ca21f046 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -943,6 +943,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k if (!key) { zend_string_release(lc_name); } + CHECK_CLASS_CASE_ZSTR(name,ce); return ce; } @@ -1030,6 +1031,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *k if (!key) { zend_string_release(lc_name); } + CHECK_CLASS_CASE_ZSTR(name,ce); return ce; } /* }}} */ diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index c140a18ec2f03..6772591982cb4 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -143,6 +143,7 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */ lc_parent_class_name = zend_string_tolower(ce->parent->name); if (!zend_hash_exists(&ce->function_table, lc_parent_class_name) && (function = zend_hash_find_ptr(&ce->parent->function_table, lc_parent_class_name)) != NULL) { + CHECK_CLASS_CASE_ZSTR(ce->parent->name,ce->parent); if (function->common.fn_flags & ZEND_ACC_CTOR) { /* inherit parent's constructor */ if (function->type == ZEND_INTERNAL_FUNCTION) { diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 852d2d01dd6fe..3fd7899caa154 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -994,6 +994,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str } fbc = Z_FUNC_P(func); + CHECK_METHOD_CASE_ZSTR(method_name,fbc); /* Check access level */ if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) { zend_function *updated_fbc; @@ -1004,6 +1005,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str updated_fbc = zend_check_private_int(fbc, zobj->ce, lc_method_name); if (EXPECTED(updated_fbc != NULL)) { fbc = updated_fbc; + CHECK_METHOD_CASE_ZSTR(method_name,fbc); } else { if (zobj->ce->__call) { fbc = zend_get_user_call_function(zobj->ce, method_name); @@ -1023,6 +1025,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str if (priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE && priv_fbc->common.scope == EG(scope)) { fbc = priv_fbc; + CHECK_METHOD_CASE_ZSTR(method_name,fbc); } } } @@ -1135,6 +1138,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st zval *func = zend_hash_find(&ce->function_table, lc_function_name); if (EXPECTED(func != NULL)) { fbc = Z_FUNC_P(func); + CHECK_METHOD_CASE_ZSTR(function_name,fbc); } else { if (UNEXPECTED(!key)) { zend_string_release(lc_function_name); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index aedd52cfe0db2..9c267ef9d5966 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2528,6 +2528,7 @@ ZEND_VM_C_LABEL(try_function_name): FREE_OP2(); fbc = Z_FUNC_P(func); + CHECK_FUNCTION_CASE_ZSTR(Z_STR_P(function_name),fbc); called_scope = NULL; object = NULL; } else if (OP2_TYPE != IS_CONST && diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index bc5eb60b315dd..bcb4c5e9687f5 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1585,6 +1585,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE zend_string_release(lcname); fbc = Z_FUNC_P(func); + CHECK_FUNCTION_CASE_ZSTR(Z_STR_P(function_name),fbc); called_scope = NULL; object = NULL; } else if (IS_CONST != IS_CONST && @@ -1968,6 +1969,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA zend_string_release(lcname); fbc = Z_FUNC_P(func); + CHECK_FUNCTION_CASE_ZSTR(Z_STR_P(function_name),fbc); called_scope = NULL; object = NULL; } else if (IS_CV != IS_CONST && @@ -2158,6 +2160,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER(ZEND_OPCOD zval_ptr_dtor_nogc(free_op2); fbc = Z_FUNC_P(func); + CHECK_FUNCTION_CASE_ZSTR(Z_STR_P(function_name),fbc); called_scope = NULL; object = NULL; } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&