From fcff846a73de03fe02fc2fca2e212cbc12feb945 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 9 Feb 2026 13:22:35 +0100 Subject: [PATCH] Fix borked FETCH_W+ZEND_FETCH_GLOBAL_LOCK optimization (GH-21121) Fixes OSS-Fuzz #481014628 Introduced in GH-20628 Co-authored-by: Arnaud Le Blanc <365207+arnaud-lb@users.noreply.github.com> --- Zend/Optimizer/block_pass.c | 4 +++- ext/opcache/tests/oss-fuzz-481014628.phpt | 27 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/oss-fuzz-481014628.phpt diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index 7f97caa1fda..5a0af263039 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -176,7 +176,9 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array && zend_optimizer_update_op1_const(op_array, opline, &c)) { VAR_SOURCE(op1) = NULL; if (opline->opcode != ZEND_JMP_NULL - && !zend_bitset_in(used_ext, VAR_NUM(src->result.var))) { + && !zend_bitset_in(used_ext, VAR_NUM(src->result.var)) + /* FETCH_W with ZEND_FETCH_GLOBAL_LOCK does not free op1, which will be used again. */ + && !(opline->opcode == ZEND_FETCH_W && (opline->extended_value & ZEND_FETCH_GLOBAL_LOCK))) { literal_dtor(&ZEND_OP1_LITERAL(src)); MAKE_NOP(src); } diff --git a/ext/opcache/tests/oss-fuzz-481014628.phpt b/ext/opcache/tests/oss-fuzz-481014628.phpt new file mode 100644 index 00000000000..8aa6cf3fe1f --- /dev/null +++ b/ext/opcache/tests/oss-fuzz-481014628.phpt @@ -0,0 +1,27 @@ +--TEST-- +OSS-Fuzz #481014628: Borked FETCH_W+ZEND_FETCH_GLOBAL_LOCK optimization +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- + +--EXPECT-- +NULL +int(42)