@@ -28,60 +28,12 @@ namespace {
2828 throw TrapException{};
2929}
3030
31- Address getFinalAddress (Address addr,
32- Address offset,
33- Index bytes,
34- Address memorySizeBytes) {
35- if (offset > memorySizeBytes) {
36- std::string msg = " offset > memory: " ;
37- msg += std::to_string (uint64_t (offset));
38- msg += " > " ;
39- msg += std::to_string (uint64_t (memorySizeBytes));
40- trap (msg);
41- }
42- if (addr > memorySizeBytes - offset) {
43- std::string msg = " final > memory: " ;
44- msg += std::to_string (uint64_t (addr));
45- msg += " > " ;
46- msg += std::to_string (uint64_t (memorySizeBytes - offset));
47- trap (msg);
48- }
49-
50- addr = size_t (addr) + offset;
51-
52- if (bytes > memorySizeBytes - addr) {
53- std::string msg = " highest > memory: " ;
54- msg += std::to_string (uint64_t (addr));
55- msg += " + " ;
56- msg += std::to_string (uint64_t (bytes));
57- msg += " > " ;
58- msg += std::to_string (uint64_t (memorySizeBytes));
59- trap (msg);
60- }
61- return addr;
62- }
63-
64- void checkLoadAddress (Address addr,
65- Index bytes,
66- Address memorySizeBytes) {
67- if (addr > memorySizeBytes || bytes > memorySizeBytes - addr) {
68- std::string msg = " highest > memory: " ;
69- msg += std::to_string (uint64_t (addr));
70- msg += " + " ;
71- msg += std::to_string (uint64_t (bytes));
72- msg += " > " ;
73- msg += std::to_string (uint64_t (memorySizeBytes));
74- trap (msg);
75- }
76- }
77-
78- void checkAtomicAddress (Address addr,
79- Index bytes,
80- Address memorySizeBytes) {
81- checkLoadAddress (addr, bytes, memorySizeBytes);
31+ void checkAtomicAddress (const RuntimeMemory& runtimeMemory,
32+ Address finalAddr,
33+ Index bytes) {
8234 // Unaligned atomics trap.
8335 if (bytes > 1 ) {
84- if (addr & (bytes - 1 )) {
36+ if (finalAddr & (bytes - 1 )) {
8537 trap (" unaligned atomic operation" );
8638 }
8739 }
@@ -105,9 +57,9 @@ Literal RealRuntimeMemory::load(Address addr,
10557 MemoryOrder order,
10658 Type type,
10759 bool signed_) const {
108- Address final = getFinalAddress (addr, offset, byteCount, size () );
60+ Address final = validateAddress (addr, offset, byteCount);
10961 if (order != MemoryOrder::Unordered) {
110- checkAtomicAddress (final , byteCount, size () );
62+ checkAtomicAddress (* this , final , byteCount );
11163 }
11264 switch (type.getBasic ()) {
11365 case Type::i32 : {
@@ -168,9 +120,9 @@ void RealRuntimeMemory::store(Address addr,
168120 MemoryOrder order,
169121 Literal value,
170122 Type type) {
171- Address final = getFinalAddress (addr, offset, byteCount, size () );
123+ Address final = validateAddress (addr, offset, byteCount);
172124 if (order != MemoryOrder::Unordered) {
173- checkAtomicAddress (final , byteCount, size () );
125+ checkAtomicAddress (* this , final , byteCount );
174126 }
175127 switch (type.getBasic ()) {
176128 case Type::i32 : {
@@ -259,7 +211,7 @@ void RealRuntimeMemory::init(Address dest,
259211 if (src > data->data .size () || byteCount > data->data .size () - src) {
260212 trap (" out of bounds segment access in memory.init" );
261213 }
262- Address final = getFinalAddress (dest, 0 , byteCount, size () );
214+ Address final = validateAddress (dest, 0 , byteCount);
263215 if (byteCount > 0 ) {
264216 std::memcpy (&memory[final ], &data->data [src], byteCount);
265217 }
@@ -269,27 +221,43 @@ void RealRuntimeMemory::copy(Address dest,
269221 Address src,
270222 Address byteCount,
271223 const RuntimeMemory* srcMemory) {
272- Address finalDest = getFinalAddress (dest, 0 , byteCount, size ());
273- Address finalSrc = getFinalAddress (src, 0 , byteCount, srcMemory->size ());
274- const std::vector<uint8_t >* srcBuffer = srcMemory->getBuffer ();
275- if (!srcBuffer) {
276- // If it's not a memory with a direct buffer, we might need another way to
277- // access it, or we can just fail if this is the only implementation we
278- // support for now.
279- WASM_UNREACHABLE (" unsupported srcMemory type in copy" );
280- }
224+ Address finalDest = validateAddress (dest, 0 , byteCount);
281225 if (byteCount > 0 ) {
282- std::memmove (&memory[finalDest], &(*srcBuffer)[finalSrc], byteCount);
226+ srcMemory->copyTo (&memory[finalDest], src, byteCount);
227+ } else {
228+ // still need to validate src even for 0-byte copy
229+ srcMemory->validateAddress (src, 0 , 0 );
283230 }
284231}
285232
286233void RealRuntimeMemory::fill (Address dest, uint8_t value, Address byteCount) {
287- Address final = getFinalAddress (dest, 0 , byteCount, size () );
234+ Address final = validateAddress (dest, 0 , byteCount);
288235 if (byteCount > 0 ) {
289236 std::memset (&memory[final ], value, byteCount);
290237 }
291238}
292239
240+ void RealRuntimeMemory::copyTo (uint8_t * dest, Address src, Address byteCount) const {
241+ Address finalSrc = validateAddress (src, 0 , byteCount);
242+ if (byteCount > 0 && dest) {
243+ std::memcpy (dest, &memory[finalSrc], byteCount);
244+ }
245+ }
246+
247+ Address RealRuntimeMemory::validateAddress (Address addr, Address offset, Address byteCount) const {
248+ Address memorySizeBytes = size ();
249+ if (offset > memorySizeBytes || addr > memorySizeBytes - offset) {
250+ trap (" out of bounds memory access" );
251+ }
252+
253+ addr = size_t (addr) + offset;
254+
255+ if (byteCount > memorySizeBytes - addr) {
256+ trap (" out of bounds memory access" );
257+ }
258+ return addr;
259+ }
260+
293261void RealRuntimeMemory::resize (size_t newSize) {
294262 intendedSize = newSize;
295263 const size_t minSize = 1 << 12 ;
0 commit comments