1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Don't evalutae ZEND_AST_CLASS_CONST to ZEND_AST_CONSTANT ar

compile-time. Keep at to run-time and use Fast Class Cache during
run-time evaluation.
This commit is contained in:
Dmitry Stogov
2021-04-09 17:48:28 +03:00
parent 718dd06744
commit 4dcde9cf18
7 changed files with 125 additions and 16 deletions

View File

@@ -784,6 +784,19 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast
zend_enum_new(result, ce, case_name, case_value_zv);
break;
}
case ZEND_AST_CLASS_CONST:
{
zend_string *class_name = zend_ast_get_str(ast->child[0]);
zend_string *const_name = zend_ast_get_str(ast->child[1]);
zval *zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr);
if (UNEXPECTED(zv == NULL)) {
ZVAL_UNDEF(result);
return FAILURE;
}
ZVAL_COPY_OR_DUP(result, zv);
break;
}
default:
zend_throw_error(NULL, "Unsupported constant expression");
ret = FAILURE;

View File

@@ -9462,10 +9462,7 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
{
zend_ast *ast = *ast_ptr;
zend_ast *class_ast = ast->child[0];
zend_ast *const_ast = ast->child[1];
zend_string *class_name;
zend_string *const_name = zend_ast_get_str(const_ast);
zend_string *name;
int fetch_type;
if (class_ast->kind != ZEND_AST_ZVAL) {
@@ -9482,17 +9479,17 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
}
if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
class_name = zend_resolve_class_name_ast(class_ast);
} else {
zend_string_addref(class_name);
zend_string *tmp = zend_resolve_class_name_ast(class_ast);
zend_string_release_ex(class_name, 0);
if (tmp != class_name) {
zval *zv = zend_ast_get_zval(class_ast);
ZVAL_STR(zv, tmp);
}
}
name = zend_create_member_string(class_name, const_name);
zend_ast_destroy(ast);
zend_string_release_ex(class_name, 0);
*ast_ptr = zend_ast_create_constant(name, fetch_type | ZEND_FETCH_CLASS_EXCEPTION);
ast->attr |= ZEND_FETCH_CLASS_EXCEPTION;
}
/* }}} */

View File

@@ -324,11 +324,87 @@ ZEND_API zval *zend_get_constant(zend_string *name)
return NULL;
}
ZEND_API zval *zend_get_class_constant_ex(zend_string *class_name, zend_string *constant_name, zend_class_entry *scope, uint32_t flags)
{
zend_class_entry *ce = NULL;
zend_class_constant *c = NULL;
zval *ret_constant = NULL;
if (ZSTR_HAS_CE_CACHE(class_name)) {
ce = ZSTR_GET_CE_CACHE(class_name);
if (!ce) {
ce = zend_fetch_class(class_name, flags);
}
} else if (zend_string_equals_literal_ci(class_name, "self")) {
if (UNEXPECTED(!scope)) {
zend_throw_error(NULL, "Cannot access \"self\" when no class scope is active");
goto failure;
}
ce = scope;
} else if (zend_string_equals_literal_ci(class_name, "parent")) {
if (UNEXPECTED(!scope)) {
zend_throw_error(NULL, "Cannot access \"parent\" when no class scope is active");
goto failure;
} else if (UNEXPECTED(!scope->parent)) {
zend_throw_error(NULL, "Cannot access \"parent\" when current class scope has no parent");
goto failure;
} else {
ce = scope->parent;
}
} else if (zend_string_equals_literal_ci(class_name, "static")) {
ce = zend_get_called_scope(EG(current_execute_data));
if (UNEXPECTED(!ce)) {
zend_throw_error(NULL, "Cannot access \"static\" when no class scope is active");
goto failure;
}
} else {
ce = zend_fetch_class(class_name, flags);
}
if (ce) {
c = zend_hash_find_ptr(CE_CONSTANTS_TABLE(ce), constant_name);
if (c == NULL) {
if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
zend_throw_error(NULL, "Undefined constant %s::%s", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
goto failure;
}
ret_constant = NULL;
} else {
if (!zend_verify_const_access(c, scope)) {
if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
}
goto failure;
}
ret_constant = &c->value;
}
}
if (ret_constant && Z_TYPE_P(ret_constant) == IS_CONSTANT_AST) {
zend_result ret;
if (IS_CONSTANT_VISITED(ret_constant)) {
zend_throw_error(NULL, "Cannot declare self-referencing constant %s::%s", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
ret_constant = NULL;
goto failure;
}
MARK_CONSTANT_VISITED(ret_constant);
ret = zval_update_constant_ex(ret_constant, c->ce);
RESET_CONSTANT_VISITED(ret_constant);
if (UNEXPECTED(ret != SUCCESS)) {
ret_constant = NULL;
goto failure;
}
}
failure:
return ret_constant;
}
ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, uint32_t flags)
{
zend_constant *c;
const char *colon;
zend_class_entry *ce = NULL;
const char *name = ZSTR_VAL(cname);
size_t name_len = ZSTR_LEN(cname);
@@ -344,7 +420,14 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
int class_name_len = colon - name - 1;
size_t const_name_len = name_len - class_name_len - 2;
zend_string *constant_name = zend_string_init(colon + 1, const_name_len, 0);
zend_string *class_name = zend_string_init(name, class_name_len, 0);
zend_string *class_name = zend_string_init_interned(name, class_name_len, 0);
zval *ret_constant = zend_get_class_constant_ex(class_name, constant_name, scope, flags);
zend_string_release_ex(class_name, 0);
zend_string_efree(constant_name);
return ret_constant;
/*
zend_class_entry *ce = NULL;
zend_class_constant *c = NULL;
zval *ret_constant = NULL;
@@ -414,6 +497,7 @@ failure:
zend_string_release_ex(class_name, 0);
zend_string_efree(constant_name);
return ret_constant;
*/
}
/* non-class constant */

View File

@@ -76,6 +76,7 @@ ZEND_API bool zend_verify_const_access(zend_class_constant *c, zend_class_entry
ZEND_API zval *zend_get_constant(zend_string *name);
ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len);
ZEND_API zval *zend_get_constant_ex(zend_string *name, zend_class_entry *scope, uint32_t flags);
ZEND_API zval *zend_get_class_constant_ex(zend_string *class_name, zend_string *constant_name, zend_class_entry *scope, uint32_t flags);
ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, bool bval, int flags, int module_number);
ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number);
ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number);

View File

@@ -786,6 +786,10 @@ static ZEND_COLD zend_string *zend_get_function_declaration(
zend_ast *ast = Z_ASTVAL_P(zv);
if (ast->kind == ZEND_AST_CONSTANT) {
smart_str_append(&str, zend_ast_get_constant_name(ast));
} else if (ast->kind == ZEND_AST_CLASS_CONST) {
smart_str_append(&str, zend_ast_get_str(ast->child[0]));
smart_str_appends(&str, "::");
smart_str_append(&str, zend_ast_get_str(ast->child[1]));
} else {
smart_str_appends(&str, "<expression>");
}

View File

@@ -2820,7 +2820,9 @@ ZEND_METHOD(ReflectionParameter, isDefaultValueConstant)
if (Z_TYPE(default_value) == IS_CONSTANT_AST) {
zend_ast *ast = Z_ASTVAL(default_value);
RETVAL_BOOL(ast->kind == ZEND_AST_CONSTANT || ast->kind == ZEND_AST_CONSTANT_CLASS);
RETVAL_BOOL(ast->kind == ZEND_AST_CONSTANT
|| ast->kind == ZEND_AST_CONSTANT_CLASS
|| ast->kind == ZEND_AST_CLASS_CONST);
} else {
RETVAL_FALSE;
}
@@ -2858,6 +2860,13 @@ ZEND_METHOD(ReflectionParameter, getDefaultValueConstantName)
RETVAL_STR_COPY(zend_ast_get_constant_name(ast));
} else if (ast->kind == ZEND_AST_CONSTANT_CLASS) {
RETVAL_STRINGL("__CLASS__", sizeof("__CLASS__")-1);
} else if (ast->kind == ZEND_AST_CLASS_CONST) {
zend_string *class_name = zend_ast_get_str(ast->child[0]);
zend_string *const_name = zend_ast_get_str(ast->child[1]);
RETVAL_NEW_STR(zend_string_concat3(
ZSTR_VAL(class_name), ZSTR_LEN(class_name),
"::", sizeof("::")-1,
ZSTR_VAL(const_name), ZSTR_LEN(const_name)));
} else {
RETVAL_NULL();
}

View File

@@ -844,7 +844,8 @@ char *phpdbg_short_zval_print(zval *zv, int maxlen) /* {{{ */
zend_ast *ast = Z_ASTVAL_P(zv);
if (ast->kind == ZEND_AST_CONSTANT
|| ast->kind == ZEND_AST_CONSTANT_CLASS) {
|| ast->kind == ZEND_AST_CONSTANT_CLASS
|| ast->kind == ZEND_AST_CLASS_CONST) {
decode = estrdup("<constant>");
} else {
decode = estrdup("<ast>");