From 3c01c679b3e5afca84769f0b6e6a6d5a22759c1e Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 29 Oct 2025 15:14:45 +0100 Subject: [PATCH] Reset Z_EXTRA_P(op2) of ZEND_INIT_FCALL for opcache file cache The offset becomes stale if the environment changes. We're currently relying on other factors in the environment staying constant, e.g. send types. But this seems to be the worst offender. Partially addresses GH-17733 --- ext/opcache/zend_file_cache.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 736d644516a04..328f323d85c94 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -535,13 +535,29 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra } if (opline->op2_type == IS_CONST) { SERIALIZE_PTR(opline->op2.zv); + + /* See GH-17733. Reset Z_EXTRA_P(op2) of ZEND_INIT_FCALL to avoid + * calling incorrect function when environment changes. */ + if (opline->opcode == ZEND_INIT_FCALL) { + zval *op2 = opline->op2.zv; + UNSERIALIZE_PTR(op2); + Z_EXTRA_P(op2) = 0; + ZEND_VM_SET_OPCODE_HANDLER(opline); + } } #else if (opline->op1_type == IS_CONST) { opline->op1.constant = RT_CONSTANT(opline, opline->op1) - literals; } if (opline->op2_type == IS_CONST) { - opline->op2.constant = RT_CONSTANT(opline, opline->op2) - literals; + zval *op2 = RT_CONSTANT(opline, opline->op2); + opline->op2.constant = op2 - literals; + + /* See GH-17733 and comment above. */ + if (opline->opcode == ZEND_INIT_FCALL) { + Z_EXTRA_P(op2) = 0; + ZEND_VM_SET_OPCODE_HANDLER(opline); + } } #endif #if ZEND_USE_ABS_JMP_ADDR