summaryrefslogtreecommitdiff
path: root/Zend/zend_ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_ast.c')
-rw-r--r--Zend/zend_ast.c172
1 files changed, 118 insertions, 54 deletions
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)