Skip to content

Commit 66d3095

Browse files
committed
Fixed bug #69038 (switch(SOMECONSTANT) misbehaves)
1 parent 35a68c2 commit 66d3095

File tree

3 files changed

+79
-11
lines changed

3 files changed

+79
-11
lines changed

NEWS

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ PHP NEWS
88
. Added NULL byte protection to exec, system and passthru. (Yasuo)
99

1010
- ODBC:
11-
. Bug #68964 (Allowed memory size exhausted with odbc_exec). (Anatol)
11+
. Fixed bug #68964 (Allowed memory size exhausted with odbc_exec). (Anatol)
12+
13+
- Opcache:
14+
. Fixed bug #69038 (switch(SOMECONSTANT) misbehaves). (Laruence)
1215

1316
- OpenSSL:
1417
. Fix bug #61285, #68329, #68046, #41631: encrypted streams don't observe

ext/opcache/Optimizer/zend_optimizer.c

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -291,17 +291,41 @@ static void replace_tmp_by_const(zend_op_array *op_array,
291291
* usually terminated by ZEND_FREE that finally kills the value.
292292
*/
293293
if (opline->opcode == ZEND_CASE) {
294-
zval old_val;
295-
old_val = *val;
296-
zval_copy_ctor(val);
297-
update_op1_const(op_array, opline, val TSRMLS_CC);
298-
*val = old_val;
294+
zend_op *m, *n;
295+
int brk = op_array->last_brk_cont;
296+
while (brk--) {
297+
if (op_array->brk_cont_array[brk].start <= (opline - op_array->opcodes) &&
298+
op_array->brk_cont_array[brk].brk > (opline - op_array->opcodes)) {
299+
break;
300+
}
301+
}
302+
m = opline;
303+
n = op_array->opcodes + op_array->brk_cont_array[brk].brk + 1;
304+
while (m < n) {
305+
if (ZEND_OP1_TYPE(m) == IS_TMP_VAR &&
306+
ZEND_OP1(m).var == var) {
307+
if (m->opcode == ZEND_CASE) {
308+
zval old_val;
309+
old_val = *val;
310+
zval_copy_ctor(val);
311+
update_op1_const(op_array, m, val TSRMLS_CC);
312+
*val = old_val;
313+
} else if (m->opcode == ZEND_FREE) {
314+
MAKE_NOP(m);
315+
} else {
316+
ZEND_ASSERT(0);
317+
}
318+
}
319+
m++;
320+
}
321+
zval_dtor(val);
322+
break;
299323
} else if (opline->opcode == ZEND_FREE) {
300324
MAKE_NOP(opline);
325+
zval_dtor(val);
301326
break;
302327
} else {
303328
update_op1_const(op_array, opline, val TSRMLS_CC);
304-
val = NULL;
305329
break;
306330
}
307331
}
@@ -311,14 +335,10 @@ static void replace_tmp_by_const(zend_op_array *op_array,
311335

312336
update_op2_const(op_array, opline, val TSRMLS_CC);
313337
/* TMP_VAR may be used only once */
314-
val = NULL;
315338
break;
316339
}
317340
opline++;
318341
}
319-
if (val) {
320-
zval_dtor(val);
321-
}
322342
}
323343

324344
#include "Optimizer/nop_removal.c"

ext/opcache/tests/bug69038.phpt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Bug #69038 (switch(SOMECONSTANT) misbehaves)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
--SKIPIF--
8+
<?php require_once('skipif.inc'); ?>
9+
--FILE--
10+
<?php
11+
function a($a = "bad") {
12+
13+
switch (PHP_OS) {
14+
case "LALALALA" : return "LALALAL";
15+
case PHP_OS: return "okey";
16+
default: break;
17+
}
18+
19+
return $a;
20+
}
21+
22+
var_dump(a());
23+
24+
25+
function b($b = "bad") {
26+
switch (PHP_OS) {
27+
case "LALALAL": return "bad";
28+
case PHP_OS:
29+
switch (PHP_OS) {
30+
case "FOO": break;
31+
case PHP_OS: return "okey";
32+
default :
33+
break;
34+
}
35+
break;
36+
default:
37+
break;
38+
}
39+
return $b;
40+
}
41+
var_dump(b());
42+
?>
43+
--EXPECT--
44+
string(4) "okey"
45+
string(4) "okey"

0 commit comments

Comments
 (0)