diff options
author | Nikita Popov <nikic@php.net> | 2015-03-30 22:05:26 +0200 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2015-03-30 22:59:06 +0200 |
commit | 53a40386bc81da824468ac3aa8b1962ab7029238 (patch) | |
tree | db15d2da7900c4726b3ae6e775a59fa0354cb50f /Zend/zend_compile.c | |
parent | 607b7d662a854443713e8a9c651c888527718618 (diff) | |
download | php-git-53a40386bc81da824468ac3aa8b1962ab7029238.tar.gz |
Implement additional type reservations
* The class names false, true and null are now reserved.
* The code dealing with reserved class names is now decoupled
from scalar type hint handling. It also includes self, parent,
and static, which are class names which were already reserved
previously.
* Reuse existing messages for reserved class names.
Fallout: class_alias() can no longer alias self, parent and static.
However this never really worked in the first place, as the test
which was testing this shows.
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r-- | Zend/zend_compile.c | 102 |
1 files changed, 58 insertions, 44 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 9d5bd0f1f1..2a76ff39e6 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -129,6 +129,53 @@ static zend_bool zend_get_unqualified_name(const zend_string *name, const char * } /* }}} */ +struct reserved_class_name { + const char *name; + size_t len; +}; +static const struct reserved_class_name reserved_class_names[] = { + {ZEND_STRL("bool")}, + {ZEND_STRL("false")}, + {ZEND_STRL("float")}, + {ZEND_STRL("int")}, + {ZEND_STRL("null")}, + {ZEND_STRL("parent")}, + {ZEND_STRL("self")}, + {ZEND_STRL("static")}, + {ZEND_STRL("string")}, + {ZEND_STRL("true")}, + {NULL, 0} +}; + +static zend_bool zend_is_reserved_class_name(const zend_string *name) /* {{{ */ +{ + const struct reserved_class_name *reserved = reserved_class_names; + + const char *uqname = name->val; + size_t uqname_len = name->len; + zend_get_unqualified_name(name, &uqname, &uqname_len); + + for (; reserved->name; ++reserved) { + if (uqname_len == reserved->len + && zend_binary_strcasecmp(uqname, uqname_len, reserved->name, reserved->len) == 0 + ) { + return 1; + } + } + + return 0; +} +/* }}} */ + +ZEND_API void zend_assert_valid_class_name(const zend_string *name) /* {{{ */ +{ + if (zend_is_reserved_class_name(name)) { + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot use '%s' as class name as it is reserved", name->val); + } +} +/* }}} */ + typedef struct _scalar_typehint_info { const char* name; const size_t name_len; @@ -143,39 +190,19 @@ static const scalar_typehint_info scalar_typehints[] = { {NULL, 0, IS_UNDEF} }; -static zend_always_inline const scalar_typehint_info* zend_find_scalar_typehint(const zend_string *const_name) /* {{{ */ +static zend_always_inline const scalar_typehint_info* zend_find_scalar_typehint(const zend_string *name) /* {{{ */ { const scalar_typehint_info *info = &scalar_typehints[0]; - const char *uqname; - size_t uqname_len; - - if (!zend_get_unqualified_name(const_name, &uqname, &uqname_len)) { - uqname = const_name->val; - uqname_len = const_name->len; - } - while (info->name) { - if (uqname_len == info->name_len && zend_binary_strcasecmp(uqname, uqname_len, info->name, info->name_len) == 0) { - break; + for (; info->name; ++info) { + if (name->len == info->name_len + && zend_binary_strcasecmp(name->val, name->len, info->name, info->name_len) == 0 + ) { + return info; } - info++; - } - - if (info->name) { - return info; - } else { - return NULL; } -} -/* }}} */ - -ZEND_API void zend_assert_valid_class_name(const zend_string *const_name) /* {{{ */ -{ - const scalar_typehint_info *info = zend_find_scalar_typehint(const_name); - if (info) { - zend_error_noreturn(E_COMPILE_ERROR, "\"%s\" cannot be used as a class name", info->name); - } + return NULL; } /* }}} */ @@ -184,9 +211,6 @@ static zend_always_inline zend_uchar zend_lookup_scalar_typehint_by_name(const z const scalar_typehint_info *info = zend_find_scalar_typehint(const_name); if (info) { - if (const_name->len != info->name_len) { - zend_error_noreturn(E_COMPILE_ERROR, "\"%s\" cannot be used as a type declaration", const_name->val); - } return info->type; } else { return 0; @@ -4099,6 +4123,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, zend_bool is_ } else { if (zend_is_const_default_class_ref(return_type_ast)) { class_name = zend_resolve_class_name_ast(return_type_ast); + zend_assert_valid_class_name(class_name); } else { zend_string_addref(class_name); if (!is_method) { @@ -4225,9 +4250,9 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, zend_bool is_ if (type != 0) { arg_info->type_hint = type; } else { - if (zend_is_const_default_class_ref(type_ast)) { class_name = zend_resolve_class_name_ast(type_ast); + zend_assert_valid_class_name(class_name); } else { zend_string_addref(class_name); } @@ -4846,10 +4871,7 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ return; } - if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", - name->val); - } + zend_assert_valid_class_name(name); lcname = zend_string_tolower(name); @@ -4857,8 +4879,6 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ import_name = zend_hash_find_ptr(CG(current_import), lcname); } - zend_assert_valid_class_name(name); - if (CG(current_namespace)) { name = zend_prefix_with_ns(name); @@ -5094,19 +5114,13 @@ void zend_compile_use(zend_ast *ast) /* {{{ */ } } - if (type == T_CLASS) { - zend_assert_valid_class_name(new_name); - } - if (case_sensitive) { lookup_name = zend_string_copy(new_name); } else { lookup_name = zend_string_tolower(new_name); } - if (type == T_CLASS && (zend_string_equals_literal(lookup_name, "self") - || zend_string_equals_literal(lookup_name, "parent")) - ) { + if (type == T_CLASS && zend_is_reserved_class_name(new_name)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' " "is a special class name", old_name->val, new_name->val, new_name->val); } |