diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-09-03 11:18:11 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-09-03 11:18:11 +0200 |
commit | ce74ff2b3d767d7f804fd16fb366e04dbe2cec5d (patch) | |
tree | 672ce601448057bc23c77b430db99975adf69d5d | |
parent | 67e9b3be396a861d3c0a00881ae6092dc8a349bd (diff) | |
parent | 04e77d2dea03955b987bc6e253ea236c2c7a12aa (diff) | |
download | php-git-ce74ff2b3d767d7f804fd16fb366e04dbe2cec5d.tar.gz |
Merge branch 'PHP-7.4'
* PHP-7.4:
Fixed bug #80046
-rw-r--r-- | Zend/tests/bug80046.phpt | 22 | ||||
-rw-r--r-- | ext/opcache/Optimizer/block_pass.c | 14 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_cfg.c | 3 |
3 files changed, 34 insertions, 5 deletions
diff --git a/Zend/tests/bug80046.phpt b/Zend/tests/bug80046.phpt new file mode 100644 index 0000000000..87a493c203 --- /dev/null +++ b/Zend/tests/bug80046.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #80046: FREE for SWITCH_STRING optimized away +--FILE-- +<?php + +function test($foo) { + switch ($foo . 'Bar') { + case 'A': + throw new Exception('A'); + default: + throw new Exception('Default'); + } +} +try { + test('Foo'); +} catch (Exception $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Default diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 68555115f8..7b9fb2afca 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -967,7 +967,15 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op if (b->len == 0) { continue; } - if (b->flags & ZEND_BB_REACHABLE) { + if (b->flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) { + if (b->flags & ZEND_BB_UNREACHABLE_FREE) { + /* Only keep the FREE for the loop var */ + ZEND_ASSERT(op_array->opcodes[b->start].opcode == ZEND_FREE + || op_array->opcodes[b->start].opcode == ZEND_FE_FREE); + len += b->len = 1; + continue; + } + opline = op_array->opcodes + b->start + b->len - 1; if (opline->opcode == ZEND_JMP) { zend_basic_block *next = b + 1; @@ -1005,7 +1013,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op /* Copy code of reachable blocks into a single buffer */ for (b = blocks; b < end; b++) { - if (b->flags & ZEND_BB_REACHABLE) { + if (b->flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) { memcpy(opline, op_array->opcodes + b->start, b->len * sizeof(zend_op)); b->start = opline - new_opcodes; opline += b->len; @@ -1131,7 +1139,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op /* rebuild map (just for printing) */ memset(cfg->map, -1, sizeof(int) * op_array->last); for (n = 0; n < cfg->blocks_count; n++) { - if (cfg->blocks[n].flags & ZEND_BB_REACHABLE) { + if (cfg->blocks[n].flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) { cfg->map[cfg->blocks[n].start] = n; } } diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c index b8088924f9..127fca5dca 100644 --- a/ext/opcache/Optimizer/zend_cfg.c +++ b/ext/opcache/Optimizer/zend_cfg.c @@ -593,9 +593,8 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b } /* Build CFG, Step 4, Mark Reachable Basic Blocks */ - zend_mark_reachable_blocks(op_array, cfg, 0); - cfg->flags |= flags; + zend_mark_reachable_blocks(op_array, cfg, 0); return SUCCESS; } |