diff options
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r-- | src/wasm-interpreter.h | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index b38272acd..86d868ac8 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1618,6 +1618,13 @@ public: truncateForPacking(value.getSingleValue(), field); return Flow(); } + + // Arbitrary deterministic limit on size. If we need to allocate a Literals + // vector that takes around 1-2GB of memory then we are likely to hit memory + // limits on 32-bit machines, and in particular on wasm32 VMs that do not + // have 4GB support, so give up there. + static const Index ArrayLimit = (1 << 30) / sizeof(Literal); + Flow visitArrayNew(ArrayNew* curr) { NOTE_ENTER("ArrayNew"); auto rtt = this->visit(curr->rtt); @@ -1630,11 +1637,7 @@ public: } const auto& element = curr->rtt->type.getHeapType().getArray().element; Index num = size.getSingleValue().geti32(); - // Arbitrary deterministic limit on size. If we need to allocate a Literals - // vector that takes around 1-2GB of memory then we are likely to hit memory - // limits on 32-bit machines, and in particular on wasm32 VMs that do not - // have 4GB support, so give up there. - if (num >= (1 << 30) / sizeof(Literal)) { + if (num >= ArrayLimit) { hostLimit("allocation failure"); } Literals data(num); @@ -1715,6 +1718,58 @@ public: } return Literal(int32_t(data->values.size())); } + Flow visitArrayCopy(ArrayCopy* curr) { + NOTE_ENTER("ArrayCopy"); + Flow destRef = this->visit(curr->destRef); + if (destRef.breaking()) { + return destRef; + } + Flow destIndex = this->visit(curr->destIndex); + if (destIndex.breaking()) { + return destIndex; + } + Flow srcRef = this->visit(curr->srcRef); + if (srcRef.breaking()) { + return srcRef; + } + Flow srcIndex = this->visit(curr->srcIndex); + if (srcIndex.breaking()) { + return srcIndex; + } + Flow length = this->visit(curr->length); + if (length.breaking()) { + return length; + } + auto destData = destRef.getSingleValue().getGCData(); + if (!destData) { + trap("null ref"); + } + auto srcData = srcRef.getSingleValue().getGCData(); + if (!srcData) { + trap("null ref"); + } + size_t destVal = destIndex.getSingleValue().getUnsigned(); + size_t srcVal = srcIndex.getSingleValue().getUnsigned(); + size_t lengthVal = length.getSingleValue().getUnsigned(); + if (lengthVal >= ArrayLimit) { + hostLimit("allocation failure"); + } + std::vector<Literal> copied; + copied.resize(lengthVal); + for (size_t i = 0; i < lengthVal; i++) { + if (srcVal + i >= srcData->values.size()) { + trap("oob"); + } + copied[i] = srcData->values[srcVal + i]; + } + for (size_t i = 0; i < lengthVal; i++) { + if (destVal + i >= destData->values.size()) { + trap("oob"); + } + destData->values[destVal + i] = copied[i]; + } + return Flow(); + } Flow visitRefAs(RefAs* curr) { NOTE_ENTER("RefAs"); Flow flow = visit(curr->value); |