diff --git a/src/compiler/evm_frontend/evm_mir_compiler.cpp b/src/compiler/evm_frontend/evm_mir_compiler.cpp index aefdfad7..5b834371 100644 --- a/src/compiler/evm_frontend/evm_mir_compiler.cpp +++ b/src/compiler/evm_frontend/evm_mir_compiler.cpp @@ -2693,6 +2693,18 @@ EVMMirBuilder::handleMLoad(Operand AddrComponents) { Operand Bytes32Op(MemPtr, EVMType::BYTES32); Operand Result = convertBytes32ToU256Operand(Bytes32Op); + + // Pin loaded values into local variables so the backend cannot reschedule + // the memory reads past later function calls (e.g. CODECOPY / MSTORE) that + // may modify the same memory region. Without this, an MLOAD result that + // stays on the EVM stack across a memory-writing opcode could observe the + // *new* contents instead of the value at the time of the MLOAD. + U256Inst Parts = extractU256Operand(Result); + for (int I = 0; I < static_cast(EVM_ELEMENTS_COUNT); ++I) { + Parts[I] = protectUnsafeValue(Parts[I], I64Type); + } + Result = Operand(Parts, EVMType::UINT256); + #ifdef ZEN_ENABLE_EVM_GAS_REGISTER reloadGasFromMemory(); #endif