diff options
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/tests/bug46304.phpt | 15 | ||||
-rw-r--r-- | Zend/tests/case_insensitive_constant_deprecation.phpt | 127 | ||||
-rw-r--r-- | Zend/zend_builtin_functions.c | 9 | ||||
-rw-r--r-- | Zend/zend_constants.c | 92 | ||||
-rw-r--r-- | Zend/zend_constants.h | 6 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 13 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 13 |
7 files changed, 254 insertions, 21 deletions
diff --git a/Zend/tests/bug46304.phpt b/Zend/tests/bug46304.phpt index e2e031116d..9898838907 100644 --- a/Zend/tests/bug46304.phpt +++ b/Zend/tests/bug46304.phpt @@ -40,6 +40,11 @@ print ns1\ns2\coNSt6 . "\n"; print NS1\ns2\coNSt1 . "\n"; ?> --EXPECTF-- +Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 6 + +Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 7 + +Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 8 value1 value1 value1 @@ -52,13 +57,23 @@ value3 value4 value4 value4 + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS1\ns2\const4" in %s on line 25 value4 value5 value5 value5 + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\ns2\const5" in %s on line 30 value5 + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\NS2\coNSt6" in %s on line 32 value6 + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\NS2\coNSt6" in %s on line 33 value6 + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "ns1\NS2\coNSt6" in %s on line 34 value6 value6 diff --git a/Zend/tests/case_insensitive_constant_deprecation.phpt b/Zend/tests/case_insensitive_constant_deprecation.phpt new file mode 100644 index 0000000000..e7a92c8c4c --- /dev/null +++ b/Zend/tests/case_insensitive_constant_deprecation.phpt @@ -0,0 +1,127 @@ +--TEST-- +Case-insensitive constants are deprecated +--FILE-- +<?php + +namespace { + define('FOO', 42, true); // Deprecated + define('NS\FOO', 24, true); // Deprecated + + var_dump(FOO); // Ok + var_dump(foo); // Deprecated + + var_dump(NS\FOO); // Ok + var_dump(ns\FOO); // Ok + var_dump(ns\foo); // Deprecated + + var_dump(defined('FOO')); // Ok + var_dump(defined('foo')); // Ok + var_dump(defined('NS\FOO')); // Ok + var_dump(defined('ns\FOO')); // Ok + var_dump(defined('ns\foo')); // Ok + + var_dump(constant('FOO')); // Ok + var_dump(constant('foo')); // Deprecated + var_dump(constant('NS\FOO')); // Ok + var_dump(constant('ns\FOO')); // Ok + var_dump(constant('ns\foo')); // Deprecated +} + +namespace NS { + var_dump(FOO); // Ok + var_dump(foo); // Deprecated +} + +namespace ns { + var_dump(FOO); // Ok + var_dump(foo); // Deprecated +} + +namespace Other { + var_dump(FOO); // Ok + var_dump(foo); // Deprecated + + var_dump(defined('FOO')); // Ok + var_dump(defined('foo')); // Ok + var_dump(defined('NS\FOO')); // Ok + var_dump(defined('ns\FOO')); // Ok + var_dump(defined('ns\foo')); // Ok + + var_dump(constant('FOO')); // Ok + var_dump(constant('foo')); // Deprecated + var_dump(constant('NS\FOO')); // Ok + var_dump(constant('ns\FOO')); // Ok + var_dump(constant('ns\foo')); // Deprecated + + const C1 = FOO; // Ok + var_dump(C1); + const C2 = foo; // Deprecated + var_dump(C2); + const C3 = 1 + FOO; // Ok + var_dump(C3); + const C4 = 1 + foo; // Deprecated + var_dump(C4); +} + +?> +--EXPECTF-- +Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 4 + +Deprecated: define(): Declaration of case-insensitive constants is deprecated in %s on line 5 +int(42) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 8 +int(42) +int(24) +int(24) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 12 +int(24) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +int(42) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 21 +int(42) +int(24) +int(24) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 24 +int(24) +int(24) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 29 +int(24) +int(24) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 34 +int(24) +int(42) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 39 +int(42) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +int(42) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 48 +int(42) +int(24) +int(24) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "NS\FOO" in %s on line 51 +int(24) +int(42) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 55 +int(42) +int(43) + +Deprecated: Case-insensitive constants are deprecated. The correct casing for this constant is "FOO" in %s on line 59 +int(43) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 57e5d77380..7b6cebff5e 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -854,7 +854,6 @@ ZEND_FUNCTION(define) case_sensitive = 0; } - /* class constant, check if there is name and make sure class is valid & exists */ if (zend_memnstr(ZSTR_VAL(name), "::", sizeof("::") - 1, ZSTR_VAL(name) + ZSTR_LEN(name))) { zend_error(E_WARNING, "Class constants cannot be defined or redefined"); RETURN_FALSE; @@ -905,7 +904,13 @@ repeat: ZVAL_COPY(&c.value, val); zval_ptr_dtor(&val_free); + register_constant: + if (non_cs) { + zend_error(E_DEPRECATED, + "define(): Declaration of case-insensitive constants is deprecated"); + } + c.flags = case_sensitive; /* non persistent */ c.name = zend_string_copy(name); c.module_number = PHP_USER_CONSTANT; @@ -928,7 +933,7 @@ ZEND_FUNCTION(defined) Z_PARAM_STR(name) ZEND_PARSE_PARAMETERS_END(); - if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT)) { + if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT | ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK)) { RETURN_TRUE; } else { RETURN_FALSE; diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index fe1d9e235b..8b68858ad4 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -250,7 +250,7 @@ ZEND_API int zend_verify_const_access(zend_class_constant *c, zend_class_entry * } /* }}} */ -ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len) +static inline zend_constant *zend_get_constant_str_impl(const char *name, size_t name_len) { zend_constant *c; ALLOCA_FLAG(use_heap) @@ -268,10 +268,16 @@ ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len) free_alloca(lcname, use_heap); } + return c; +} + +ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len) +{ + zend_constant *c = zend_get_constant_str_impl(name, name_len); return c ? &c->value : NULL; } -ZEND_API zval *zend_get_constant(zend_string *name) +static inline zend_constant *zend_get_constant_impl(zend_string *name) { zval *zv; zend_constant *c; @@ -291,9 +297,32 @@ ZEND_API zval *zend_get_constant(zend_string *name) c = zend_get_special_constant(ZSTR_VAL(name), ZSTR_LEN(name)); } free_alloca(lcname, use_heap); - return c ? &c->value : NULL; + return c; + } else { + return (zend_constant *) Z_PTR_P(zv); + } +} + +ZEND_API zval *zend_get_constant(zend_string *name) +{ + zend_constant *c = zend_get_constant_impl(name); + return c ? &c->value : NULL; +} + +static zend_bool is_access_deprecated(const zend_constant *c, const char *access_name) { + const char *ns_sep = zend_memrchr(ZSTR_VAL(c->name), '\\', ZSTR_LEN(c->name)); + if (ns_sep) { + /* Namespaces are always case-insensitive. Only compare shortname. */ + size_t shortname_offset = ns_sep - ZSTR_VAL(c->name) + 1; + size_t shortname_len = ZSTR_LEN(c->name) - shortname_offset; + return memcmp( + access_name + shortname_offset, + ZSTR_VAL(c->name) + shortname_offset, + shortname_len + ) != 0; } else { - return &((zend_constant*)Z_PTR_P(zv))->value; + /* No namespace, compare whole name */ + return memcmp(access_name, ZSTR_VAL(c->name), ZSTR_LEN(c->name)) != 0; } } @@ -415,26 +444,45 @@ failure: } } free_alloca(lcname, use_heap); - if (c) { - return &c->value; + + if (!c) { + if (!(flags & IS_CONSTANT_UNQUALIFIED)) { + return NULL; + } + + /* name requires runtime resolution, need to check non-namespaced name */ + c = zend_get_constant_str_impl(constant_name, const_name_len); + name = constant_name; } - /* name requires runtime resolution, need to check non-namespaced name */ - if ((flags & IS_CONSTANT_UNQUALIFIED) != 0) { - return zend_get_constant_str(constant_name, const_name_len); + } else { + if (cname) { + c = zend_get_constant_impl(cname); + } else { + c = zend_get_constant_str_impl(name, name_len); } + } + + if (!c) { return NULL; } - if (cname) { - return zend_get_constant(cname); - } else { - return zend_get_constant_str(name, name_len); + if (!(flags & ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK)) { + if (!(c->flags & (CONST_CS|CONST_CT_SUBST)) && is_access_deprecated(c, name)) { + zend_error(E_DEPRECATED, + "Case-insensitive constants are deprecated. " + "The correct casing for this constant is \"%s\"", + ZSTR_VAL(c->name)); + } } + + return &c->value; } -ZEND_API zend_constant* ZEND_FASTCALL zend_quick_get_constant(const zval *key, uint32_t flags) +ZEND_API zend_constant* ZEND_FASTCALL zend_quick_get_constant( + const zval *key, uint32_t flags, zend_bool *is_deprecated) { zval *zv; + const zval *orig_key = key; zend_constant *c = NULL; zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); @@ -461,6 +509,22 @@ ZEND_API zend_constant* ZEND_FASTCALL zend_quick_get_constant(const zval *key, u } } } + + if (!c) { + return NULL; + } + + if (is_deprecated) { + if (c->flags & (CONST_CS|CONST_CT_SUBST)) { + /* Constant is case-sensitive or true/false/null */ + *is_deprecated = 0; + } else { + zend_bool ns_fallback = key >= orig_key + 2; + const zval *access_key = ns_fallback ? orig_key + 2 : orig_key - 1; + *is_deprecated = is_access_deprecated(c, Z_STRVAL_P(access_key)); + } + } + return c; } diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h index 98484debe2..e06d91ee14 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -31,6 +31,9 @@ #define PHP_USER_CONSTANT INT_MAX /* a constant defined in user space */ +/* Flag for zend_get_constant_ex(). Must not class with ZEND_FETCH_CLASS_* flags. */ +#define ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK 0x1000 + typedef struct _zend_constant { zval value; zend_string *name; @@ -79,7 +82,8 @@ ZEND_API int zend_register_constant(zend_constant *c); #ifdef ZTS void zend_copy_constants(HashTable *target, HashTable *sourc); #endif -ZEND_API zend_constant* ZEND_FASTCALL zend_quick_get_constant(const zval *key, uint32_t flags); +ZEND_API zend_constant* ZEND_FASTCALL zend_quick_get_constant( + const zval *key, uint32_t flags, zend_bool *is_deprecated); END_EXTERN_C() #define ZEND_CONSTANT_DTOR free_zend_constant diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 898bb1229a..3d0fdc0182 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5045,11 +5045,12 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED|CONST_FETCH, CONST, CACHE_SLOT) { USE_OPLINE zend_constant *c; + zend_bool is_deprecated; c = CACHED_PTR(opline->extended_value); if (EXPECTED(c != NULL) && EXPECTED(!IS_SPECIAL_CACHE_VAL(c))) { /* pass */ - } else if (UNEXPECTED((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num)) == NULL)) { + } else if (UNEXPECTED((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num, &is_deprecated)) == NULL)) { SAVE_OPLINE(); if ((opline->op1.num & IS_CONSTANT_UNQUALIFIED) != 0) { @@ -5070,6 +5071,14 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED|CONST_FETCH, CONST, CACHE_SLOT) ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } + } else if (is_deprecated) { + SAVE_OPLINE(); + zend_error(E_DEPRECATED, + "Case-insensitive constants are deprecated. " + "The correct casing for this constant is \"%s\"", + ZSTR_VAL(c->name)); + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { CACHE_PTR(opline->extended_value, c); } @@ -7611,7 +7620,7 @@ ZEND_VM_HANDLER(122, ZEND_DEFINED, CONST, ANY, CACHE_SLOT) break; } } - if ((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op1), 0)) == NULL) { + if ((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op1), 0, NULL)) == NULL) { CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants)))); result = 0; } else { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 499838f1cc..c5598d6da7 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3883,7 +3883,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST_HANDLER(ZEN break; } } - if ((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op1), 0)) == NULL) { + if ((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op1), 0, NULL)) == NULL) { CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants)))); result = 0; } else { @@ -31965,11 +31965,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON { USE_OPLINE zend_constant *c; + zend_bool is_deprecated; c = CACHED_PTR(opline->extended_value); if (EXPECTED(c != NULL) && EXPECTED(!IS_SPECIAL_CACHE_VAL(c))) { /* pass */ - } else if (UNEXPECTED((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num)) == NULL)) { + } else if (UNEXPECTED((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num, &is_deprecated)) == NULL)) { SAVE_OPLINE(); if ((opline->op1.num & IS_CONSTANT_UNQUALIFIED) != 0) { @@ -31990,6 +31991,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON ZVAL_UNDEF(EX_VAR(opline->result.var)); HANDLE_EXCEPTION(); } + } else if (is_deprecated) { + SAVE_OPLINE(); + zend_error(E_DEPRECATED, + "Case-insensitive constants are deprecated. " + "The correct casing for this constant is \"%s\"", + ZSTR_VAL(c->name)); + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { CACHE_PTR(opline->extended_value, c); } |