mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fix SCDF cleanup of unused basic block, kept only because of FREE of a loop var
Fixes oss-fuzz #41516
This commit is contained in:
parent
b594a95a2f
commit
c3766c08f4
4 changed files with 30 additions and 6 deletions
|
@ -224,10 +224,11 @@ static uint32_t cleanup_loop_var_free_block(scdf_ctx *scdf, zend_basic_block *bl
|
|||
zend_ssa *ssa = scdf->ssa;
|
||||
const zend_op_array *op_array = scdf->op_array;
|
||||
const zend_cfg *cfg = &ssa->cfg;
|
||||
int block_num = block - cfg->blocks;
|
||||
uint32_t removed_ops = 0;
|
||||
|
||||
/* Removes phi nodes */
|
||||
for (zend_ssa_phi *phi = ssa->blocks[block - cfg->blocks].phis; phi; phi = phi->next) {
|
||||
for (zend_ssa_phi *phi = ssa->blocks[block_num].phis; phi; phi = phi->next) {
|
||||
zend_ssa_remove_uses_of_var(ssa, phi->ssa_var);
|
||||
zend_ssa_remove_phi(ssa, phi);
|
||||
}
|
||||
|
@ -235,7 +236,8 @@ static uint32_t cleanup_loop_var_free_block(scdf_ctx *scdf, zend_basic_block *bl
|
|||
for (uint32_t i = block->start; i < block->start + block->len; i++) {
|
||||
zend_op *opline = &op_array->opcodes[i];
|
||||
zend_ssa_op *ssa_op = &scdf->ssa->ops[i];
|
||||
if (is_live_loop_var_free(scdf, opline, ssa_op)) {
|
||||
if (opline->opcode == ZEND_NOP
|
||||
|| is_live_loop_var_free(scdf, opline, ssa_op)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -243,10 +245,11 @@ static uint32_t cleanup_loop_var_free_block(scdf_ctx *scdf, zend_basic_block *bl
|
|||
* in the block. */
|
||||
zend_ssa_remove_defs_of_instr(ssa, ssa_op);
|
||||
zend_ssa_remove_instr(ssa, opline, ssa_op);
|
||||
removed_ops++;
|
||||
}
|
||||
|
||||
/* This block has no predecessors anymore. */
|
||||
block->predecessors_count = 0;
|
||||
zend_ssa_remove_block_from_cfg(ssa, block_num);
|
||||
|
||||
return removed_ops;
|
||||
}
|
||||
|
||||
|
|
|
@ -1448,9 +1448,8 @@ void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int i) /* {{{
|
|||
{
|
||||
zend_basic_block *block = &ssa->cfg.blocks[i];
|
||||
zend_ssa_block *ssa_block = &ssa->blocks[i];
|
||||
int *predecessors;
|
||||
zend_ssa_phi *phi;
|
||||
int j, s;
|
||||
int j;
|
||||
|
||||
block->flags &= ~ZEND_BB_REACHABLE;
|
||||
|
||||
|
@ -1470,6 +1469,16 @@ void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int i) /* {{{
|
|||
zend_ssa_remove_instr(ssa, &op_array->opcodes[j], &ssa->ops[j]);
|
||||
}
|
||||
|
||||
zend_ssa_remove_block_from_cfg(ssa, i);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_ssa_remove_block_from_cfg(zend_ssa *ssa, int i) /* {{{ */
|
||||
{
|
||||
zend_basic_block *block = &ssa->cfg.blocks[i];
|
||||
int *predecessors;
|
||||
int j, s;
|
||||
|
||||
for (s = 0; s < block->successors_count; s++) {
|
||||
zend_ssa_remove_predecessor(ssa, i, block->successors[s]);
|
||||
}
|
||||
|
|
|
@ -157,6 +157,7 @@ void zend_ssa_remove_phi(zend_ssa *ssa, zend_ssa_phi *phi);
|
|||
void zend_ssa_remove_uses_of_var(zend_ssa *ssa, int var_num);
|
||||
void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int b);
|
||||
void zend_ssa_rename_var_uses(zend_ssa *ssa, int old_var, int new_var, bool update_types);
|
||||
void zend_ssa_remove_block_from_cfg(zend_ssa *ssa, int b);
|
||||
|
||||
static zend_always_inline void _zend_ssa_remove_def(zend_ssa_var *var)
|
||||
{
|
||||
|
|
11
Zend/tests/match/match_scdf_cleanup.phpt
Normal file
11
Zend/tests/match/match_scdf_cleanup.phpt
Normal file
|
@ -0,0 +1,11 @@
|
|||
--TEST--
|
||||
Cleanup of basic block kept only because of FREE loop var
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(X||match(X and true or true){false=>X});
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Undefined constant "X" in %smatch_scdf_cleanup.php:2
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %smatch_scdf_cleanup.php on line 2
|
Loading…
Add table
Add a link
Reference in a new issue