Change the methods
diff --git a/src/ir/runtime-memory.cpp b/src/ir/runtime-memory.cpp index 18fad75..fc6581c 100644 --- a/src/ir/runtime-memory.cpp +++ b/src/ir/runtime-memory.cpp
@@ -28,60 +28,12 @@ throw TrapException{}; } -Address getFinalAddress(Address addr, - Address offset, - Index bytes, - Address memorySizeBytes) { - if (offset > memorySizeBytes) { - std::string msg = "offset > memory: "; - msg += std::to_string(uint64_t(offset)); - msg += " > "; - msg += std::to_string(uint64_t(memorySizeBytes)); - trap(msg); - } - if (addr > memorySizeBytes - offset) { - std::string msg = "final > memory: "; - msg += std::to_string(uint64_t(addr)); - msg += " > "; - msg += std::to_string(uint64_t(memorySizeBytes - offset)); - trap(msg); - } - - addr = size_t(addr) + offset; - - if (bytes > memorySizeBytes - addr) { - std::string msg = "highest > memory: "; - msg += std::to_string(uint64_t(addr)); - msg += " + "; - msg += std::to_string(uint64_t(bytes)); - msg += " > "; - msg += std::to_string(uint64_t(memorySizeBytes)); - trap(msg); - } - return addr; -} - -void checkLoadAddress(Address addr, - Index bytes, - Address memorySizeBytes) { - if (addr > memorySizeBytes || bytes > memorySizeBytes - addr) { - std::string msg = "highest > memory: "; - msg += std::to_string(uint64_t(addr)); - msg += " + "; - msg += std::to_string(uint64_t(bytes)); - msg += " > "; - msg += std::to_string(uint64_t(memorySizeBytes)); - trap(msg); - } -} - -void checkAtomicAddress(Address addr, - Index bytes, - Address memorySizeBytes) { - checkLoadAddress(addr, bytes, memorySizeBytes); +void checkAtomicAddress(const RuntimeMemory& runtimeMemory, + Address finalAddr, + Index bytes) { // Unaligned atomics trap. if (bytes > 1) { - if (addr & (bytes - 1)) { + if (finalAddr & (bytes - 1)) { trap("unaligned atomic operation"); } } @@ -105,9 +57,9 @@ MemoryOrder order, Type type, bool signed_) const { - Address final = getFinalAddress(addr, offset, byteCount, size()); + Address final = validateAddress(addr, offset, byteCount); if (order != MemoryOrder::Unordered) { - checkAtomicAddress(final, byteCount, size()); + checkAtomicAddress(*this, final, byteCount); } switch (type.getBasic()) { case Type::i32: { @@ -168,9 +120,9 @@ MemoryOrder order, Literal value, Type type) { - Address final = getFinalAddress(addr, offset, byteCount, size()); + Address final = validateAddress(addr, offset, byteCount); if (order != MemoryOrder::Unordered) { - checkAtomicAddress(final, byteCount, size()); + checkAtomicAddress(*this, final, byteCount); } switch (type.getBasic()) { case Type::i32: { @@ -259,7 +211,7 @@ if (src > data->data.size() || byteCount > data->data.size() - src) { trap("out of bounds segment access in memory.init"); } - Address final = getFinalAddress(dest, 0, byteCount, size()); + Address final = validateAddress(dest, 0, byteCount); if (byteCount > 0) { std::memcpy(&memory[final], &data->data[src], byteCount); } @@ -269,27 +221,43 @@ Address src, Address byteCount, const RuntimeMemory* srcMemory) { - Address finalDest = getFinalAddress(dest, 0, byteCount, size()); - Address finalSrc = getFinalAddress(src, 0, byteCount, srcMemory->size()); - const std::vector<uint8_t>* srcBuffer = srcMemory->getBuffer(); - if (!srcBuffer) { - // If it's not a memory with a direct buffer, we might need another way to - // access it, or we can just fail if this is the only implementation we - // support for now. - WASM_UNREACHABLE("unsupported srcMemory type in copy"); - } + Address finalDest = validateAddress(dest, 0, byteCount); if (byteCount > 0) { - std::memmove(&memory[finalDest], &(*srcBuffer)[finalSrc], byteCount); + srcMemory->copyTo(&memory[finalDest], src, byteCount); + } else { + // still need to validate src even for 0-byte copy + srcMemory->validateAddress(src, 0, 0); } } void RealRuntimeMemory::fill(Address dest, uint8_t value, Address byteCount) { - Address final = getFinalAddress(dest, 0, byteCount, size()); + Address final = validateAddress(dest, 0, byteCount); if (byteCount > 0) { std::memset(&memory[final], value, byteCount); } } +void RealRuntimeMemory::copyTo(uint8_t* dest, Address src, Address byteCount) const { + Address finalSrc = validateAddress(src, 0, byteCount); + if (byteCount > 0 && dest) { + std::memcpy(dest, &memory[finalSrc], byteCount); + } +} + +Address RealRuntimeMemory::validateAddress(Address addr, Address offset, Address byteCount) const { + Address memorySizeBytes = size(); + if (offset > memorySizeBytes || addr > memorySizeBytes - offset) { + trap("out of bounds memory access"); + } + + addr = size_t(addr) + offset; + + if (byteCount > memorySizeBytes - addr) { + trap("out of bounds memory access"); + } + return addr; +} + void RealRuntimeMemory::resize(size_t newSize) { intendedSize = newSize; const size_t minSize = 1 << 12;
diff --git a/src/ir/runtime-memory.h b/src/ir/runtime-memory.h index 89f3515..eaf4a68 100644 --- a/src/ir/runtime-memory.h +++ b/src/ir/runtime-memory.h
@@ -54,7 +54,9 @@ const Memory* getDefinition() const { return &memoryDefinition; } - virtual const std::vector<uint8_t>* getBuffer() const { return nullptr; } + virtual void copyTo(uint8_t* dest, Address src, Address byteCount) const = 0; + + virtual Address validateAddress(Address addr, Address offset, Address byteCount) const = 0; protected: const Memory memoryDefinition; @@ -96,17 +98,19 @@ void fill(Address dest, uint8_t value, Address byteCount) override; + void copyTo(uint8_t* dest, Address src, Address byteCount) const override; + + Address validateAddress(Address addr, Address offset, Address byteCount) const override; + void resize(size_t newSize); - template<typename T> T get(size_t address) const; - template<typename T> void set(size_t address, T value); - - const std::vector<uint8_t>* getBuffer() const override { return &memory; } - std::vector<uint8_t>& getBuffer() { return memory; } - protected: std::vector<uint8_t> memory; Address intendedSize = 0; + +private: + template<typename T> T get(size_t address) const; + template<typename T> void set(size_t address, T value); }; } // namespace wasm
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 531b470..dc5ef6f 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp
@@ -213,7 +213,7 @@ } void ensureCapacity(Address size) { - if (size > getBuffer().size()) { + if (size > memory.size()) { if (size > 100 * 1024 * 1024) { // MaximumMemory throw FailToEvalException("excessively high memory address accessed"); } @@ -509,10 +509,8 @@ // memory. auto* runtimeMemory = static_cast<CtorEvalRuntimeMemory*>(instance->allMemories[memory->name]); - segment->data.resize(runtimeMemory->getBuffer().size()); - std::memcpy(segment->data.data(), - runtimeMemory->getBuffer().data(), - runtimeMemory->getBuffer().size()); + segment->data.resize(runtimeMemory->size()); + runtimeMemory->copyTo((uint8_t*)segment->data.data(), 0, runtimeMemory->size()); } // Serializing GC data requires more work than linear memory, because