arguments). (cmb)
. Fixed bug #76392 (Error relocating sapi/cli/php: unsupported relocation
type 37). (Peter Kokot)
+ . The declaration and use of case-insensitive constants has been deprecated.
+ (Nikita)
- Filter:
. Added the 'add_slashes' sanitization mode (FILTER_SANITIZE_ADD_SLASHES).
4. Deprecated Functionality
========================================
+Core:
+ . The declaration of case-insensitive constants has been deprecate. Passing
+ true as the third argument to define() will now generate a deprecation
+ warning. The use of case-insensitive constants with a case that differs from
+ the declaration is also deprecated.
+ (RFC: https://wiki.php.net/rfc/case_insensitive_constant_deprecation)
+
GD:
. image2wbmp() has been deprecated.
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
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
--- /dev/null
+--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)
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;
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;
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;
}
/* }}} */
-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)
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;
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;
}
}
}
}
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);
}
}
}
+
+ 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;
}
#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;
#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
{
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) {
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);
}
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 {
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 {
{
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) {
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);
}