Skip to content

Commit 6b15163

Browse files
committed
Merge branch 'PHP-7.4'
2 parents 5063a70 + 806db1a commit 6b15163

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) {
@@ -1421,6 +1427,12 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
14211427
SKIP_IF_TOP(op1);
14221428
SKIP_IF_TOP(op2);
14231429

1430+
/* TODO: We could implement support for evaluation of + on partial arrays. */
1431+
if (IS_PARTIAL_ARRAY(op1) || IS_PARTIAL_ARRAY(op2)) {
1432+
SET_RESULT_BOT(result);
1433+
break;
1434+
}
1435+
14241436
if (zend_optimizer_eval_binary_op(&zv, opline->opcode, op1, op2) == SUCCESS) {
14251437
SET_RESULT(result, &zv);
14261438
zval_ptr_dtor_nogc(&zv);
@@ -1607,6 +1619,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
16071619
case ZEND_BW_NOT:
16081620
case ZEND_BOOL_NOT:
16091621
SKIP_IF_TOP(op1);
1622+
if (IS_PARTIAL_ARRAY(op1)) {
1623+
SET_RESULT_BOT(result);
1624+
break;
1625+
}
16101626
if (zend_optimizer_eval_unary_op(&zv, opline->opcode, op1) == SUCCESS) {
16111627
SET_RESULT(result, &zv);
16121628
zval_ptr_dtor_nogc(&zv);
@@ -1616,6 +1632,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
16161632
break;
16171633
case ZEND_CAST:
16181634
SKIP_IF_TOP(op1);
1635+
if (IS_PARTIAL_ARRAY(op1)) {
1636+
SET_RESULT_BOT(result);
1637+
break;
1638+
}
16191639
if (zend_optimizer_eval_cast(&zv, opline->extended_value, op1) == SUCCESS) {
16201640
SET_RESULT(result, &zv);
16211641
zval_ptr_dtor_nogc(&zv);
@@ -1627,6 +1647,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
16271647
case ZEND_JMPZ_EX:
16281648
case ZEND_JMPNZ_EX:
16291649
SKIP_IF_TOP(op1);
1650+
if (IS_PARTIAL_ARRAY(op1)) {
1651+
SET_RESULT_BOT(result);
1652+
break;
1653+
}
16301654
ZVAL_BOOL(&zv, zend_is_true(op1));
16311655
SET_RESULT(result, &zv);
16321656
break;
@@ -1757,6 +1781,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
17571781
break;
17581782
case ZEND_ROPE_INIT:
17591783
SKIP_IF_TOP(op2);
1784+
if (IS_PARTIAL_ARRAY(op2)) {
1785+
SET_RESULT_BOT(result);
1786+
break;
1787+
}
17601788
if (zend_optimizer_eval_cast(&zv, IS_STRING, op2) == SUCCESS) {
17611789
SET_RESULT(result, &zv);
17621790
zval_ptr_dtor_nogc(&zv);
@@ -1771,6 +1799,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
17711799
// string for all SSA vars with some extra checks
17721800
SKIP_IF_TOP(op1);
17731801
SKIP_IF_TOP(op2);
1802+
if (IS_PARTIAL_ARRAY(op2)) {
1803+
SET_RESULT_BOT(result);
1804+
break;
1805+
}
17741806
if (zend_optimizer_eval_binary_op(&zv, ZEND_CONCAT, op1, op2) == SUCCESS) {
17751807
SET_RESULT(result, &zv);
17761808
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)