Skip to content

Commit a287c3f

Browse files
committed
Fix magic constants (__LINE__) with ?? for constant scalar exprs
Also fix general memory leak when root ast gets replaced in compile time evaluation
1 parent 672a995 commit a287c3f

File tree

5 files changed

+49
-11
lines changed

5 files changed

+49
-11
lines changed

Zend/tests/constant_expressions_coalesce.phpt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ const T_1 = null ?? A[1]['undefined']['index'] ?? 1;
99
const T_2 = null ?? A['undefined']['index'] ?? 2;
1010
const T_3 = null ?? A[1][0][2] ?? 3;
1111
const T_4 = A[1][0][2] ?? 4;
12+
const T_5 = null ?? __LINE__;
13+
const T_6 = __LINE__ ?? "bar";
1214

1315
var_dump(T_1);
1416
var_dump(T_2);
1517
var_dump(T_3);
1618
var_dump(T_4);
19+
var_dump(T_5);
20+
var_dump(T_6);
1721

1822
var_dump((function(){ static $var = null ?? A[1]['undefined']['index'] ?? 1; return $var; })());
1923
var_dump((function(){ static $var = null ?? A['undefined']['index'] ?? 2; return $var; })());
@@ -25,14 +29,14 @@ var_dump((new class { public $var = null ?? A['undefined']['index'] ?? 2; })->va
2529
var_dump((new class { public $var = null ?? A[1][0][2] ?? 3; })->var);
2630
var_dump((new class { public $var = A[1][0][2] ?? 4; })->var);
2731

28-
const D = [][] ?? 1;
29-
3032
?>
3133
--EXPECTF--
3234
int(1)
3335
int(2)
3436
int(3)
3537
int(4)
38+
int(%d)
39+
int(%d)
3640
int(1)
3741
int(2)
3842
int(3)
@@ -41,5 +45,3 @@ int(1)
4145
int(2)
4246
int(3)
4347
int(4)
44-
45-
Fatal error: Cannot use [] for reading in %s.php on line 25
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
Constant expressions with empty dimension fetch on coalesce
3+
--FILE--
4+
<?php
5+
6+
const A = [][] ?? 1;
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Cannot use [] for reading in %s.php on line %d
11+

Zend/tests/constant_expressions_dynamic.phpt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ const T_19 = [
3535
false => false,
3636
true => true,
3737
];
38+
eval("const T_20x = 'a';");
39+
const T_20 = null ?: (T_20x . 'bc');
3840

3941
var_dump(
4042
T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9, T_10,
41-
T_11, T_12, T_13, T_14, T_15, T_16, T_17, T_18, T_19
43+
T_11, T_12, T_13, T_14, T_15, T_16, T_17, T_18, T_19, T_20
4244
);
4345

4446
?>
@@ -75,3 +77,4 @@ array(6) {
7577
[1]=>
7678
bool(true)
7779
}
80+
string(3) "abc"

Zend/zend_compile.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6967,14 +6967,16 @@ void zend_const_expr_to_zval(zval *result, zend_ast *ast) /* {{{ */
69676967
zend_compile_const_expr(&ast);
69686968
if (ast->kind == ZEND_AST_ZVAL) {
69696969
ZVAL_COPY_VALUE(result, zend_ast_get_zval(ast));
6970-
6971-
/* Kill this branch of the original AST, as it was already destroyed.
6972-
* It would be nice to find a better solution to this problem in the
6973-
* future. */
6974-
orig_ast->kind = 0;
69756970
} else {
69766971
ZVAL_NEW_AST(result, zend_ast_copy(ast));
6972+
/* destroy the ast here, it might have been replaced */
6973+
zend_ast_destroy(ast);
69776974
}
6975+
6976+
/* Kill this branch of the original AST, as it was already destroyed.
6977+
* It would be nice to find a better solution to this problem in the
6978+
* future. */
6979+
orig_ast->kind = 0;
69786980
}
69796981
/* }}} */
69806982

@@ -7385,6 +7387,26 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
73857387

73867388
zend_ct_eval_unary_pm(&result, ast->kind, zend_ast_get_zval(ast->child[0]));
73877389
break;
7390+
case ZEND_AST_COALESCE:
7391+
zend_eval_const_expr(&ast->child[0]);
7392+
7393+
if (ast->child[0]->kind != ZEND_AST_ZVAL) {
7394+
/* ensure everything was compile-time evaluated at least once */
7395+
zend_eval_const_expr(&ast->child[1]);
7396+
return;
7397+
}
7398+
7399+
if (Z_TYPE_P(zend_ast_get_zval(ast->child[0])) == IS_NULL) {
7400+
zend_eval_const_expr(&ast->child[1]);
7401+
*ast_ptr = ast->child[1];
7402+
ast->child[1] = NULL;
7403+
zend_ast_destroy(ast);
7404+
} else {
7405+
*ast_ptr = ast->child[0];
7406+
ast->child[0] = NULL;
7407+
zend_ast_destroy(ast);
7408+
}
7409+
return;
73887410
case ZEND_AST_CONDITIONAL:
73897411
{
73907412
zend_ast **child, *child_ast;

Zend/zend_execute.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1914,7 +1914,7 @@ ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *
19141914

19151915
ZEND_API void zend_fetch_dimension_by_zval_is(zval *result, zval *container, zval *dim, int dim_type)
19161916
{
1917-
zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1);
1917+
zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS);
19181918
}
19191919

19201920

0 commit comments

Comments
 (0)