| 62 | } |
| 63 | |
| 64 | Expect<void> |
| 65 | Executor::runMemoryCopyOp(Runtime::StackManager &StackMgr, |
| 66 | Runtime::Instance::MemoryInstance &MemInstDst, |
| 67 | Runtime::Instance::MemoryInstance &MemInstSrc, |
| 68 | const AST::Instruction &Instr) { |
| 69 | // Pop the length, source, and destination from the stack. |
| 70 | const auto AddrType1 = MemInstSrc.getMemoryType().getLimit().getAddrType(); |
| 71 | const auto AddrType2 = MemInstDst.getMemoryType().getLimit().getAddrType(); |
| 72 | uint64_t Len = extractAddr(StackMgr.pop(), std::min(AddrType1, AddrType2)); |
| 73 | uint64_t Src = extractAddr(StackMgr.pop(), AddrType2); |
| 74 | uint64_t Dst = extractAddr(StackMgr.pop(), AddrType1); |
| 75 | |
| 76 | // Replace mem[Dst : Dst + Len] with mem[Src : Src + Len]. |
| 77 | // When source and destination are the same memory instance, overlapping |
| 78 | // regions require memmove semantics per the Wasm spec. |
| 79 | if (&MemInstSrc == &MemInstDst) { |
| 80 | // Same memory: validate bounds, then use memmove for overlap safety. |
| 81 | EXPECTED_TRY(MemInstSrc.getBytes(Src, Len).map_error([&Instr](auto E) { |
| 82 | spdlog::error( |
| 83 | ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); |
| 84 | return E; |
| 85 | })); |
| 86 | EXPECTED_TRY(MemInstDst.getBytes(Dst, Len).map_error([&Instr](auto E) { |
| 87 | spdlog::error( |
| 88 | ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); |
| 89 | return E; |
| 90 | })); |
| 91 | if (likely(Len > 0)) { |
| 92 | std::memmove(MemInstDst.getDataPtr() + Dst, MemInstSrc.getDataPtr() + Src, |
| 93 | Len); |
| 94 | } |
| 95 | return {}; |
| 96 | } else { |
| 97 | // Different memories: no overlap possible, use the existing path. |
| 98 | EXPECTED_TRY(auto Data, |
| 99 | MemInstSrc.getBytes(Src, Len).map_error([&Instr](auto E) { |
| 100 | spdlog::error(ErrInfo::InfoInstruction(Instr.getOpCode(), |
| 101 | Instr.getOffset())); |
| 102 | return E; |
| 103 | })); |
| 104 | return MemInstDst.setBytes(Data, Dst, 0, Len).map_error([&Instr](auto E) { |
| 105 | spdlog::error( |
| 106 | ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset())); |
| 107 | return E; |
| 108 | }); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | Expect<void> |
| 113 | Executor::runMemoryFillOp(Runtime::StackManager &StackMgr, |
nothing calls this directly
no test coverage detected