diff options
-rw-r--r-- | Zend/zend_constants.c | 50 | ||||
-rw-r--r-- | Zend/zend_constants.h | 2 | ||||
-rw-r--r-- | Zend/zend_execute.c | 113 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 42 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 42 |
5 files changed, 123 insertions, 126 deletions
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 8b68858ad4..48b01863ea 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -478,56 +478,6 @@ failure: return &c->value; } -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 (zv) { - c = (zend_constant*)Z_PTR_P(zv); - } else { - key++; - zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); - if (zv && (((zend_constant*)Z_PTR_P(zv))->flags & CONST_CS) == 0) { - c = (zend_constant*)Z_PTR_P(zv); - } else { - if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) { - key++; - zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); - if (zv) { - c = (zend_constant*)Z_PTR_P(zv); - } else { - key++; - zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); - if (zv && (((zend_constant*)Z_PTR_P(zv))->flags & CONST_CS) == 0) { - c = (zend_constant*)Z_PTR_P(zv); - } - } - } - } - } - - 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; -} - static void* zend_hash_add_constant(HashTable *ht, zend_string *key, zend_constant *c) { void *ret; diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h index e06d91ee14..b8112d33a1 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -82,8 +82,6 @@ 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_bool *is_deprecated); END_EXTERN_C() #define ZEND_CONSTANT_DTOR free_zend_constant diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 0778c19ddd..6abdc4c2ca 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3285,6 +3285,119 @@ static zend_never_inline zend_bool ZEND_FASTCALL zend_fe_reset_iterator(zval *ar } /* }}} */ +static zend_always_inline int _zend_quick_get_constant( + const zval *key, uint32_t flags, int check_defined_only OPLINE_DC EXECUTE_DATA_DC) /* {{{ */ +{ + 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 (zv) { + c = (zend_constant*)Z_PTR_P(zv); + } else { + key++; + zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); + if (zv && (((zend_constant*)Z_PTR_P(zv))->flags & CONST_CS) == 0) { + c = (zend_constant*)Z_PTR_P(zv); + } else { + if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) { + key++; + zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); + if (zv) { + c = (zend_constant*)Z_PTR_P(zv); + } else { + key++; + zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1); + if (zv && (((zend_constant*)Z_PTR_P(zv))->flags & CONST_CS) == 0) { + c = (zend_constant*)Z_PTR_P(zv); + } + } + } + } + } + + if (!c) { + if (!check_defined_only) { + if ((opline->op1.num & IS_CONSTANT_UNQUALIFIED) != 0) { + char *actual = (char *)zend_memrchr(Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)), '\\', Z_STRLEN_P(RT_CONSTANT(opline, opline->op2))); + if (!actual) { + ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(RT_CONSTANT(opline, opline->op2))); + } else { + actual++; + ZVAL_STRINGL(EX_VAR(opline->result.var), + actual, Z_STRLEN_P(RT_CONSTANT(opline, opline->op2)) - (actual - Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)))); + } + /* non-qualified constant - allow text substitution */ + zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", + Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); + } else { + zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + } + return FAILURE; + } + + if (!check_defined_only) { + ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); + if (!(c->flags & (CONST_CS|CONST_CT_SUBST))) { + const char *ns_sep; + size_t shortname_offset; + size_t shortname_len; + zend_bool is_deprecated; + + if (flags & IS_CONSTANT_UNQUALIFIED) { + const zval *access_key; + + if (!(flags & IS_CONSTANT_IN_NAMESPACE)) { + access_key = orig_key - 1; + } else { + if (key < orig_key + 2) { + goto check_short_name; + } else { + access_key = orig_key + 2; + } + } + is_deprecated = !zend_string_equals(c->name, Z_STR_P(access_key)); + } else { +check_short_name: + ns_sep = zend_memrchr(ZSTR_VAL(c->name), '\\', ZSTR_LEN(c->name)); + ZEND_ASSERT(ns_sep); + /* Namespaces are always case-insensitive. Only compare shortname. */ + shortname_offset = ns_sep - ZSTR_VAL(c->name) + 1; + shortname_len = ZSTR_LEN(c->name) - shortname_offset; + + is_deprecated = memcmp(ZSTR_VAL(c->name) + shortname_offset, Z_STRVAL_P(orig_key - 1) + shortname_offset, shortname_len) != 0; + } + + if (is_deprecated) { + zend_error(E_DEPRECATED, + "Case-insensitive constants are deprecated. " + "The correct casing for this constant is \"%s\"", + ZSTR_VAL(c->name)); + return SUCCESS; + } + } + } + + CACHE_PTR(opline->extended_value, c); + return SUCCESS; +} +/* }}} */ + +static zend_never_inline void ZEND_FASTCALL zend_quick_get_constant( + const zval *key, uint32_t flags OPLINE_DC EXECUTE_DATA_DC) /* {{{ */ +{ + _zend_quick_get_constant(key, flags, 0 OPLINE_CC EXECUTE_DATA_CC); +} + +static zend_never_inline int ZEND_FASTCALL zend_quick_check_constant( + const zval *key, uint32_t flags OPLINE_DC EXECUTE_DATA_DC) /* {{{ */ +{ + return _zend_quick_get_constant(key, flags, 1 OPLINE_CC EXECUTE_DATA_CC); +} + #ifdef ZEND_VM_TRACE_HANDLERS # include "zend_vm_trace_handlers.h" #elif defined(ZEND_VM_TRACE_MAP) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 3d0fdc0182..087dd3ac84 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5045,47 +5045,16 @@ 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, &is_deprecated)) == NULL)) { - SAVE_OPLINE(); - - if ((opline->op1.num & IS_CONSTANT_UNQUALIFIED) != 0) { - char *actual = (char *)zend_memrchr(Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)), '\\', Z_STRLEN_P(RT_CONSTANT(opline, opline->op2))); - if (!actual) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(RT_CONSTANT(opline, opline->op2))); - } else { - actual++; - ZVAL_STRINGL(EX_VAR(opline->result.var), - actual, Z_STRLEN_P(RT_CONSTANT(opline, opline->op2)) - (actual - Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)))); - } - /* non-qualified constant - allow text substitution */ - zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", - Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); - 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); + ZEND_VM_NEXT_OPCODE(); } - ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); - - ZEND_VM_NEXT_OPCODE(); + SAVE_OPLINE(); + zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CONST, CACHE_SLOT) @@ -7620,11 +7589,10 @@ ZEND_VM_HANDLER(122, ZEND_DEFINED, CONST, ANY, CACHE_SLOT) break; } } - if ((c = zend_quick_get_constant(RT_CONSTANT(opline, opline->op1), 0, NULL)) == NULL) { + if (zend_quick_check_constant(RT_CONSTANT(opline, opline->op1), ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants)))); result = 0; } else { - CACHE_PTR(opline->extended_value, c); result = 1; } } while (0); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c5598d6da7..a177bcea0f 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3883,11 +3883,10 @@ 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)) == NULL) { + if (zend_quick_check_constant(RT_CONSTANT(opline, opline->op1), ZEND_GET_CONSTANT_NO_DEPRECATION_CHECK OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants)))); result = 0; } else { - CACHE_PTR(opline->extended_value, c); result = 1; } } while (0); @@ -31965,47 +31964,16 @@ 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, &is_deprecated)) == NULL)) { - SAVE_OPLINE(); - - if ((opline->op1.num & IS_CONSTANT_UNQUALIFIED) != 0) { - char *actual = (char *)zend_memrchr(Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)), '\\', Z_STRLEN_P(RT_CONSTANT(opline, opline->op2))); - if (!actual) { - ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(RT_CONSTANT(opline, opline->op2))); - } else { - actual++; - ZVAL_STRINGL(EX_VAR(opline->result.var), - actual, Z_STRLEN_P(RT_CONSTANT(opline, opline->op2)) - (actual - Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)))); - } - /* non-qualified constant - allow text substitution */ - zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)", - Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var))); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } else { - zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))); - 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); + ZEND_VM_NEXT_OPCODE(); } - ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value); - - ZEND_VM_NEXT_OPCODE(); + SAVE_OPLINE(); + zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num OPLINE_CC EXECUTE_DATA_CC); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) |