com php-src: Fully fixing all the affected const expr cases (see bug #69832): Zend/tests/bug69832.phpt Zend/zend_compile.c
| From: | Bob Weinand | Date: | Tue, 16 Jun 2015 14:53:30 +0000 |
| Subject: | com php-src: Fully fixing all the affected const expr cases (see bug #69832): Zend/tests/bug69832.phpt Zend/zend_compile.c | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-87295@lists.php.net to get a copy of this message | ||
Commit: 52e9a772a33fe3fac17f99257c3c5cc767801f66
Author: Bob Weinand <bobwei9@hotmail.com> Tue, 16 Jun 2015 16:53:17 +0200
Parents: 3e57e50fb0c1e82bd1148a1a002ecc1c980ff75d
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=52e9a772a33fe3fac17f99257c3c5cc767801f66
Log:
Fully fixing all the affected const expr cases (see bug #69832)
Bugs:
https://bugs.php.net/69832
Changed paths:
M Zend/tests/bug69832.phpt
M Zend/zend_compile.c
Diff:
diff --git a/Zend/tests/bug69832.phpt b/Zend/tests/bug69832.phpt
index 64f1634..2617c7b 100644
--- a/Zend/tests/bug69832.phpt
+++ b/Zend/tests/bug69832.phpt
@@ -4,7 +4,10 @@ Bug #69832 (Assertion failed in zend_compile_const_expr_magic_const)
<?php
class Test {
- public $foo = [Bar::A, __CLASS__];
+ public $foo = [Bar::A, __CLASS__][__CLASS__ != ""];
+ public $bar = Bar::A && __CLASS__;
+ public $baz = Bar::A ?: __CLASS__;
+ public $buzz = Bar::A ? __CLASS__ : 0;
}
eval(<<<'PHP'
@@ -14,13 +17,16 @@ class Bar {
PHP
);
-var_dump((new Test)->foo);
+$t = new Test;
+var_dump($t->foo);
+var_dump($t->bar);
+var_dump($t->baz);
+var_dump($t->buzz);
?>
--EXPECT--
-array(2) {
- [0]=>
- int(1)
- [1]=>
- string(4) "Test"
-}
+string(4) "Test"
+bool(true)
+int(1)
+string(4) "Test"
+
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index e934fef..9e86e6d 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -7178,6 +7178,39 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
zend_ct_eval_greater(&result, ast->kind,
zend_ast_get_zval(ast->child[0]), zend_ast_get_zval(ast->child[1]));
break;
+ case ZEND_AST_AND:
+ case ZEND_AST_OR:
+ {
+ int i;
+ for (i = 0; i <= 1; i++) {
+ zend_eval_const_expr(&ast->child[i]);
+ if (ast->child[i]->kind == ZEND_AST_ZVAL) {
+ if (zend_is_true(zend_ast_get_zval(ast->child[i])) == (ast->kind == ZEND_AST_OR)) {
+ ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR);
+ return;
+ }
+ }
+ }
+
+ if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
+ return;
+ }
+
+ if (ast->kind == ZEND_AST_OR) {
+ ZVAL_BOOL(&result, zend_is_true(zend_ast_get_zval(ast->child[0])) ||
zend_is_true(zend_ast_get_zval(ast->child[1])));
+ } else {
+ ZVAL_BOOL(&result, zend_is_true(zend_ast_get_zval(ast->child[0])) &&
zend_is_true(zend_ast_get_zval(ast->child[1])));
+ }
+ break;
+ }
+ case ZEND_AST_UNARY_OP:
+ zend_eval_const_expr(&ast->child[0]);
+ if (ast->child[0]->kind != ZEND_AST_ZVAL) {
+ return;
+ }
+
+ zend_ct_eval_unary_op(&result, ast->attr, zend_ast_get_zval(ast->child[0]));
+ break;
case ZEND_AST_UNARY_PLUS:
case ZEND_AST_UNARY_MINUS:
zend_eval_const_expr(&ast->child[0]);
@@ -7185,9 +7218,90 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
return;
}
- zend_ct_eval_unary_pm(&result, ast->kind,
- zend_ast_get_zval(ast->child[0]));
+ zend_ct_eval_unary_pm(&result, ast->kind, zend_ast_get_zval(ast->child[0]));
+ break;
+ case ZEND_AST_CONDITIONAL:
+ {
+ zend_ast **child, *child_ast;
+ zend_eval_const_expr(&ast->child[0]);
+ if (ast->child[0]->kind != ZEND_AST_ZVAL) {
+ /* ensure everything was compile-time evaluated at least once */
+ if (ast->child[1]) {
+ zend_eval_const_expr(&ast->child[1]);
+ }
+ zend_eval_const_expr(&ast->child[2]);
+ return;
+ }
+
+ child = &ast->child[2 - zend_is_true(zend_ast_get_zval(ast->child[0]))];
+ if (*child == NULL) {
+ child--;
+ }
+ child_ast = *child;
+ *child = NULL;
+ zend_ast_destroy(ast);
+ *ast_ptr = child_ast;
+ zend_eval_const_expr(ast_ptr);
+ return;
+ }
+ case ZEND_AST_DIM:
+ {
+ /* constant expression should be always read context ... */
+
+ zval *container, *dim;
+
+ zend_eval_const_expr(&ast->child[0]);
+ zend_eval_const_expr(&ast->child[1]);
+ if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
+ return;
+ }
+
+ container = zend_ast_get_zval(ast->child[0]);
+ dim = zend_ast_get_zval(ast->child[1]);
+
+ if (Z_TYPE_P(container) == IS_ARRAY) {
+ zval *el;
+ if (Z_TYPE_P(dim) == IS_LONG) {
+ el = zend_hash_index_find(Z_ARR_P(container), Z_LVAL_P(dim));
+ if (el) {
+ ZVAL_COPY(&result, el);
+ } else {
+ return;
+ }
+ } else if (Z_TYPE_P(dim) == IS_STRING) {
+ el = zend_symtable_find(Z_ARR_P(container), Z_STR_P(dim));
+ if (el) {
+ ZVAL_COPY(&result, el);
+ } else {
+ return;
+ }
+ } else {
+ return; /* warning... handle at runtime */
+ }
+ } else if (Z_TYPE_P(container) == IS_STRING) {
+ zend_long offset;
+ zend_uchar c;
+ if (Z_TYPE_P(dim) == IS_LONG) {
+ offset = Z_LVAL_P(dim);
+ } else if (Z_TYPE_P(dim) != IS_STRING || is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim),
&offset, NULL, 1) != IS_LONG) {
+ return;
+ }
+ if (offset < 0 || offset >= Z_STRLEN_P(container)) {
+ return;
+ }
+ c = (zend_uchar) Z_STRVAL_P(container)[offset];
+ if (CG(one_char_string)[c]) {
+ ZVAL_INTERNED_STR(&result, CG(one_char_string)[c]);
+ } else {
+ ZVAL_NEW_STR(&result, zend_string_init((char *) &c, 1, 0));
+ }
+ } else if (Z_TYPE_P(container) <= IS_FALSE) {
+ ZVAL_NULL(&result);
+ } else {
+ return;
+ }
break;
+ }
case ZEND_AST_ARRAY:
if (!zend_try_ct_eval_array(&result, ast)) {
return;