From 7d483418e21b8c250f03cbef6480e34e428e6f53 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 27 Sep 2021 16:13:33 +0200 Subject: [PATCH] Fix relative offsets when copying JMPZNZ This was doing a plain copy of JMPZNZ, even though it encodes offsets relative to the opline. As such, the offsets would be relative to target, while they should be relative to opline. Fix this by recomputing them. Fixes oss-fuzz #39295. --- Zend/tests/jmpznz_relative_offsets.phpt | 16 ++++++++++++++++ ext/opcache/Optimizer/pass3.c | 4 ++++ 2 files changed, 20 insertions(+) create mode 100644 Zend/tests/jmpznz_relative_offsets.phpt diff --git a/Zend/tests/jmpznz_relative_offsets.phpt b/Zend/tests/jmpznz_relative_offsets.phpt new file mode 100644 index 00000000000..c6b67b23f27 --- /dev/null +++ b/Zend/tests/jmpznz_relative_offsets.phpt @@ -0,0 +1,16 @@ +--TEST-- +Check for correct treatment of relative JMPZNZ offsets when copying opline +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c index f98c41848c2..1b508a5da2f 100644 --- a/ext/opcache/Optimizer/pass3.c +++ b/ext/opcache/Optimizer/pass3.c @@ -95,6 +95,10 @@ void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx) ZVAL_COPY(&zv, &ZEND_OP1_LITERAL(opline)); opline->op1.constant = zend_optimizer_add_literal(op_array, &zv); } + /* Jump addresses may be encoded as offsets, recompute them. */ + ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target)); + opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, + ZEND_OFFSET_TO_OPLINE(target, target->extended_value)); goto optimize_jmpznz; } else if ((target->opcode == ZEND_RETURN || target->opcode == ZEND_RETURN_BY_REF ||