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.
This commit is contained in:
Nikita Popov 2021-09-27 16:13:33 +02:00
parent 823888c472
commit 7d483418e2
2 changed files with 20 additions and 0 deletions

View File

@ -0,0 +1,16 @@
--TEST--
Check for correct treatment of relative JMPZNZ offsets when copying opline
--FILE--
<?php
function test($c) {
L1:
if ($c) {
goto L1;
goto L1;
}
}
test(false);
?>
===DONE===
--EXPECT--
===DONE===

View File

@ -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 ||