diff --git a/NEWS b/NEWS index a55358c265d..882a17d2ed3 100644 --- a/NEWS +++ b/NEWS @@ -55,6 +55,8 @@ PHP NEWS . Fixed bug GH-19875 (JIT 1205 segfault on large file compiled in subprocess). (Arnaud) . Fixed bug GH-20012 (heap buffer overflow in jit). (Arnaud) + . Partially fixed bug GH-17733 (Avoid calling wrong function when reusing file + caches across differing environments). (ilutov) - PgSql: . Fix memory leak when first string conversion fails. (nielsdos) diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 736d644516a..36ab3f6c9ae 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -535,13 +535,32 @@ 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, which + * is an offset into the global function table, to avoid calling + * incorrect functions when environment changes. This, and the + * equivalent code below, can be removed once proper system ID + * validation is implemented. */ + 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