Skip to content

Commit 9d76fbd

Browse files
committed
Fixed bug #78015
Don't try to evaluate various operations with partial array operands. We could evaluate some of these, but let's be conservative for now...
1 parent 5846119 commit 9d76fbd

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ PHP NEWS
66
. Fixed bug #76980 (Interface gets skipped if autoloader throws an exception).
77
(Nikita)
88

9+
- Opcache:
10+
. Fixed bug #78015 (Incorrect evaluation of expressions involving partials
11+
arrays in SCCP). (Nikita)
12+
913
16 May 2019, PHP 7.3.6RC1
1014

1115
- cURL:

ext/opcache/Optimizer/sccp.c

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

662662
static inline void ct_eval_type_check(zval *result, uint32_t type_mask, zval *op1) {
663-
ZVAL_BOOL(result, (type_mask >> Z_TYPE_P(op1)) & 1);
663+
uint32_t type = Z_TYPE_P(op1);
664+
if (type == PARTIAL_ARRAY) {
665+
type = IS_ARRAY;
666+
} else if (type == PARTIAL_OBJECT) {
667+
type = IS_OBJECT;
668+
}
669+
ZVAL_BOOL(result, (type_mask >> type) & 1);
664670
}
665671

666672
static inline int ct_eval_in_array(zval *result, uint32_t extended_value, zval *op1, zval *op2) {
@@ -1359,6 +1365,12 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
13591365
SKIP_IF_TOP(op1);
13601366
SKIP_IF_TOP(op2);
13611367

1368+
/* TODO: We could implement support for evaluation of + on partial arrays. */
1369+
if (IS_PARTIAL_ARRAY(op1) || IS_PARTIAL_ARRAY(op2)) {
1370+
SET_RESULT_BOT(result);
1371+
break;
1372+
}
1373+
13621374
if (zend_optimizer_eval_binary_op(&zv, opline->opcode, op1, op2) == SUCCESS) {
13631375
SET_RESULT(result, &zv);
13641376
zval_ptr_dtor_nogc(&zv);
@@ -1540,6 +1552,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
15401552
case ZEND_BW_NOT:
15411553
case ZEND_BOOL_NOT:
15421554
SKIP_IF_TOP(op1);
1555+
if (IS_PARTIAL_ARRAY(op1)) {
1556+
SET_RESULT_BOT(result);
1557+
break;
1558+
}
15431559
if (zend_optimizer_eval_unary_op(&zv, opline->opcode, op1) == SUCCESS) {
15441560
SET_RESULT(result, &zv);
15451561
zval_ptr_dtor_nogc(&zv);
@@ -1549,6 +1565,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
15491565
break;
15501566
case ZEND_CAST:
15511567
SKIP_IF_TOP(op1);
1568+
if (IS_PARTIAL_ARRAY(op1)) {
1569+
SET_RESULT_BOT(result);
1570+
break;
1571+
}
15521572
if (zend_optimizer_eval_cast(&zv, opline->extended_value, op1) == SUCCESS) {
15531573
SET_RESULT(result, &zv);
15541574
zval_ptr_dtor_nogc(&zv);
@@ -1560,6 +1580,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
15601580
case ZEND_JMPZ_EX:
15611581
case ZEND_JMPNZ_EX:
15621582
SKIP_IF_TOP(op1);
1583+
if (IS_PARTIAL_ARRAY(op1)) {
1584+
SET_RESULT_BOT(result);
1585+
break;
1586+
}
15631587
ZVAL_BOOL(&zv, zend_is_true(op1));
15641588
SET_RESULT(result, &zv);
15651589
break;
@@ -1679,6 +1703,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
16791703
break;
16801704
case ZEND_ROPE_INIT:
16811705
SKIP_IF_TOP(op2);
1706+
if (IS_PARTIAL_ARRAY(op2)) {
1707+
SET_RESULT_BOT(result);
1708+
break;
1709+
}
16821710
if (zend_optimizer_eval_cast(&zv, IS_STRING, op2) == SUCCESS) {
16831711
SET_RESULT(result, &zv);
16841712
zval_ptr_dtor_nogc(&zv);
@@ -1693,6 +1721,10 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
16931721
// string for all SSA vars with some extra checks
16941722
SKIP_IF_TOP(op1);
16951723
SKIP_IF_TOP(op2);
1724+
if (IS_PARTIAL_ARRAY(op2)) {
1725+
SET_RESULT_BOT(result);
1726+
break;
1727+
}
16961728
if (zend_optimizer_eval_binary_op(&zv, ZEND_CONCAT, op1, op2) == SUCCESS) {
16971729
SET_RESULT(result, &zv);
16981730
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)