From 53df29bc29e8dd52f7dbc9edf76374727761a716 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 8 Nov 2021 14:51:04 +0100 Subject: [PATCH] Drop pi nodes for both old/new pred in replace_predecessor We also need to drop pi nodes for new_pred here, as the pi node restriction for new_pred is not necessarily true for control coming from old_pred as well. Fixes oss-fuzz #40782. --- Zend/tests/replace_pred_pi_node.phpt | 5 +++++ ext/opcache/Optimizer/dfa_pass.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Zend/tests/replace_pred_pi_node.phpt b/Zend/tests/replace_pred_pi_node.phpt index fa12b28b1e8..446baf3fcc5 100644 --- a/Zend/tests/replace_pred_pi_node.phpt +++ b/Zend/tests/replace_pred_pi_node.phpt @@ -7,6 +7,11 @@ function test(bool $a, bool $b) { if ($a && $byte > 0 && $b) {} unknown($byte); } +function test2() { + foreach (0 as $v) { + $v ??= 0; + } +} ?> ===DONE=== --EXPECT-- diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index f118fa7fcbb..aff91f554f2 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -596,7 +596,7 @@ static void replace_predecessor(zend_ssa *ssa, int block_id, int old_pred, int n /* Also remove the corresponding phi node entries */ for (phi = ssa->blocks[block_id].phis; phi; phi = phi->next) { if (phi->pi >= 0) { - if (phi->pi == old_pred) { + if (phi->pi == old_pred || phi->pi == new_pred) { zend_ssa_rename_var_uses( ssa, phi->ssa_var, phi->sources[0], /* update_types */ 0); zend_ssa_remove_phi(ssa, phi);