Skip to content

Commit a54ee8a

Browse files
committed
Merge branch 'PHP-7.3' into PHP-7.4
2 parents 6791107 + e7a83ec commit a54ee8a

File tree

2 files changed

+58
-10
lines changed

2 files changed

+58
-10
lines changed

Zend/tests/bug78271.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Bug #78271: Invalid result of if-else
3+
--FILE--
4+
<?
5+
function test($a, $b){
6+
if ($a==10) {
7+
$w="x";
8+
} else {
9+
$w="y";
10+
}
11+
12+
if ($b) {
13+
$d1="none";
14+
$d2="block";
15+
} else {
16+
$d1="block";
17+
$d2="none";
18+
}
19+
20+
echo $d2.$b."\n";
21+
22+
}
23+
24+
test(1, 1);
25+
?>
26+
--EXPECT--
27+
block1

ext/opcache/Optimizer/dfa_pass.c

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,37 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx,
125125
return SUCCESS;
126126
}
127127

128+
static zend_bool is_smart_branch_inhibiting_nop(
129+
zend_op_array *op_array, uint32_t target, uint32_t current,
130+
zend_basic_block *b, zend_basic_block *blocks_end)
131+
{
132+
uint32_t next;
133+
/* Target points one past the last non-nop instruction. Make sure there is one. */
134+
if (target == 0) {
135+
return 0;
136+
}
137+
138+
/* Find the next instruction, skipping unreachable or empty blocks. */
139+
next = current + 1;
140+
if (next >= b->start + b->len) {
141+
do {
142+
b++;
143+
if (b == blocks_end) {
144+
return 0;
145+
}
146+
} while (!(b->flags & ZEND_BB_REACHABLE) || b->len == 0);
147+
next = b->start;
148+
}
149+
150+
return (op_array->opcodes[next].opcode == ZEND_JMPZ ||
151+
op_array->opcodes[next].opcode == ZEND_JMPNZ) &&
152+
zend_is_smart_branch(op_array->opcodes + target - 1);
153+
}
154+
128155
static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_optimizer_ctx *ctx)
129156
{
130157
zend_basic_block *blocks = ssa->cfg.blocks;
131-
zend_basic_block *end = blocks + ssa->cfg.blocks_count;
158+
zend_basic_block *blocks_end = blocks + ssa->cfg.blocks_count;
132159
zend_basic_block *b;
133160
zend_func_info *func_info;
134161
int j;
@@ -152,7 +179,7 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op
152179
}
153180
}
154181

155-
for (b = blocks; b < end; b++) {
182+
for (b = blocks; b < blocks_end; b++) {
156183
if (b->flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) {
157184
uint32_t end;
158185

@@ -174,13 +201,7 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op
174201
while (i < end) {
175202
shiftlist[i] = i - target;
176203
if (EXPECTED(op_array->opcodes[i].opcode != ZEND_NOP) ||
177-
/* Keep NOP to support ZEND_VM_SMART_BRANCH. Using "target-1" instead of
178-
* "i-1" here to check the last non-NOP instruction. */
179-
(target > 0 &&
180-
i + 1 < op_array->last &&
181-
(op_array->opcodes[i+1].opcode == ZEND_JMPZ ||
182-
op_array->opcodes[i+1].opcode == ZEND_JMPNZ) &&
183-
zend_is_smart_branch(op_array->opcodes + target - 1))) {
204+
is_smart_branch_inhibiting_nop(op_array, target, i, b, blocks_end)) {
184205
if (i != target) {
185206
op_array->opcodes[target] = op_array->opcodes[i];
186207
ssa->ops[target] = ssa->ops[i];
@@ -240,7 +261,7 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op
240261
}
241262

242263
/* update branch targets */
243-
for (b = blocks; b < end; b++) {
264+
for (b = blocks; b < blocks_end; b++) {
244265
if ((b->flags & ZEND_BB_REACHABLE) && b->len != 0) {
245266
zend_op *opline = op_array->opcodes + b->start + b->len - 1;
246267
zend_optimizer_shift_jump(op_array, opline, shiftlist);

0 commit comments

Comments
 (0)