1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix block_pass JMP[N]Z optimization

In the following optimization:

JMPZ(X,L1) JMP(L2) L1: -> JMPNZ(X,L2) NOP

L1 must not be followed by another block, so that it may safely be followed by
the block containing the JMPNZ. get_next_block() is used to verify L1 is the
direct follower. This function also skips empty blocks, including live, empty
target blocks, which will then implicitly follow the new follow block. This will
result in L1 being followed by two separate blocks, which is not possible.

Resolve this by get_next_block() stopping at target blocks.

Fixes OSS-Fuzz #472563272
Closes GH-20850
This commit is contained in:
Ilija Tovilo
2026-01-06 00:01:51 +01:00
parent 6f6c9e35e8
commit f61b1fc036
3 changed files with 16 additions and 1 deletions

1
NEWS
View File

@@ -6,6 +6,7 @@ PHP NEWS
. Fixed bug GH-20837 (NULL dereference when calling ob_start() in shutdown
function triggered by bailout in php_output_lock_error()). (timwolla)
. Fix OSS-Fuzz #471533782 (Infinite loop in GC destructor fiber). (ilutov)
. Fix OSS-Fuzz #472563272 (Borked block_pass JMP[N]Z optimization). (ilutov)
- MbString:
. Fixed bug GH-20833 (mb_str_pad() divide by zero if padding string is

View File

@@ -1152,7 +1152,7 @@ static zend_always_inline zend_basic_block *get_next_block(const zend_cfg *cfg,
}
next_block++;
}
while (next_block->len == 0 && !(next_block->flags & ZEND_BB_PROTECTED)) {
while (next_block->len == 0 && !(next_block->flags & (ZEND_BB_TARGET|ZEND_BB_PROTECTED))) {
next_block = cfg->blocks + next_block->successors[0];
}
return next_block;

View File

@@ -0,0 +1,14 @@
--TEST--
OSS-Fuzz #472563272: Borked block_pass JMP[N]Z optimization
--EXTENSIONS--
opcache
--INI--
opcache.enable=1
opcache.enable_cli=1
--FILE--
<?php
false || (true ? true : false) || (false ? true : false) || true;
?>
===DONE===
--EXPECT--
===DONE===