From ea09a9fa325fe21ebc81c41a63ab8c2f377d7f75 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 2 Apr 2015 02:05:25 +0300 Subject: [PATCH] Convert fatal errors into EngineExceptions Make zval_update_constant_ex(), zval_update_constant(), zend_update_class_constants() and zend_ast_evaluate() return SUCCESS or FAILURE. --- Zend/zend_API.c | 40 +++++--- Zend/zend_API.h | 3 +- Zend/zend_ast.c | 172 ++++++++++++++++++++++---------- Zend/zend_ast.h | 2 +- Zend/zend_builtin_functions.c | 8 +- Zend/zend_constants.c | 4 +- Zend/zend_execute.c | 5 +- Zend/zend_execute.h | 2 - Zend/zend_execute_API.c | 59 +++++------ Zend/zend_inheritance.c | 2 +- Zend/zend_interfaces.c | 4 +- Zend/zend_object_handlers.c | 4 +- Zend/zend_vm_def.h | 29 +++--- Zend/zend_vm_execute.h | 85 +++++++++------- ext/pdo/pdo_dbh.c | 16 ++- ext/pdo/pdo_stmt.c | 4 +- ext/reflection/php_reflection.c | 62 +++++++++--- ext/spl/spl_directory.c | 8 +- ext/standard/basic_functions.c | 4 +- 19 files changed, 328 insertions(+), 185 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 80af57d76a..6744ea0a76 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1119,7 +1119,7 @@ static int zval_update_class_constant(zval *pp, int is_static, uint32_t offset) int ret; zend_class_entry *old_scope = *scope; *scope = prop_info->ce; - ret = zval_update_constant(pp, 1); + ret = zval_update_constant_ex(pp, 1, NULL); *scope = old_scope; return ret; } @@ -1128,13 +1128,13 @@ static int zval_update_class_constant(zval *pp, int is_static, uint32_t offset) } while (ce); } - return zval_update_constant(pp, 1); + return zval_update_constant_ex(pp, 1, NULL); } - return 0; + return SUCCESS; } /* }}} */ -ZEND_API void zend_update_class_constants(zend_class_entry *class_type) /* {{{ */ +ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */ { int i; @@ -1143,7 +1143,9 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type) /* {{{ * zval *p; if (class_type->parent) { - zend_update_class_constants(class_type->parent); + if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) { + return FAILURE; + } } #if ZTS CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval) * class_type->default_static_members_count); @@ -1177,22 +1179,29 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type) /* {{{ * *scope = class_type; ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) { - zval_update_constant(val, 1); + if (UNEXPECTED(zval_update_constant_ex(val, 1, class_type) != SUCCESS)) { + return FAILURE; + } } ZEND_HASH_FOREACH_END(); for (i = 0; i < class_type->default_properties_count; i++) { if (Z_TYPE(class_type->default_properties_table[i]) != IS_UNDEF) { - zval_update_class_constant(&class_type->default_properties_table[i], 0, OBJ_PROP_TO_OFFSET(i)); + if (UNEXPECTED(zval_update_class_constant(&class_type->default_properties_table[i], 0, OBJ_PROP_TO_OFFSET(i)) != SUCCESS)) { + return FAILURE; + } } } for (i = 0; i < class_type->default_static_members_count; i++) { - zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i); + if (UNEXPECTED(zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i) != SUCCESS)) { + return FAILURE; + } } *scope = old_scope; class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED; } + return SUCCESS; } /* }}} */ @@ -1273,15 +1282,22 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type { if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { if (class_type->ce_flags & ZEND_ACC_INTERFACE) { - zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", class_type->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate interface %s", class_type->name->val); } else if (class_type->ce_flags & ZEND_ACC_TRAIT) { - zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", class_type->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate trait %s", class_type->name->val); } else { - zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", class_type->name->val); + zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate abstract class %s", class_type->name->val); } + ZVAL_NULL(arg); + Z_OBJ_P(arg) = NULL; + return FAILURE; } - zend_update_class_constants(class_type); + if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) { + ZVAL_NULL(arg); + Z_OBJ_P(arg) = NULL; + return FAILURE; + } if (class_type->create_object == NULL) { ZVAL_OBJ(arg, zend_objects_new(class_type)); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index b8547e685e..23ec35f00c 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -325,7 +325,8 @@ ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length); ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value); -ZEND_API void zend_update_class_constants(zend_class_entry *class_type); +ZEND_API int zend_update_class_constants(zend_class_entry *class_type); + ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value); ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, size_t name_length); ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value); diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index b8a2d45474..d538a2191f 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -177,7 +177,7 @@ ZEND_API zend_ast *zend_ast_list_add(zend_ast *ast, zend_ast *op) { return (zend_ast *) list; } -static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr) +static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr) { switch (Z_TYPE_P(offset)) { case IS_UNDEF: @@ -203,68 +203,90 @@ static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr) zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr); break; default: - zend_error_noreturn(E_ERROR, "Illegal offset type"); - break; + zend_error(E_EXCEPTION | E_ERROR, "Illegal offset type"); + return FAILURE; } + return SUCCESS; } -ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope) +ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope) { zval op1, op2; + int ret = SUCCESS; switch (ast->kind) { case ZEND_AST_BINARY_OP: - { - binary_op_type op = get_binary_op(ast->attr); - zend_ast_evaluate(&op1, ast->child[0], scope); - zend_ast_evaluate(&op2, ast->child[1], scope); - op(result, &op1, &op2); - zval_dtor(&op1); - zval_dtor(&op2); + if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { + ret = FAILURE; + } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) { + zval_dtor(&op1); + ret = FAILURE; + } else { + binary_op_type op = get_binary_op(ast->attr); + ret = op(result, &op1, &op2); + zval_dtor(&op1); + zval_dtor(&op2); + } break; - } case ZEND_AST_GREATER: case ZEND_AST_GREATER_EQUAL: - { - /* op1 > op2 is the same as op2 < op1 */ - binary_op_type op = ast->kind == ZEND_AST_GREATER - ? is_smaller_function : is_smaller_or_equal_function; - zend_ast_evaluate(&op1, ast->child[0], scope); - zend_ast_evaluate(&op2, ast->child[1], scope); - op(result, &op2, &op1); - zval_dtor(&op1); - zval_dtor(&op2); + if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { + ret = FAILURE; + } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) { + zval_dtor(&op1); + ret = FAILURE; + } else { + /* op1 > op2 is the same as op2 < op1 */ + binary_op_type op = ast->kind == ZEND_AST_GREATER + ? is_smaller_function : is_smaller_or_equal_function; + ret = op(result, &op2, &op1); + zval_dtor(&op1); + zval_dtor(&op2); + } break; - } case ZEND_AST_UNARY_OP: - { - unary_op_type op = get_unary_op(ast->attr); - zend_ast_evaluate(&op1, ast->child[0], scope); - op(result, &op1); - zval_dtor(&op1); + if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { + ret = FAILURE; + } else { + unary_op_type op = get_unary_op(ast->attr); + ret = op(result, &op1); + zval_dtor(&op1); + } break; - } case ZEND_AST_ZVAL: { zval *zv = zend_ast_get_zval(ast); if (scope) { /* class constants may be updated in-place */ if (Z_OPT_CONSTANT_P(zv)) { - zval_update_constant_ex(zv, 1, scope); + if (UNEXPECTED(zval_update_constant_ex(zv, 1, scope) != SUCCESS)) { + ret = FAILURE; + break; + } } ZVAL_DUP(result, zv); } else { ZVAL_DUP(result, zv); if (Z_OPT_CONSTANT_P(result)) { - zval_update_constant_ex(result, 1, scope); + if (UNEXPECTED(zval_update_constant_ex(result, 1, scope) != SUCCESS)) { + ret = FAILURE; + break; + } } } break; } case ZEND_AST_AND: - zend_ast_evaluate(&op1, ast->child[0], scope); + if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { + ret = FAILURE; + break; + } if (zend_is_true(&op1)) { - zend_ast_evaluate(&op2, ast->child[1], scope); + if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) { + zval_dtor(&op1); + ret = FAILURE; + break; + } ZVAL_BOOL(result, zend_is_true(&op2)); zval_dtor(&op2); } else { @@ -273,41 +295,65 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s zval_dtor(&op1); break; case ZEND_AST_OR: - zend_ast_evaluate(&op1, ast->child[0], scope); + if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { + ret = FAILURE; + break; + } if (zend_is_true(&op1)) { ZVAL_TRUE(result); } else { - zend_ast_evaluate(&op2, ast->child[1], scope); + if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) { + zval_dtor(&op1); + ret = FAILURE; + break; + } ZVAL_BOOL(result, zend_is_true(&op2)); zval_dtor(&op2); } zval_dtor(&op1); break; case ZEND_AST_CONDITIONAL: - zend_ast_evaluate(&op1, ast->child[0], scope); + if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { + ret = FAILURE; + break; + } if (zend_is_true(&op1)) { if (!ast->child[1]) { *result = op1; } else { - zend_ast_evaluate(result, ast->child[1], scope); + if (UNEXPECTED(zend_ast_evaluate(result, ast->child[1], scope) != SUCCESS)) { + zval_dtor(&op1); + ret = FAILURE; + break; + } zval_dtor(&op1); } } else { - zend_ast_evaluate(result, ast->child[2], scope); + if (UNEXPECTED(zend_ast_evaluate(result, ast->child[2], scope) != SUCCESS)) { + zval_dtor(&op1); + ret = FAILURE; + break; + } zval_dtor(&op1); } break; case ZEND_AST_UNARY_PLUS: - ZVAL_LONG(&op1, 0); - zend_ast_evaluate(&op2, ast->child[0], scope); - add_function(result, &op1, &op2); - zval_dtor(&op2); + if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) { + ret = FAILURE; + } else { + ZVAL_LONG(&op1, 0); + ret = add_function(result, &op1, &op2); + zval_dtor(&op2); + } break; case ZEND_AST_UNARY_MINUS: - ZVAL_LONG(&op1, 0); - zend_ast_evaluate(&op2, ast->child[0], scope); - sub_function(result, &op1, &op2); - zval_dtor(&op2); + if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) { + ret = FAILURE; + } else { + ZVAL_LONG(&op1, 0); + ret = sub_function(result, &op1, &op2); + zval_dtor(&op2); + } break; case ZEND_AST_ARRAY: array_init(result); @@ -317,29 +363,47 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s for (i = 0; i < list->children; i++) { zend_ast *elem = list->child[i]; if (elem->child[1]) { - zend_ast_evaluate(&op1, elem->child[1], scope); + if (UNEXPECTED(zend_ast_evaluate(&op1, elem->child[1], scope) != SUCCESS)) { + zval_dtor(result); + return FAILURE; + } } else { ZVAL_UNDEF(&op1); } - zend_ast_evaluate(&op2, elem->child[0], scope); - zend_ast_add_array_element(result, &op1, &op2); + if (UNEXPECTED(zend_ast_evaluate(&op2, elem->child[0], scope) != SUCCESS)) { + zval_dtor(&op1); + zval_dtor(result); + return FAILURE; + } + if (UNEXPECTED(zend_ast_add_array_element(result, &op1, &op2) != SUCCESS)) { + zval_dtor(&op1); + zval_dtor(&op2); + zval_dtor(result); + return FAILURE; + } } } break; case ZEND_AST_DIM: - zend_ast_evaluate(&op1, ast->child[0], scope); - zend_ast_evaluate(&op2, ast->child[1], scope); - { + if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) { + ret = FAILURE; + } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) { + zval_dtor(&op1); + ret = FAILURE; + } else { zval tmp; + zend_fetch_dimension_by_zval(&tmp, &op1, &op2); ZVAL_ZVAL(result, &tmp, 1, 1); + zval_dtor(&op1); + zval_dtor(&op2); } - zval_dtor(&op1); - zval_dtor(&op2); break; default: - zend_error_noreturn(E_ERROR, "Unsupported constant expression"); + zend_error(E_EXCEPTION | E_ERROR, "Unsupported constant expression"); + ret = FAILURE; } + return ret; } ZEND_API zend_ast *zend_ast_copy(zend_ast *ast) diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 8cd06419be..553578f848 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -203,7 +203,7 @@ ZEND_API zend_ast *zend_ast_create_decl( ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...); ZEND_API zend_ast *zend_ast_list_add(zend_ast *list, zend_ast *op); -ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope); +ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope); ZEND_API zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix); ZEND_API zend_ast *zend_ast_copy(zend_ast *ast); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 275fcf9cff..0d9e3c002c 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1075,7 +1075,9 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value /* this is necessary to make it able to work with default array * properties, returned to user */ if (Z_OPT_CONSTANT_P(prop)) { - zval_update_constant(prop, 0); + if (UNEXPECTED(zval_update_constant_ex(prop, 0, NULL) != SUCCESS)) { + return; + } } zend_hash_add_new(Z_ARRVAL_P(return_value), key, prop); @@ -1099,7 +1101,9 @@ ZEND_FUNCTION(get_class_vars) RETURN_FALSE; } else { array_init(return_value); - zend_update_class_constants(ce); + if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { + return; + } add_class_vars(ce, 0, return_value); add_class_vars(ce, 1, return_value); } diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index da842364be..32f249ce08 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -375,7 +375,9 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, zend_string_release(class_name); zend_string_free(constant_name); if (ret_constant && Z_CONSTANT_P(ret_constant)) { - zval_update_constant_ex(ret_constant, 1, ce); + if (UNEXPECTED(zval_update_constant_ex(ret_constant, 1, ce) != SUCCESS)) { + return NULL; + } } return ret_constant; } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 06c25c7bc1..424f4888e9 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -629,7 +629,9 @@ static int is_null_constant(zval *default_value) zval constant; ZVAL_COPY_VALUE(&constant, default_value); - zval_update_constant(&constant, 0); + if (UNEXPECTED(zval_update_constant_ex(&constant, 0, NULL) != SUCCESS)) { + return 0; + } if (Z_TYPE(constant) == IS_NULL) { return 1; } @@ -1714,7 +1716,6 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_offset, const zend_op_array *op_array, const zend_execute_data *execute_data) { - int original_nest_levels = nest_levels; zend_brk_cont_element *jmp_to; do { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 239185ccb7..dce9e1c040 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -113,8 +113,6 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval } ZEND_API int zval_update_constant(zval *pp, zend_bool inline_change); -ZEND_API int zval_update_constant_inline_change(zval *pp, zend_class_entry *scope); -ZEND_API int zval_update_constant_no_inline_change(zval *pp, zend_class_entry *scope); ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope); /* dedicated Zend executor functions - do not use! */ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 705eea0668..995850ff62 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -520,6 +520,7 @@ ZEND_API void _zval_internal_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ * #define IS_VISITED_CONSTANT 0x80 #define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT) #define MARK_CONSTANT_VISITED(p) Z_TYPE_INFO_P(p) |= IS_VISITED_CONSTANT +#define RESET_CONSTANT_VISITED(p) Z_TYPE_INFO_P(p) &= ~IS_VISITED_CONSTANT ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_class_entry *scope) /* {{{ */ { @@ -527,7 +528,8 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas char *colon; if (IS_CONSTANT_VISITED(p)) { - zend_error_noreturn(E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p)); + zend_error(E_EXCEPTION | E_ERROR, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p)); + return FAILURE; } else if (Z_TYPE_P(p) == IS_CONSTANT) { int refcount; @@ -544,22 +546,18 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas } else { ZVAL_EMPTY_STRING(p); } - } else if ((const_value = zend_get_constant_ex(Z_STR_P(p), scope, Z_CONST_FLAGS_P(p))) == NULL) { + } else if (UNEXPECTED((const_value = zend_get_constant_ex(Z_STR_P(p), scope, Z_CONST_FLAGS_P(p))) == NULL)) { char *actual = Z_STRVAL_P(p); - if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) { + if (UNEXPECTED(EG(exception))) { + RESET_CONSTANT_VISITED(p); + return FAILURE; + } else if ((colon = (char*)zend_memrchr(Z_STRVAL_P(p), ':', Z_STRLEN_P(p)))) { size_t len; - zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p)); - len = Z_STRLEN_P(p) - ((colon - Z_STRVAL_P(p)) + 1); - if (inline_change) { - zend_string *tmp = zend_string_init(colon + 1, len, 0); - zend_string_release(Z_STR_P(p)); - Z_STR_P(p) = tmp; - } else { - Z_STR_P(p) = zend_string_init(colon + 1, len, 0); - } - Z_TYPE_FLAGS_P(p) = IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE; + zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p)); + RESET_CONSTANT_VISITED(p); + return FAILURE; } else { zend_string *save = Z_STR_P(p); char *slash; @@ -584,14 +582,15 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas } if ((Z_CONST_FLAGS_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) { if (save->val[0] == '\\') { - zend_error_noreturn(E_ERROR, "Undefined constant '%s'", save->val + 1); + zend_error(E_EXCEPTION | E_ERROR, "Undefined constant '%s'", save->val + 1); } else { - zend_error_noreturn(E_ERROR, "Undefined constant '%s'", save->val); + zend_error(E_EXCEPTION | E_ERROR, "Undefined constant '%s'", save->val); } if (inline_change) { zend_string_release(save); } - save = NULL; + RESET_CONSTANT_VISITED(p); + return FAILURE; } else { zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual); if (!inline_change) { @@ -611,7 +610,10 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas } ZVAL_COPY_VALUE(p, const_value); if (Z_OPT_CONSTANT_P(p)) { - zval_update_constant_ex(p, 1, NULL); + if (UNEXPECTED(zval_update_constant_ex(p, 1, NULL) != SUCCESS)) { + RESET_CONSTANT_VISITED(p); + return FAILURE; + } } zval_opt_copy_ctor(p); } @@ -619,29 +621,16 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount); } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) { zval tmp; - if (inline_change) { - SEPARATE_ZVAL_NOREF(p); + + if (UNEXPECTED(zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope) != SUCCESS)) { + return FAILURE; } - zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope); if (inline_change) { - zend_ast_destroy_and_free(Z_ASTVAL_P(p)); - efree_size(Z_AST_P(p), sizeof(zend_ast_ref)); + zval_ptr_dtor(p); } ZVAL_COPY_VALUE(p, &tmp); } - return 0; -} -/* }}} */ - -ZEND_API int zval_update_constant_inline_change(zval *pp, zend_class_entry *scope) /* {{{ */ -{ - return zval_update_constant_ex(pp, 1, scope); -} -/* }}} */ - -ZEND_API int zval_update_constant_no_inline_change(zval *pp, zend_class_entry *scope) /* {{{ */ -{ - return zval_update_constant_ex(pp, 0, scope); + return SUCCESS; } /* }}} */ diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index bd4fc373e0..e203599aea 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -772,7 +772,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent if (parent_ce->type != ce->type) { /* User class extends internal class */ - zend_update_class_constants(parent_ce ); + zend_update_class_constants(parent_ce); if (parent_ce->default_static_members_count) { int i = ce->default_static_members_count + parent_ce->default_static_members_count; diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 28f651cc85..93c0209a96 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -447,7 +447,9 @@ ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const uns { zval zdata; - object_init_ex(object, ce); + if (UNEXPECTED(object_init_ex(object, ce) != SUCCESS)) { + return FAILURE; + } ZVAL_STRINGL(&zdata, (char*)buf, buf_len); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 07d5039961..1ce666b719 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1314,7 +1314,9 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p goto undeclared_property; } - zend_update_class_constants(ce); + if (UNEXPECTED(zend_update_class_constants(ce)) != SUCCESS) { + return NULL; + } ret = CE_STATIC_MEMBERS(ce) + property_info->offset; /* check if static properties were destoyed */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 901629f834..57e77375b3 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1576,7 +1576,10 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V } if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1); + if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { + FREE_OP1(); + HANDLE_EXCEPTION(); + } } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { FREE_OP1(); @@ -4538,7 +4541,10 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST) if (arg_num > EX_NUM_ARGS()) { ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2)); if (Z_OPT_CONSTANT_P(param)) { - zval_update_constant(param, 0); + if (UNEXPECTED(zval_update_constant_ex(param, 0, NULL) != SUCCESS)) { + ZVAL_UNDEF(param); + HANDLE_EXCEPTION(); + } } else { /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) { @@ -4751,17 +4757,9 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY) } else { ce = Z_CE_P(EX_VAR(opline->op1.var)); } - if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { - if (ce->ce_flags & ZEND_ACC_INTERFACE) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate interface %s", ce->name->val); - } else if (ce->ce_flags & ZEND_ACC_TRAIT) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate trait %s", ce->name->val); - } else { - zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); - } + if (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) { HANDLE_EXCEPTION(); } - object_init_ex(&object_zval, ce); constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); if (constructor == NULL) { @@ -4949,7 +4947,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) ZVAL_DEREF(value); if (Z_CONSTANT_P(value)) { EG(scope) = ce; - zval_update_constant(value, 1); + zval_update_constant_ex(value, 1, NULL); EG(scope) = EX(func)->op_array.scope; } if (OP1_TYPE == IS_CONST) { @@ -4963,7 +4961,6 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); - HANDLE_EXCEPTION(); } } ZEND_VM_C_LABEL(constant_fetch_end): @@ -7065,7 +7062,11 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST) ZVAL_COPY_VALUE(&c.value, val); if (Z_OPT_CONSTANT(c.value)) { - zval_update_constant(&c.value, 0); + if (UNEXPECTED(zval_update_constant_ex(&c.value, 0, NULL) != SUCCESS)) { + FREE_OP1(); + FREE_OP2(); + HANDLE_EXCEPTION(); + } } else { /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ if (UNEXPECTED(Z_OPT_COPYABLE(c.value))) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index aa3c392510..a99e13456a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2076,7 +2076,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(Z if (arg_num > EX_NUM_ARGS()) { ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2)); if (Z_OPT_CONSTANT_P(param)) { - zval_update_constant(param, 0); + if (UNEXPECTED(zval_update_constant_ex(param, 0, NULL) != SUCCESS)) { + ZVAL_UNDEF(param); + HANDLE_EXCEPTION(); + } } else { /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) { @@ -3079,17 +3082,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OP } else { ce = Z_CE_P(EX_VAR(opline->op1.var)); } - if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { - if (ce->ce_flags & ZEND_ACC_INTERFACE) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate interface %s", ce->name->val); - } else if (ce->ce_flags & ZEND_ACC_TRAIT) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate trait %s", ce->name->val); - } else { - zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); - } + if (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) { HANDLE_EXCEPTION(); } - object_init_ex(&object_zval, ce); constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); if (constructor == NULL) { @@ -4604,7 +4599,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1); + if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { + + HANDLE_EXCEPTION(); + } } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { @@ -5325,7 +5323,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONS ZVAL_DEREF(value); if (Z_CONSTANT_P(value)) { EG(scope) = ce; - zval_update_constant(value, 1); + zval_update_constant_ex(value, 1, NULL); EG(scope) = EX(func)->op_array.scope; } if (IS_CONST == IS_CONST) { @@ -5339,7 +5337,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONS ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); - HANDLE_EXCEPTION(); } } constant_fetch_end: @@ -5830,7 +5827,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST ZVAL_COPY_VALUE(&c.value, val); if (Z_OPT_CONSTANT(c.value)) { - zval_update_constant(&c.value, 0); + if (UNEXPECTED(zval_update_constant_ex(&c.value, 0, NULL) != SUCCESS)) { + + + HANDLE_EXCEPTION(); + } } else { /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ if (UNEXPECTED(Z_OPT_COPYABLE(c.value))) { @@ -6322,7 +6323,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1); + if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { + + HANDLE_EXCEPTION(); + } } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { @@ -6822,7 +6826,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1); + if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { + + HANDLE_EXCEPTION(); + } } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { @@ -13901,17 +13908,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCO } else { ce = Z_CE_P(EX_VAR(opline->op1.var)); } - if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) { - if (ce->ce_flags & ZEND_ACC_INTERFACE) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate interface %s", ce->name->val); - } else if (ce->ce_flags & ZEND_ACC_TRAIT) { - zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate trait %s", ce->name->val); - } else { - zend_error(E_EXCEPTION | E_ERROR, "Cannot instantiate abstract class %s", ce->name->val); - } + if (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) { HANDLE_EXCEPTION(); } - object_init_ex(&object_zval, ce); constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); if (constructor == NULL) { @@ -16158,7 +16157,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_ ZVAL_DEREF(value); if (Z_CONSTANT_P(value)) { EG(scope) = ce; - zval_update_constant(value, 1); + zval_update_constant_ex(value, 1, NULL); EG(scope) = EX(func)->op_array.scope; } if (IS_VAR == IS_CONST) { @@ -16172,7 +16171,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_ ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); - HANDLE_EXCEPTION(); } } constant_fetch_end: @@ -22440,7 +22438,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON ZVAL_DEREF(value); if (Z_CONSTANT_P(value)) { EG(scope) = ce; - zval_update_constant(value, 1); + zval_update_constant_ex(value, 1, NULL); EG(scope) = EX(func)->op_array.scope; } if (IS_UNUSED == IS_CONST) { @@ -22454,7 +22452,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name); } else { zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); - HANDLE_EXCEPTION(); } } constant_fetch_end: @@ -29456,7 +29453,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1); + if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { + + HANDLE_EXCEPTION(); + } } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { @@ -31563,7 +31563,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1); + if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { + + HANDLE_EXCEPTION(); + } } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { @@ -32497,7 +32500,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1); + if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { + + HANDLE_EXCEPTION(); + } } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { @@ -39458,7 +39464,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1); + if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { zval_ptr_dtor_nogc(free_op1); @@ -40382,7 +40391,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1); + if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { zval_ptr_dtor_nogc(free_op1); @@ -40789,7 +40801,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { if (Z_CONSTANT_P(retval)) { - zval_update_constant(retval, 1); + if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { + zval_ptr_dtor_nogc(free_op1); + HANDLE_EXCEPTION(); + } } } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { zval_ptr_dtor_nogc(free_op1); diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index ed541543f9..41d3974b72 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -424,7 +424,9 @@ static zval *pdo_stmt_instantiate(pdo_dbh_t *dbh, zval *object, zend_class_entry } } - object_init_ex(object, dbstmt_ce); + if (UNEXPECTED(object_init_ex(object, dbstmt_ce) != SUCCESS)) { + return NULL; + } // ??? Z_SET_REFCOUNT_P(object, 1); //Z_SET_ISREF_P(object); @@ -538,9 +540,11 @@ static PHP_METHOD(PDO, prepare) } if (!pdo_stmt_instantiate(dbh, return_value, dbstmt_ce, &ctor_args)) { - pdo_raise_impl_error(dbh, NULL, "HY000", - "failed to instantiate user-supplied statement class" - ); + if (EXPECTED(!EG(exception))) { + pdo_raise_impl_error(dbh, NULL, "HY000", + "failed to instantiate user-supplied statement class" + ); + } PDO_HANDLE_DBH_ERR(); RETURN_FALSE; } @@ -1077,7 +1081,9 @@ static PHP_METHOD(PDO, query) PDO_CONSTRUCT_CHECK; if (!pdo_stmt_instantiate(dbh, return_value, dbh->def_stmt_ce, &dbh->def_stmt_ctor_args)) { - pdo_raise_impl_error(dbh, NULL, "HY000", "failed to instantiate user supplied statement class"); + if (EXPECTED(!EG(exception))) { + pdo_raise_impl_error(dbh, NULL, "HY000", "failed to instantiate user supplied statement class"); + } return; } stmt = Z_PDO_STMT_P(return_value); diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index d221c9ed22..346aba7eb0 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -945,7 +945,9 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_ return 0; } if ((flags & PDO_FETCH_SERIALIZE) == 0) { - object_init_ex(return_value, ce); + if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) { + return 0; + } if (!stmt->fetch.cls.fci.size) { if (!do_fetch_class_prepare(stmt)) { diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 4dc0ed6868..b4dd978f08 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -428,7 +428,6 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in /* Constants */ if (&ce->constants_table) { - zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1); string_printf(str, "\n"); count = zend_hash_num_elements(&ce->constants_table); string_printf(str, "%s - Constants [%d] {\n", indent, count); @@ -437,6 +436,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zval *value; ZEND_HASH_FOREACH_STR_KEY_VAL(&ce->constants_table, key, value) { + zval_update_constant_ex(value, 1, NULL); _const_string(str, key->val, value, indent); } ZEND_HASH_FOREACH_END(); } @@ -1851,6 +1851,7 @@ ZEND_METHOD(reflection_function, getStaticVariables) { reflection_object *intern; zend_function *fptr; + zval *val; if (zend_parse_parameters_none() == FAILURE) { return; @@ -1866,7 +1867,11 @@ ZEND_METHOD(reflection_function, getStaticVariables) } fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables); } - zend_hash_apply_with_argument(fptr->op_array.static_variables, (apply_func_arg_t) zval_update_constant_inline_change, fptr->common.scope); + ZEND_HASH_FOREACH_VAL(fptr->op_array.static_variables, val) { + if (UNEXPECTED(zval_update_constant_ex(val, 1, fptr->common.scope) != SUCCESS)) { + return; + } + } ZEND_HASH_FOREACH_END(); zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, zval_add_ref); } } @@ -3430,7 +3435,9 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value /* this is necessary to make it able to work with default array * properties, returned to user */ if (Z_CONSTANT(prop_copy)) { - zval_update_constant(&prop_copy, 1); + if (UNEXPECTED(zval_update_constant_ex(&prop_copy, 1, NULL) != SUCCESS)) { + return; + } } zend_hash_update(Z_ARRVAL_P(return_value), key, &prop_copy); @@ -3451,7 +3458,9 @@ ZEND_METHOD(reflection_class, getStaticProperties) GET_REFLECTION_OBJECT_PTR(ce); - zend_update_class_constants(ce); + if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { + return; + } array_init(return_value); add_class_vars(ce, 1, return_value); @@ -3473,7 +3482,9 @@ ZEND_METHOD(reflection_class, getStaticPropertyValue) GET_REFLECTION_OBJECT_PTR(ce); - zend_update_class_constants(ce); + if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { + return; + } prop = zend_std_get_static_property(ce, name, 1); if (!prop) { if (def_value) { @@ -3504,7 +3515,9 @@ ZEND_METHOD(reflection_class, setStaticPropertyValue) GET_REFLECTION_OBJECT_PTR(ce); - zend_update_class_constants(ce); + if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { + return; + } variable_ptr = zend_std_get_static_property(ce, name, 1); if (!variable_ptr) { zend_throw_exception_ex(reflection_exception_ptr, 0, @@ -3528,7 +3541,9 @@ ZEND_METHOD(reflection_class, getDefaultProperties) } GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); - zend_update_class_constants(ce); + if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { + return; + } add_class_vars(ce, 1, return_value); add_class_vars(ce, 0, return_value); } @@ -4049,13 +4064,18 @@ ZEND_METHOD(reflection_class, getConstants) { reflection_object *intern; zend_class_entry *ce; + zval *val; if (zend_parse_parameters_none() == FAILURE) { return; } GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); - zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t)zval_update_constant_inline_change, ce); + ZEND_HASH_FOREACH_VAL(&ce->constants_table, val) { + if (UNEXPECTED(zval_update_constant_ex(val, 1, ce) != SUCCESS)) { + return; + } + } ZEND_HASH_FOREACH_END(); zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, zval_add_ref_unref); } /* }}} */ @@ -4075,7 +4095,11 @@ ZEND_METHOD(reflection_class, getConstant) } GET_REFLECTION_OBJECT_PTR(ce); - zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t)zval_update_constant_inline_change, ce); + ZEND_HASH_FOREACH_VAL(&ce->constants_table, value) { + if (UNEXPECTED(zval_update_constant_ex(value, 1, ce) != SUCCESS)) { + return; + } + } ZEND_HASH_FOREACH_END(); if ((value = zend_hash_find(&ce->constants_table, name)) == NULL) { RETURN_FALSE; } @@ -4147,7 +4171,9 @@ ZEND_METHOD(reflection_class, isCloneable) if (ce->clone) { RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC); } else { - object_init_ex(&obj, ce); + if (UNEXPECTED(object_init_ex(&obj, ce) != SUCCESS)) { + return; + } RETVAL_BOOL(Z_OBJ_HANDLER(obj, clone_obj) != NULL); zval_dtor(&obj); } @@ -4232,7 +4258,9 @@ ZEND_METHOD(reflection_class, newInstance) METHOD_NOTSTATIC(reflection_class_ptr); GET_REFLECTION_OBJECT_PTR(ce); - object_init_ex(return_value, ce); + if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) { + return; + } old_scope = EG(scope); EG(scope) = ce; @@ -4334,7 +4362,9 @@ ZEND_METHOD(reflection_class, newInstanceArgs) argc = args->nNumOfElements; } - object_init_ex(return_value, ce); + if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) { + return; + } old_scope = EG(scope); EG(scope) = ce; @@ -5012,7 +5042,9 @@ ZEND_METHOD(reflection_property, getValue) } if ((ref->prop.flags & ZEND_ACC_STATIC)) { - zend_update_class_constants(intern->ce); + if (UNEXPECTED(zend_update_class_constants(intern->ce) != SUCCESS)) { + return; + } if (Z_TYPE(CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) == IS_UNDEF) { php_error_docref(NULL, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name->val, ref->prop.name->val); /* Bails out */ @@ -5061,7 +5093,9 @@ ZEND_METHOD(reflection_property, setValue) return; } } - zend_update_class_constants(intern->ce); + if (UNEXPECTED(zend_update_class_constants(intern->ce) != SUCCESS)) { + return; + } if (Z_TYPE(CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) == IS_UNDEF) { php_error_docref(NULL, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name->val, ref->prop.name->val); diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 9e51626cbd..b91e8b0558 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -480,7 +480,9 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int ht, spl_file case SPL_FS_INFO: ce = ce ? ce : source->info_class; - zend_update_class_constants(ce); + if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { + break; + } intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce)); ZVAL_OBJ(return_value, &intern->std); @@ -500,7 +502,9 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int ht, spl_file case SPL_FS_FILE: ce = ce ? ce : source->file_class; - zend_update_class_constants(ce); + if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) { + break; + } intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce)); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 7bf51eb5d5..36d530d47b 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -3827,7 +3827,9 @@ PHP_FUNCTION(constant) if (c) { ZVAL_COPY_VALUE(return_value, c); if (Z_CONSTANT_P(return_value)) { - zval_update_constant_ex(return_value, 1, NULL); + if (UNEXPECTED(zval_update_constant_ex(return_value, 1, NULL) != SUCCESS)) { + return; + } } zval_copy_ctor(return_value); } else { -- 2.40.0