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.
This commit is contained in:
Dmitry Stogov 2015-04-02 02:05:25 +03:00
parent 956fa034e3
commit ea09a9fa32
19 changed files with 328 additions and 185 deletions

View file

@ -1119,7 +1119,7 @@ static int zval_update_class_constant(zval *pp, int is_static, uint32_t offset)
int ret; int ret;
zend_class_entry *old_scope = *scope; zend_class_entry *old_scope = *scope;
*scope = prop_info->ce; *scope = prop_info->ce;
ret = zval_update_constant(pp, 1); ret = zval_update_constant_ex(pp, 1, NULL);
*scope = old_scope; *scope = old_scope;
return ret; return ret;
} }
@ -1128,13 +1128,13 @@ static int zval_update_class_constant(zval *pp, int is_static, uint32_t offset)
} while (ce); } 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; int i;
@ -1143,7 +1143,9 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type) /* {{{ *
zval *p; zval *p;
if (class_type->parent) { 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 #if ZTS
CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval) * class_type->default_static_members_count); 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; *scope = class_type;
ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) { 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(); } ZEND_HASH_FOREACH_END();
for (i = 0; i < class_type->default_properties_count; i++) { for (i = 0; i < class_type->default_properties_count; i++) {
if (Z_TYPE(class_type->default_properties_table[i]) != IS_UNDEF) { 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++) { 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; *scope = old_scope;
class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED; 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_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
if (class_type->ce_flags & ZEND_ACC_INTERFACE) { 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) { } 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 { } 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) { if (class_type->create_object == NULL) {
ZVAL_OBJ(arg, zend_objects_new(class_type)); ZVAL_OBJ(arg, zend_objects_new(class_type));

View file

@ -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_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 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(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_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); ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value);

View file

@ -177,7 +177,7 @@ ZEND_API zend_ast *zend_ast_list_add(zend_ast *ast, zend_ast *op) {
return (zend_ast *) list; 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)) { switch (Z_TYPE_P(offset)) {
case IS_UNDEF: 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); zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr);
break; break;
default: default:
zend_error_noreturn(E_ERROR, "Illegal offset type"); zend_error(E_EXCEPTION | E_ERROR, "Illegal offset type");
break; 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; zval op1, op2;
int ret = SUCCESS;
switch (ast->kind) { switch (ast->kind) {
case ZEND_AST_BINARY_OP: case ZEND_AST_BINARY_OP:
{ if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
binary_op_type op = get_binary_op(ast->attr); ret = FAILURE;
zend_ast_evaluate(&op1, ast->child[0], scope); } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
zend_ast_evaluate(&op2, ast->child[1], scope); zval_dtor(&op1);
op(result, &op1, &op2); ret = FAILURE;
zval_dtor(&op1); } else {
zval_dtor(&op2); binary_op_type op = get_binary_op(ast->attr);
ret = op(result, &op1, &op2);
zval_dtor(&op1);
zval_dtor(&op2);
}
break; break;
}
case ZEND_AST_GREATER: case ZEND_AST_GREATER:
case ZEND_AST_GREATER_EQUAL: case ZEND_AST_GREATER_EQUAL:
{ if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
/* op1 > op2 is the same as op2 < op1 */ ret = FAILURE;
binary_op_type op = ast->kind == ZEND_AST_GREATER } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
? is_smaller_function : is_smaller_or_equal_function; zval_dtor(&op1);
zend_ast_evaluate(&op1, ast->child[0], scope); ret = FAILURE;
zend_ast_evaluate(&op2, ast->child[1], scope); } else {
op(result, &op2, &op1); /* op1 > op2 is the same as op2 < op1 */
zval_dtor(&op1); binary_op_type op = ast->kind == ZEND_AST_GREATER
zval_dtor(&op2); ? is_smaller_function : is_smaller_or_equal_function;
ret = op(result, &op2, &op1);
zval_dtor(&op1);
zval_dtor(&op2);
}
break; break;
}
case ZEND_AST_UNARY_OP: case ZEND_AST_UNARY_OP:
{ if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
unary_op_type op = get_unary_op(ast->attr); ret = FAILURE;
zend_ast_evaluate(&op1, ast->child[0], scope); } else {
op(result, &op1); unary_op_type op = get_unary_op(ast->attr);
zval_dtor(&op1); ret = op(result, &op1);
zval_dtor(&op1);
}
break; break;
}
case ZEND_AST_ZVAL: case ZEND_AST_ZVAL:
{ {
zval *zv = zend_ast_get_zval(ast); zval *zv = zend_ast_get_zval(ast);
if (scope) { if (scope) {
/* class constants may be updated in-place */ /* class constants may be updated in-place */
if (Z_OPT_CONSTANT_P(zv)) { 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); ZVAL_DUP(result, zv);
} else { } else {
ZVAL_DUP(result, zv); ZVAL_DUP(result, zv);
if (Z_OPT_CONSTANT_P(result)) { 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; break;
} }
case ZEND_AST_AND: 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)) { 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_BOOL(result, zend_is_true(&op2));
zval_dtor(&op2); zval_dtor(&op2);
} else { } else {
@ -273,41 +295,65 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s
zval_dtor(&op1); zval_dtor(&op1);
break; break;
case ZEND_AST_OR: 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)) { if (zend_is_true(&op1)) {
ZVAL_TRUE(result); ZVAL_TRUE(result);
} else { } 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_BOOL(result, zend_is_true(&op2));
zval_dtor(&op2); zval_dtor(&op2);
} }
zval_dtor(&op1); zval_dtor(&op1);
break; break;
case ZEND_AST_CONDITIONAL: 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 (zend_is_true(&op1)) {
if (!ast->child[1]) { if (!ast->child[1]) {
*result = op1; *result = op1;
} else { } 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); zval_dtor(&op1);
} }
} else { } 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); zval_dtor(&op1);
} }
break; break;
case ZEND_AST_UNARY_PLUS: case ZEND_AST_UNARY_PLUS:
ZVAL_LONG(&op1, 0); if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
zend_ast_evaluate(&op2, ast->child[0], scope); ret = FAILURE;
add_function(result, &op1, &op2); } else {
zval_dtor(&op2); ZVAL_LONG(&op1, 0);
ret = add_function(result, &op1, &op2);
zval_dtor(&op2);
}
break; break;
case ZEND_AST_UNARY_MINUS: case ZEND_AST_UNARY_MINUS:
ZVAL_LONG(&op1, 0); if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
zend_ast_evaluate(&op2, ast->child[0], scope); ret = FAILURE;
sub_function(result, &op1, &op2); } else {
zval_dtor(&op2); ZVAL_LONG(&op1, 0);
ret = sub_function(result, &op1, &op2);
zval_dtor(&op2);
}
break; break;
case ZEND_AST_ARRAY: case ZEND_AST_ARRAY:
array_init(result); 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++) { for (i = 0; i < list->children; i++) {
zend_ast *elem = list->child[i]; zend_ast *elem = list->child[i];
if (elem->child[1]) { 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 { } else {
ZVAL_UNDEF(&op1); ZVAL_UNDEF(&op1);
} }
zend_ast_evaluate(&op2, elem->child[0], scope); if (UNEXPECTED(zend_ast_evaluate(&op2, elem->child[0], scope) != SUCCESS)) {
zend_ast_add_array_element(result, &op1, &op2); 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; break;
case ZEND_AST_DIM: case ZEND_AST_DIM:
zend_ast_evaluate(&op1, ast->child[0], scope); if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
zend_ast_evaluate(&op2, ast->child[1], scope); ret = FAILURE;
{ } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
zval_dtor(&op1);
ret = FAILURE;
} else {
zval tmp; zval tmp;
zend_fetch_dimension_by_zval(&tmp, &op1, &op2); zend_fetch_dimension_by_zval(&tmp, &op1, &op2);
ZVAL_ZVAL(result, &tmp, 1, 1); ZVAL_ZVAL(result, &tmp, 1, 1);
zval_dtor(&op1);
zval_dtor(&op2);
} }
zval_dtor(&op1);
zval_dtor(&op2);
break; break;
default: 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) ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)

View file

@ -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_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 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_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix);
ZEND_API zend_ast *zend_ast_copy(zend_ast *ast); ZEND_API zend_ast *zend_ast_copy(zend_ast *ast);

View file

@ -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 /* this is necessary to make it able to work with default array
* properties, returned to user */ * properties, returned to user */
if (Z_OPT_CONSTANT_P(prop)) { 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); zend_hash_add_new(Z_ARRVAL_P(return_value), key, prop);
@ -1099,7 +1101,9 @@ ZEND_FUNCTION(get_class_vars)
RETURN_FALSE; RETURN_FALSE;
} else { } else {
array_init(return_value); 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, 0, return_value);
add_class_vars(ce, 1, return_value); add_class_vars(ce, 1, return_value);
} }

View file

@ -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_release(class_name);
zend_string_free(constant_name); zend_string_free(constant_name);
if (ret_constant && Z_CONSTANT_P(ret_constant)) { 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; return ret_constant;
} }

View file

@ -629,7 +629,9 @@ static int is_null_constant(zval *default_value)
zval constant; zval constant;
ZVAL_COPY_VALUE(&constant, default_value); 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) { if (Z_TYPE(constant) == IS_NULL) {
return 1; 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) 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; zend_brk_cont_element *jmp_to;
do { do {

View file

@ -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(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); ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope);
/* dedicated Zend executor functions - do not use! */ /* dedicated Zend executor functions - do not use! */

View file

@ -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_VISITED_CONSTANT 0x80
#define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT) #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 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) /* {{{ */ 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; char *colon;
if (IS_CONSTANT_VISITED(p)) { 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) { } else if (Z_TYPE_P(p) == IS_CONSTANT) {
int refcount; int refcount;
@ -544,22 +546,18 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas
} else { } else {
ZVAL_EMPTY_STRING(p); 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); 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; size_t len;
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p)); zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(p));
len = Z_STRLEN_P(p) - ((colon - Z_STRVAL_P(p)) + 1); RESET_CONSTANT_VISITED(p);
if (inline_change) { return FAILURE;
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;
} else { } else {
zend_string *save = Z_STR_P(p); zend_string *save = Z_STR_P(p);
char *slash; 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 ((Z_CONST_FLAGS_P(p) & IS_CONSTANT_UNQUALIFIED) == 0) {
if (save->val[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 { } 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) { if (inline_change) {
zend_string_release(save); zend_string_release(save);
} }
save = NULL; RESET_CONSTANT_VISITED(p);
return FAILURE;
} else { } else {
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual); zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual);
if (!inline_change) { 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); ZVAL_COPY_VALUE(p, const_value);
if (Z_OPT_CONSTANT_P(p)) { 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); 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); if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount);
} else if (Z_TYPE_P(p) == IS_CONSTANT_AST) { } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
zval tmp; 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) { if (inline_change) {
zend_ast_destroy_and_free(Z_ASTVAL_P(p)); zval_ptr_dtor(p);
efree_size(Z_AST_P(p), sizeof(zend_ast_ref));
} }
ZVAL_COPY_VALUE(p, &tmp); ZVAL_COPY_VALUE(p, &tmp);
} }
return 0; return SUCCESS;
}
/* }}} */
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);
} }
/* }}} */ /* }}} */

View file

@ -772,7 +772,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
if (parent_ce->type != ce->type) { if (parent_ce->type != ce->type) {
/* User class extends internal class */ /* User class extends internal class */
zend_update_class_constants(parent_ce ); zend_update_class_constants(parent_ce);
if (parent_ce->default_static_members_count) { if (parent_ce->default_static_members_count) {
int i = ce->default_static_members_count + parent_ce->default_static_members_count; int i = ce->default_static_members_count + parent_ce->default_static_members_count;

View file

@ -447,7 +447,9 @@ ZEND_API int zend_user_unserialize(zval *object, zend_class_entry *ce, const uns
{ {
zval zdata; zval zdata;
object_init_ex(object, ce); if (UNEXPECTED(object_init_ex(object, ce) != SUCCESS)) {
return FAILURE;
}
ZVAL_STRINGL(&zdata, (char*)buf, buf_len); ZVAL_STRINGL(&zdata, (char*)buf, buf_len);

View file

@ -1314,7 +1314,9 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p
goto undeclared_property; 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; ret = CE_STATIC_MEMBERS(ce) + property_info->offset;
/* check if static properties were destoyed */ /* check if static properties were destoyed */

View file

@ -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 ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
if (Z_CONSTANT_P(retval)) { 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) { } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
FREE_OP1(); FREE_OP1();
@ -4538,7 +4541,10 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
if (arg_num > EX_NUM_ARGS()) { if (arg_num > EX_NUM_ARGS()) {
ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2)); ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2));
if (Z_OPT_CONSTANT_P(param)) { 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 { } else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) { if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) {
@ -4751,17 +4757,9 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
} else { } else {
ce = Z_CE_P(EX_VAR(opline->op1.var)); 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 (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) {
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);
}
HANDLE_EXCEPTION(); HANDLE_EXCEPTION();
} }
object_init_ex(&object_zval, ce);
constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval));
if (constructor == NULL) { if (constructor == NULL) {
@ -4949,7 +4947,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
ZVAL_DEREF(value); ZVAL_DEREF(value);
if (Z_CONSTANT_P(value)) { if (Z_CONSTANT_P(value)) {
EG(scope) = ce; EG(scope) = ce;
zval_update_constant(value, 1); zval_update_constant_ex(value, 1, NULL);
EG(scope) = EX(func)->op_array.scope; EG(scope) = EX(func)->op_array.scope;
} }
if (OP1_TYPE == IS_CONST) { 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); ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
} else { } else {
zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); 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): 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); ZVAL_COPY_VALUE(&c.value, val);
if (Z_OPT_CONSTANT(c.value)) { 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 { } else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE(c.value))) { if (UNEXPECTED(Z_OPT_COPYABLE(c.value))) {

View file

@ -2076,7 +2076,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(Z
if (arg_num > EX_NUM_ARGS()) { if (arg_num > EX_NUM_ARGS()) {
ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2)); ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2));
if (Z_OPT_CONSTANT_P(param)) { 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 { } else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) { 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 { } else {
ce = Z_CE_P(EX_VAR(opline->op1.var)); 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 (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) {
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);
}
HANDLE_EXCEPTION(); HANDLE_EXCEPTION();
} }
object_init_ex(&object_zval, ce);
constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval));
if (constructor == NULL) { 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 ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
if (Z_CONSTANT_P(retval)) { 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) { } 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); ZVAL_DEREF(value);
if (Z_CONSTANT_P(value)) { if (Z_CONSTANT_P(value)) {
EG(scope) = ce; EG(scope) = ce;
zval_update_constant(value, 1); zval_update_constant_ex(value, 1, NULL);
EG(scope) = EX(func)->op_array.scope; EG(scope) = EX(func)->op_array.scope;
} }
if (IS_CONST == IS_CONST) { 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); ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
} else { } else {
zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
HANDLE_EXCEPTION();
} }
} }
constant_fetch_end: 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); ZVAL_COPY_VALUE(&c.value, val);
if (Z_OPT_CONSTANT(c.value)) { 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 { } else {
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */ /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE(c.value))) { 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 ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
if (Z_CONSTANT_P(retval)) { 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) { } 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 ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
if (Z_CONSTANT_P(retval)) { 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) { } 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 { } else {
ce = Z_CE_P(EX_VAR(opline->op1.var)); 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 (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) {
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);
}
HANDLE_EXCEPTION(); HANDLE_EXCEPTION();
} }
object_init_ex(&object_zval, ce);
constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval));
if (constructor == NULL) { if (constructor == NULL) {
@ -16158,7 +16157,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_
ZVAL_DEREF(value); ZVAL_DEREF(value);
if (Z_CONSTANT_P(value)) { if (Z_CONSTANT_P(value)) {
EG(scope) = ce; EG(scope) = ce;
zval_update_constant(value, 1); zval_update_constant_ex(value, 1, NULL);
EG(scope) = EX(func)->op_array.scope; EG(scope) = EX(func)->op_array.scope;
} }
if (IS_VAR == IS_CONST) { 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); ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
} else { } else {
zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
HANDLE_EXCEPTION();
} }
} }
constant_fetch_end: constant_fetch_end:
@ -22440,7 +22438,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON
ZVAL_DEREF(value); ZVAL_DEREF(value);
if (Z_CONSTANT_P(value)) { if (Z_CONSTANT_P(value)) {
EG(scope) = ce; EG(scope) = ce;
zval_update_constant(value, 1); zval_update_constant_ex(value, 1, NULL);
EG(scope) = EX(func)->op_array.scope; EG(scope) = EX(func)->op_array.scope;
} }
if (IS_UNUSED == IS_CONST) { 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); ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
} else { } else {
zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
HANDLE_EXCEPTION();
} }
} }
constant_fetch_end: 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 ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
if (Z_CONSTANT_P(retval)) { 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) { } 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 ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
if (Z_CONSTANT_P(retval)) { 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) { } 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 ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
if (Z_CONSTANT_P(retval)) { 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) { } 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 ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
if (Z_CONSTANT_P(retval)) { 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) { } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
zval_ptr_dtor_nogc(free_op1); 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 ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
if (Z_CONSTANT_P(retval)) { 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) { } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
zval_ptr_dtor_nogc(free_op1); 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 ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
if (Z_CONSTANT_P(retval)) { 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) { } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
zval_ptr_dtor_nogc(free_op1); zval_ptr_dtor_nogc(free_op1);

View file

@ -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_REFCOUNT_P(object, 1);
//Z_SET_ISREF_P(object); //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)) { if (!pdo_stmt_instantiate(dbh, return_value, dbstmt_ce, &ctor_args)) {
pdo_raise_impl_error(dbh, NULL, "HY000", if (EXPECTED(!EG(exception))) {
"failed to instantiate user-supplied statement class" pdo_raise_impl_error(dbh, NULL, "HY000",
); "failed to instantiate user-supplied statement class"
);
}
PDO_HANDLE_DBH_ERR(); PDO_HANDLE_DBH_ERR();
RETURN_FALSE; RETURN_FALSE;
} }
@ -1077,7 +1081,9 @@ static PHP_METHOD(PDO, query)
PDO_CONSTRUCT_CHECK; PDO_CONSTRUCT_CHECK;
if (!pdo_stmt_instantiate(dbh, return_value, dbh->def_stmt_ce, &dbh->def_stmt_ctor_args)) { 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; return;
} }
stmt = Z_PDO_STMT_P(return_value); stmt = Z_PDO_STMT_P(return_value);

View file

@ -945,7 +945,9 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_
return 0; return 0;
} }
if ((flags & PDO_FETCH_SERIALIZE) == 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 (!stmt->fetch.cls.fci.size) {
if (!do_fetch_class_prepare(stmt)) if (!do_fetch_class_prepare(stmt))
{ {

View file

@ -428,7 +428,6 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
/* Constants */ /* Constants */
if (&ce->constants_table) { 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"); string_printf(str, "\n");
count = zend_hash_num_elements(&ce->constants_table); count = zend_hash_num_elements(&ce->constants_table);
string_printf(str, "%s - Constants [%d] {\n", indent, count); 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; zval *value;
ZEND_HASH_FOREACH_STR_KEY_VAL(&ce->constants_table, key, 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); _const_string(str, key->val, value, indent);
} ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END();
} }
@ -1851,6 +1851,7 @@ ZEND_METHOD(reflection_function, getStaticVariables)
{ {
reflection_object *intern; reflection_object *intern;
zend_function *fptr; zend_function *fptr;
zval *val;
if (zend_parse_parameters_none() == FAILURE) { if (zend_parse_parameters_none() == FAILURE) {
return; return;
@ -1866,7 +1867,11 @@ ZEND_METHOD(reflection_function, getStaticVariables)
} }
fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables); 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); 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 /* this is necessary to make it able to work with default array
* properties, returned to user */ * properties, returned to user */
if (Z_CONSTANT(prop_copy)) { 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); 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); GET_REFLECTION_OBJECT_PTR(ce);
zend_update_class_constants(ce); if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
return;
}
array_init(return_value); array_init(return_value);
add_class_vars(ce, 1, return_value); add_class_vars(ce, 1, return_value);
@ -3473,7 +3482,9 @@ ZEND_METHOD(reflection_class, getStaticPropertyValue)
GET_REFLECTION_OBJECT_PTR(ce); 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); prop = zend_std_get_static_property(ce, name, 1);
if (!prop) { if (!prop) {
if (def_value) { if (def_value) {
@ -3504,7 +3515,9 @@ ZEND_METHOD(reflection_class, setStaticPropertyValue)
GET_REFLECTION_OBJECT_PTR(ce); 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); variable_ptr = zend_std_get_static_property(ce, name, 1);
if (!variable_ptr) { if (!variable_ptr) {
zend_throw_exception_ex(reflection_exception_ptr, 0, zend_throw_exception_ex(reflection_exception_ptr, 0,
@ -3528,7 +3541,9 @@ ZEND_METHOD(reflection_class, getDefaultProperties)
} }
GET_REFLECTION_OBJECT_PTR(ce); GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value); 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, 1, return_value);
add_class_vars(ce, 0, return_value); add_class_vars(ce, 0, return_value);
} }
@ -4049,13 +4064,18 @@ ZEND_METHOD(reflection_class, getConstants)
{ {
reflection_object *intern; reflection_object *intern;
zend_class_entry *ce; zend_class_entry *ce;
zval *val;
if (zend_parse_parameters_none() == FAILURE) { if (zend_parse_parameters_none() == FAILURE) {
return; return;
} }
GET_REFLECTION_OBJECT_PTR(ce); GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value); 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); 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); 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) { if ((value = zend_hash_find(&ce->constants_table, name)) == NULL) {
RETURN_FALSE; RETURN_FALSE;
} }
@ -4147,7 +4171,9 @@ ZEND_METHOD(reflection_class, isCloneable)
if (ce->clone) { if (ce->clone) {
RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC); RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
} else { } else {
object_init_ex(&obj, ce); if (UNEXPECTED(object_init_ex(&obj, ce) != SUCCESS)) {
return;
}
RETVAL_BOOL(Z_OBJ_HANDLER(obj, clone_obj) != NULL); RETVAL_BOOL(Z_OBJ_HANDLER(obj, clone_obj) != NULL);
zval_dtor(&obj); zval_dtor(&obj);
} }
@ -4232,7 +4258,9 @@ ZEND_METHOD(reflection_class, newInstance)
METHOD_NOTSTATIC(reflection_class_ptr); METHOD_NOTSTATIC(reflection_class_ptr);
GET_REFLECTION_OBJECT_PTR(ce); 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); old_scope = EG(scope);
EG(scope) = ce; EG(scope) = ce;
@ -4334,7 +4362,9 @@ ZEND_METHOD(reflection_class, newInstanceArgs)
argc = args->nNumOfElements; argc = args->nNumOfElements;
} }
object_init_ex(return_value, ce); if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
return;
}
old_scope = EG(scope); old_scope = EG(scope);
EG(scope) = ce; EG(scope) = ce;
@ -5012,7 +5042,9 @@ ZEND_METHOD(reflection_property, getValue)
} }
if ((ref->prop.flags & ZEND_ACC_STATIC)) { 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) { 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); 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 */ /* Bails out */
@ -5061,7 +5093,9 @@ ZEND_METHOD(reflection_property, setValue)
return; 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) { 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); php_error_docref(NULL, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name->val, ref->prop.name->val);

View file

@ -480,7 +480,9 @@ static spl_filesystem_object *spl_filesystem_object_create_type(int ht, spl_file
case SPL_FS_INFO: case SPL_FS_INFO:
ce = ce ? ce : source->info_class; 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)); intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
ZVAL_OBJ(return_value, &intern->std); 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: case SPL_FS_FILE:
ce = ce ? ce : source->file_class; 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)); intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));

View file

@ -3827,7 +3827,9 @@ PHP_FUNCTION(constant)
if (c) { if (c) {
ZVAL_COPY_VALUE(return_value, c); ZVAL_COPY_VALUE(return_value, c);
if (Z_CONSTANT_P(return_value)) { 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); zval_copy_ctor(return_value);
} else { } else {