From 5a87b7ff39bbf427807c46d1e51e2654259ad394 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 10 Dec 2013 14:19:17 +0400 Subject: [PATCH] Fixed bug #66252 (Problems in AST evaluation invalidating valid parent:: reference. Constant expessions have to be evaluated in context of defining class). --- Zend/tests/bug66252.phpt | 14 ++++++ Zend/zend_ast.c | 98 ++++++++++++++++++++-------------------- Zend/zend_ast.h | 2 +- Zend/zend_compile.c | 2 +- Zend/zend_execute_API.c | 4 +- 5 files changed, 67 insertions(+), 53 deletions(-) create mode 100644 Zend/tests/bug66252.phpt diff --git a/Zend/tests/bug66252.phpt b/Zend/tests/bug66252.phpt new file mode 100644 index 00000000000..e692a8e706d --- /dev/null +++ b/Zend/tests/bug66252.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #66252 (Problems in AST evaluation invalidating valid parent:: reference) +--FILE-- +kind) { case ZEND_ADD: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); add_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_SUB: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); sub_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_MUL: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); mul_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_DIV: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); div_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_MOD: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); mod_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_SL: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); shift_left_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_SR: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); shift_right_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_CONCAT: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); concat_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_BW_OR: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); bitwise_or_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_BW_AND: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); bitwise_and_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_BW_XOR: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); bitwise_xor_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_BW_NOT: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); bitwise_not_function(result, &op1 TSRMLS_CC); zval_dtor(&op1); break; case ZEND_BOOL_NOT: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); boolean_not_function(result, &op1 TSRMLS_CC); zval_dtor(&op1); break; case ZEND_BOOL_XOR: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); boolean_xor_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_IS_IDENTICAL: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); is_identical_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_IS_NOT_IDENTICAL: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); is_not_identical_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_IS_EQUAL: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); is_equal_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_IS_NOT_EQUAL: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); is_not_equal_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_IS_SMALLER: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); is_smaller_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); break; case ZEND_IS_SMALLER_OR_EQUAL: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); is_smaller_or_equal_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op1); zval_dtor(&op2); @@ -226,13 +226,13 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC) *result = *ast->u.val; zval_copy_ctor(result); if (IS_CONSTANT_TYPE(Z_TYPE_P(result))) { - zval_update_constant(&result, (void *) 1 TSRMLS_CC); + zval_update_constant_ex(&result, (void *) 1, scope TSRMLS_CC); } break; case ZEND_BOOL_AND: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); if (zend_is_true(&op1)) { - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); ZVAL_BOOL(result, zend_is_true(&op2)); zval_dtor(&op2); } else { @@ -241,39 +241,39 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC) zval_dtor(&op1); break; case ZEND_BOOL_OR: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); if (zend_is_true(&op1)) { ZVAL_BOOL(result, 1); } else { - zend_ast_evaluate(&op2, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[1], scope TSRMLS_CC); ZVAL_BOOL(result, zend_is_true(&op2)); zval_dtor(&op2); } zval_dtor(&op1); break; case ZEND_SELECT: - zend_ast_evaluate(&op1, (&ast->u.child)[0] TSRMLS_CC); + zend_ast_evaluate(&op1, (&ast->u.child)[0], scope TSRMLS_CC); if (zend_is_true(&op1)) { if (!(&ast->u.child)[1]) { *result = op1; } else { - zend_ast_evaluate(result, (&ast->u.child)[1] TSRMLS_CC); + zend_ast_evaluate(result, (&ast->u.child)[1], scope TSRMLS_CC); zval_dtor(&op1); } } else { - zend_ast_evaluate(result, (&ast->u.child)[2] TSRMLS_CC); + zend_ast_evaluate(result, (&ast->u.child)[2], scope TSRMLS_CC); zval_dtor(&op1); } break; case ZEND_UNARY_PLUS: ZVAL_LONG(&op1, 0); - zend_ast_evaluate(&op2, (&ast->u.child)[0] TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC); add_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op2); break; case ZEND_UNARY_MINUS: ZVAL_LONG(&op1, 0); - zend_ast_evaluate(&op2, (&ast->u.child)[0] TSRMLS_CC); + zend_ast_evaluate(&op2, (&ast->u.child)[0], scope TSRMLS_CC); sub_function(result, &op1, &op2 TSRMLS_CC); zval_dtor(&op2); break; diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 27d595e23e9..49908cebbe1 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -53,7 +53,7 @@ ZEND_API zend_ast *zend_ast_create_ternary(uint kind, zend_ast *op0, zend_ast *o ZEND_API int zend_ast_is_ct_constant(zend_ast *ast); -ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast TSRMLS_DC); +ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope TSRMLS_DC); ZEND_API zend_ast *zend_ast_copy(zend_ast *ast); ZEND_API void zend_ast_destroy(zend_ast *ast); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 35f5f30cba8..ab8609e4106 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7341,7 +7341,7 @@ void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ result->u.constant = *ast->u.val; efree(ast); } else if (zend_ast_is_ct_constant(ast)) { - zend_ast_evaluate(&result->u.constant, ast TSRMLS_CC); + zend_ast_evaluate(&result->u.constant, ast, NULL TSRMLS_CC); zend_ast_destroy(ast); } else { Z_TYPE(result->u.constant) = IS_CONSTANT_AST; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index bcce7418d56..82689ed7d61 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -593,7 +593,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco continue; } if (str_index[str_index_len - 2] == IS_CONSTANT_AST) { - zend_ast_evaluate(&const_value, *(zend_ast **)str_index TSRMLS_CC); + zend_ast_evaluate(&const_value, *(zend_ast **)str_index, scope TSRMLS_CC); zend_ast_destroy(*(zend_ast **)str_index); } else if (!zend_get_constant_ex(str_index, str_index_len - 3, &const_value, scope, str_index[str_index_len - 2] TSRMLS_CC)) { char *actual; @@ -667,7 +667,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco SEPARATE_ZVAL_IF_NOT_REF(pp); p = *pp; - zend_ast_evaluate(&const_value, Z_AST_P(p) TSRMLS_CC); + zend_ast_evaluate(&const_value, Z_AST_P(p), scope TSRMLS_CC); if (inline_change) { zend_ast_destroy(Z_AST_P(p)); }