summaryrefslogtreecommitdiff
path: root/src/wasm-interpreter.h
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2019-12-16 16:30:05 -0800
committerGitHub <noreply@github.com>2019-12-16 16:30:05 -0800
commit48ccb2bb8a7d013abba4667dfc0fb46548bef2af (patch)
treed9fd6361f11b74670498808180418b275a6c750f /src/wasm-interpreter.h
parent2a972a9457a42b274848ae3e8790333328e65ead (diff)
downloadbinaryen-48ccb2bb8a7d013abba4667dfc0fb46548bef2af.tar.gz
binaryen-48ccb2bb8a7d013abba4667dfc0fb46548bef2af.tar.bz2
binaryen-48ccb2bb8a7d013abba4667dfc0fb46548bef2af.zip
Implement 0-len/drop spec changes in bulk memory (#2529)
This implements recent bulk memory spec changes (WebAssembly/bulk-memory-operations#126) in Binaryen. Now `data.drop` is equivalent to shrinking a segment size to 0, and dropping already dropped segments or active segments (which are thought to be dropped in the beginning) is treated as a no-op. And all bounds checking is performed in advance, so partial copying/filling/initializing does not occur. I tried to implement `visitDataDrop` in the interpreter as `segment.data.clear();`, which is exactly what the revised spec says. I didn't end up doing that because this also deletes all contents from active segments, and there are cases we shouldn't do that: - `wasm-ctor-eval` shouldn't delete active segments, because it will store the changed contents back into segments - When `--fuzz-exec` is given to `wasm-opt`, it runs the module and compare the execution call results before and after transformations. But if running a module will nullify all active segments, applying any transformation to the module or re-running it does not make any sense.
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r--src/wasm-interpreter.h35
1 files changed, 22 insertions, 13 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index caf8a9a3d..5f8296f0d 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1901,18 +1901,22 @@ private:
assert(curr->segment < instance.wasm.memory.segments.size());
Memory::Segment& segment = instance.wasm.memory.segments[curr->segment];
- if (instance.droppedSegments.count(curr->segment)) {
- trap("memory.init of dropped segment");
- }
-
Address destVal(uint32_t(dest.value.geti32()));
Address offsetVal(uint32_t(offset.value.geti32()));
Address sizeVal(uint32_t(size.value.geti32()));
+ if (offsetVal + sizeVal > 0 &&
+ instance.droppedSegments.count(curr->segment)) {
+ trap("out of bounds segment access in memory.init");
+ }
+ if ((uint64_t)offsetVal + sizeVal > segment.data.size()) {
+ trap("out of bounds segment access in memory.init");
+ }
+ if ((uint64_t)destVal + sizeVal >
+ (uint64_t)instance.memorySize * Memory::kPageSize) {
+ trap("out of bounds memory access in memory.init");
+ }
for (size_t i = 0; i < sizeVal; ++i) {
- if (offsetVal + i >= segment.data.size()) {
- trap("out of bounds segment access in memory.init");
- }
Literal addr(uint32_t(destVal + i));
instance.externalInterface->store8(instance.getFinalAddress(addr, 1),
segment.data[offsetVal + i]);
@@ -1921,9 +1925,6 @@ private:
}
Flow visitDataDrop(DataDrop* curr) {
NOTE_ENTER("DataDrop");
- if (instance.droppedSegments.count(curr->segment)) {
- trap("data.drop of dropped segment");
- }
instance.droppedSegments.insert(curr->segment);
return {};
}
@@ -1948,6 +1949,13 @@ private:
Address sourceVal(uint32_t(source.value.geti32()));
Address sizeVal(uint32_t(size.value.geti32()));
+ if ((uint64_t)sourceVal + sizeVal >
+ (uint64_t)instance.memorySize * Memory::kPageSize ||
+ (uint64_t)destVal + sizeVal >
+ (uint64_t)instance.memorySize * Memory::kPageSize) {
+ trap("out of bounds segment access in memory.copy");
+ }
+
int64_t start = 0;
int64_t end = sizeVal;
int step = 1;
@@ -1958,9 +1966,6 @@ private:
step = -1;
}
for (int64_t i = start; i != end; i += step) {
- if (i + destVal >= std::numeric_limits<uint32_t>::max()) {
- trap("Out of bounds memory access");
- }
instance.externalInterface->store8(
instance.getFinalAddress(Literal(uint32_t(destVal + i)), 1),
instance.externalInterface->load8s(
@@ -1988,6 +1993,10 @@ private:
Address destVal(uint32_t(dest.value.geti32()));
Address sizeVal(uint32_t(size.value.geti32()));
+ if ((uint64_t)destVal + sizeVal >
+ (uint64_t)instance.memorySize * Memory::kPageSize) {
+ trap("out of bounds memory access in memory.fill");
+ }
uint8_t val(value.value.geti32());
for (size_t i = 0; i < sizeVal; ++i) {
instance.externalInterface->store8(