Skip to content

Commit c01014f

Browse files
committed
implement semi-reserved words support for object declaration, object member access and namespaces
1 parent 9d6295e commit c01014f

File tree

5 files changed

+19785
-3723
lines changed

5 files changed

+19785
-3723
lines changed

Zend/zend_compile.c

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
695695
zend_string_addref(name);
696696
}
697697
/* Ensure that \self, \parent and \static are not used */
698-
if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
698+
if (ZEND_FETCH_CLASS_DEFAULT != zend_check_reserved_name(name)) {
699699
zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", name->val);
700700
}
701701
return name;
@@ -1479,6 +1479,27 @@ uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
14791479
}
14801480
/* }}} */
14811481

1482+
uint32_t zend_check_reserved_name(zend_string *name) /* {{{ */
1483+
{
1484+
if (zend_string_equals_literal_ci(name, "self")) {
1485+
return ZEND_FETCH_CLASS_SELF;
1486+
} else if (zend_string_equals_literal_ci(name, "parent")) {
1487+
return ZEND_FETCH_CLASS_PARENT;
1488+
} else if (zend_string_equals_literal_ci(name, "static")) {
1489+
return ZEND_FETCH_CLASS_STATIC;
1490+
} else if (zend_string_equals_literal_ci(name, "namespace")) {
1491+
return ZEND_FETCH_NAMESPACE;
1492+
} else if (zend_string_equals_literal_ci(name, "array")) {
1493+
return ZEND_FETCH_ARRAY;
1494+
} else if (zend_string_equals_literal_ci(name, "callable")) {
1495+
return ZEND_FETCH_CALLABLE;
1496+
} else {
1497+
return ZEND_FETCH_CLASS_DEFAULT;
1498+
}
1499+
}
1500+
/* }}} */
1501+
1502+
14821503
ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */
14831504
{
14841505
return op_array->vars[EX_VAR_TO_NUM(var)];
@@ -4404,6 +4425,12 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */
44044425
zend_const_expr_to_zval(&value_zv, value_ast);
44054426

44064427
name = zend_new_interned_string_safe(name);
4428+
4429+
if (zend_string_equals_literal_ci(name, "class")) {
4430+
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine %s::%s as ::%s is reserved",
4431+
ce->name->val, name->val, name->val);
4432+
}
4433+
44074434
if (zend_hash_add(&ce->constants_table, name, &value_zv) == NULL) {
44084435
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s",
44094436
ce->name->val, name->val);
@@ -4513,13 +4540,8 @@ void zend_compile_use_trait(zend_ast *ast) /* {{{ */
45134540
"%s is used in %s", name->val, ce->name->val);
45144541
}
45154542

4516-
switch (zend_get_class_fetch_type(name)) {
4517-
case ZEND_FETCH_CLASS_SELF:
4518-
case ZEND_FETCH_CLASS_PARENT:
4519-
case ZEND_FETCH_CLASS_STATIC:
4520-
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as trait name "
4521-
"as it is reserved", name->val);
4522-
break;
4543+
if(ZEND_FETCH_CLASS_DEFAULT != zend_check_reserved_name(name)) {
4544+
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as trait name as it is reserved", name->val);
45234545
}
45244546

45254547
opline = get_next_op(CG(active_op_array));
@@ -4593,7 +4615,7 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
45934615
return;
45944616
}
45954617

4596-
if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
4618+
if (ZEND_FETCH_CLASS_DEFAULT != zend_check_reserved_name(name)) {
45974619
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved",
45984620
name->val);
45994621
}
@@ -4845,13 +4867,16 @@ void zend_compile_use(zend_ast *ast) /* {{{ */
48454867
lookup_name = zend_string_tolower(new_name);
48464868
}
48474869

4848-
if (type == T_CLASS && (zend_string_equals_literal(lookup_name, "self")
4849-
|| zend_string_equals_literal(lookup_name, "parent"))
4850-
) {
4870+
if (type == T_CLASS && ZEND_FETCH_CLASS_DEFAULT != zend_check_reserved_name(lookup_name)) {
48514871
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' "
48524872
"is a special class name", old_name->val, new_name->val, new_name->val);
48534873
}
48544874

4875+
if (type == T_CLASS && ZEND_FETCH_CLASS_DEFAULT != zend_check_reserved_name(old_name)) {
4876+
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s because '%s' "
4877+
"is a special class name", old_name->val, old_name->val);
4878+
}
4879+
48554880
if (current_ns) {
48564881
zend_string *ns_name = zend_string_alloc(current_ns->len + 1 + new_name->len, 0);
48574882
zend_str_tolower_copy(ns_name->val, current_ns->val, current_ns->len);
@@ -5001,7 +5026,7 @@ void zend_compile_namespace(zend_ast *ast) /* {{{ */
50015026
if (name_ast) {
50025027
name = zend_ast_get_str(name_ast);
50035028

5004-
if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
5029+
if (ZEND_FETCH_CLASS_DEFAULT != zend_check_reserved_name(name)) {
50055030
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", name->val);
50065031
}
50075032

@@ -5842,7 +5867,7 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
58425867
zend_ast *const_ast = ast->child[1];
58435868

58445869
znode class_node, const_node;
5845-
zend_op *opline, *class_op = NULL;
5870+
zend_op *opline;
58465871
zend_string *resolved_name;
58475872

58485873
zend_eval_const_expr(&class_ast);
@@ -5864,7 +5889,7 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
58645889
if (class_ast->kind == ZEND_AST_ZVAL) {
58655890
zend_string_release(resolved_name);
58665891
}
5867-
class_op = zend_compile_class_ref(&class_node, class_ast);
5892+
zend_compile_class_ref(&class_node, class_ast);
58685893
}
58695894

58705895
zend_compile_expr(&const_node, const_ast);

Zend/zend_compile.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ ZEND_API zend_bool zend_is_compiling(void);
719719
ZEND_API char *zend_make_compiled_string_description(const char *name);
720720
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers);
721721
uint32_t zend_get_class_fetch_type(zend_string *name);
722+
uint32_t zend_check_reserved_name(zend_string *name);
722723

723724
typedef zend_bool (*zend_auto_global_callback)(zend_string *name);
724725
typedef struct _zend_auto_global {
@@ -753,6 +754,9 @@ int zend_add_literal(zend_op_array *op_array, zval *zv);
753754
#define ZEND_FETCH_CLASS_AUTO 4
754755
#define ZEND_FETCH_CLASS_INTERFACE 5
755756
#define ZEND_FETCH_CLASS_TRAIT 6
757+
#define ZEND_FETCH_NAMESPACE 7
758+
#define ZEND_FETCH_ARRAY 8
759+
#define ZEND_FETCH_CALLABLE 9
756760
#define ZEND_FETCH_CLASS_MASK 0x0f
757761
#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80
758762
#define ZEND_FETCH_CLASS_SILENT 0x0100

0 commit comments

Comments
 (0)