Skip to content

Commit 806db1a

Browse files
committed
Merge branch 'PHP-7.3' into PHP-7.4
2 parents c666f6e + 9d76fbd commit 806db1a

File tree

2 files changed

+103
-1
lines changed

2 files changed

+103
-1
lines changed

ext/opcache/Optimizer/sccp.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,13 @@ static inline int ct_eval_isset_isempty(zval *result, uint32_t extended_value, z
680680
}
681681

682682
static inline void ct_eval_type_check(zval *result, uint32_t type_mask, zval *op1) {
683-
ZVAL_BOOL(result, (type_mask >> Z_TYPE_P(op1)) & 1);
683+
uint32_t type = Z_TYPE_P(op1);
684+
if (type == PARTIAL_ARRAY) {
685+
type = IS_ARRAY;
686+
} else if (type == PARTIAL_OBJECT) {
687+
type = IS_OBJECT;
688+
}
689+
ZVAL_BOOL(result, (type_mask >> type) & 1);
684690
}
685691

686692
static inline int ct_eval_in_array(zval *result, uint32_t extended_value, zval *op1, zval *op2) {
@@ -1424,6 +1430,12 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
14241430
SKIP_IF_TOP(op1);
14251431
SKIP_IF_TOP(op2);
14261432

1433+
/* TODO: We could implement support for evaluation of + on partial arrays. */
1434+
if (IS_PARTIAL_ARRAY(op1) || IS_PARTIAL_ARRAY(op2)) {
1435+
SET_RESULT_BOT(result);
1436+
break;
1437+
}
1438+
14271439
if (zend_optimizer_eval_binary_op(&zv, opline->opcode, op1, op2) == SUCCESS) {
14281440
SET_RESULT(result, &zv);
14291441
zval_ptr_dtor_nogc(&zv);
@@ -1610,6 +1622,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
16101622
case ZEND_BW_NOT:
16111623
case ZEND_BOOL_NOT:
16121624
SKIP_IF_TOP(op1);
1625+
if (IS_PARTIAL_ARRAY(op1)) {
1626+
SET_RESULT_BOT(result);
1627+
break;
1628+
}
16131629
if (zend_optimizer_eval_unary_op(&zv, opline->opcode, op1) == SUCCESS) {
16141630
SET_RESULT(result, &zv);
16151631
zval_ptr_dtor_nogc(&zv);
@@ -1619,6 +1635,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
16191635
break;
16201636
case ZEND_CAST:
16211637
SKIP_IF_TOP(op1);
1638+
if (IS_PARTIAL_ARRAY(op1)) {
1639+
SET_RESULT_BOT(result);
1640+
break;
1641+
}
16221642
if (zend_optimizer_eval_cast(&zv, opline->extended_value, op1) == SUCCESS) {
16231643
SET_RESULT(result, &zv);
16241644
zval_ptr_dtor_nogc(&zv);
@@ -1630,6 +1650,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
16301650
case ZEND_JMPZ_EX:
16311651
case ZEND_JMPNZ_EX:
16321652
SKIP_IF_TOP(op1);
1653+
if (IS_PARTIAL_ARRAY(op1)) {
1654+
SET_RESULT_BOT(result);
1655+
break;
1656+
}
16331657
ZVAL_BOOL(&zv, zend_is_true(op1));
16341658
SET_RESULT(result, &zv);
16351659
break;
@@ -1760,6 +1784,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
17601784
break;
17611785
case ZEND_ROPE_INIT:
17621786
SKIP_IF_TOP(op2);
1787+
if (IS_PARTIAL_ARRAY(op2)) {
1788+
SET_RESULT_BOT(result);
1789+
break;
1790+
}
17631791
if (zend_optimizer_eval_cast(&zv, IS_STRING, op2) == SUCCESS) {
17641792
SET_RESULT(result, &zv);
17651793
zval_ptr_dtor_nogc(&zv);
@@ -1774,6 +1802,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
17741802
// string for all SSA vars with some extra checks
17751803
SKIP_IF_TOP(op1);
17761804
SKIP_IF_TOP(op2);
1805+
if (IS_PARTIAL_ARRAY(op2)) {
1806+
SET_RESULT_BOT(result);
1807+
break;
1808+
}
17771809
if (zend_optimizer_eval_binary_op(&zv, ZEND_CONCAT, op1, op2) == SUCCESS) {
17781810
SET_RESULT(result, &zv);
17791811
zval_ptr_dtor_nogc(&zv);

ext/opcache/tests/bug78015.phpt

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
--TEST--
2+
Bug #78015: Incorrect evaluation of expressions involving partials array in SCCP
3+
--FILE--
4+
<?php
5+
6+
$x = 1;
7+
8+
function test1() {
9+
global $x;
10+
$a = ['b' => [$x], 'c' => [$x]];
11+
$d = $a['b'] + $a['c'];
12+
return $d;
13+
}
14+
15+
function test2() {
16+
global $x;
17+
$a = ['b' => [$x]];
18+
$d = !$a['b'];
19+
return $d;
20+
}
21+
22+
function test3() {
23+
global $x;
24+
$a = ['b' => [$x]];
25+
$d = (int) $a['b'];
26+
return $d;
27+
}
28+
29+
function test4() {
30+
global $x;
31+
$a = ['b' => [$x]];
32+
$d = $a['b'] ?: 42;
33+
return $d;
34+
}
35+
36+
function test5() {
37+
global $x;
38+
$a = ['b' => [$x]];
39+
$d = is_array($a['b']);
40+
return $d;
41+
}
42+
43+
function test6() {
44+
global $x;
45+
$a = ['b' => [$x]];
46+
$b = "foo";
47+
$d = "$a[b]{$b}bar";
48+
return $d;
49+
}
50+
51+
var_dump(test1());
52+
var_dump(test2());
53+
var_dump(test3());
54+
var_dump(test4());
55+
var_dump(test5());
56+
var_dump(test6());
57+
58+
?>
59+
--EXPECTF--
60+
array(1) {
61+
[0]=>
62+
int(1)
63+
}
64+
bool(false)
65+
int(1)
66+
int(42)
67+
bool(true)
68+
69+
Notice: Array to string conversion in %s on line %d
70+
string(11) "Arrayfoobar"

0 commit comments

Comments
 (0)