diff options
author | Alon Zakai <azakai@google.com> | 2024-12-02 12:20:55 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-02 12:20:55 -0800 |
commit | 31c988b30556ef000bd2212754d7fc5beebf08d2 (patch) | |
tree | a8e3b30ad12c71aade983b9dc393b0cbc13556d7 | |
parent | b1c5a007f3986c11916e8ac4a84c41c01d5e04bb (diff) | |
download | binaryen-31c988b30556ef000bd2212754d7fc5beebf08d2.tar.gz binaryen-31c988b30556ef000bd2212754d7fc5beebf08d2.tar.bz2 binaryen-31c988b30556ef000bd2212754d7fc5beebf08d2.zip |
[GC] Fix trapping on array.new_data of dropped segments of offset > 0 (#7124)
Even if the size is 0, if the offset is > 0 then we should trap.
-rw-r--r-- | src/wasm-interpreter.h | 15 | ||||
-rw-r--r-- | test/lit/exec/array.wast | 21 |
2 files changed, 33 insertions, 3 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 81531e27c..937248d81 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -4022,16 +4022,25 @@ public: const auto& seg = *wasm.getDataSegment(curr->segment); auto elemBytes = element.getByteSize(); - auto end = offset + size * elemBytes; - if ((size != 0ull && droppedDataSegments.count(curr->segment)) || - end > seg.data.size()) { + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" + + uint64_t end; + if (std::ckd_add(&end, offset, size * elemBytes) || end > seg.data.size()) { trap("out of bounds segment access in array.new_data"); } + if (droppedDataSegments.count(curr->segment) && end > 0) { + trap("dropped segment access in array.new_data"); + } contents.reserve(size); for (Index i = offset; i < end; i += elemBytes) { auto addr = (void*)&seg.data[i]; contents.push_back(this->makeFromMemory(addr, element)); } + +#pragma GCC diagnostic pop + return self()->makeGCData(std::move(contents), curr->type); } Flow visitArrayNewElem(ArrayNewElem* curr) { diff --git a/test/lit/exec/array.wast b/test/lit/exec/array.wast index ff10c555c..d70af1ddc 100644 --- a/test/lit/exec/array.wast +++ b/test/lit/exec/array.wast @@ -13,6 +13,8 @@ (elem $passive $func) + (data $data "a") + ;; CHECK: [fuzz-exec] calling func ;; CHECK-NEXT: [fuzz-exec] note result: func => 1 (func $func (export "func") (result i32) @@ -98,6 +100,21 @@ (i32.const 0) ) ) + + ;; CHECK: [fuzz-exec] calling drop_array.new_data + ;; CHECK-NEXT: [trap dropped segment access in array.new_data] + (func $drop_array.new_data (export "drop_array.new_data") + ;; Dropping the data segment causes the next instruction to trap, even though + ;; the size there is 0, because the offset is > 0. + (data.drop $data) + (drop + (array.new_data $array $data + (i32.const 1) + (i32.const 0) + ) + ) + ) + ) ;; CHECK: [fuzz-exec] calling func ;; CHECK-NEXT: [fuzz-exec] note result: func => 1 @@ -115,6 +132,10 @@ ;; CHECK: [fuzz-exec] calling init_active_in_bounds ;; CHECK: [fuzz-exec] calling init_passive + +;; CHECK: [fuzz-exec] calling drop_array.new_data +;; CHECK-NEXT: [trap dropped segment access in array.new_data] +;; CHECK-NEXT: [fuzz-exec] comparing drop_array.new_data ;; CHECK-NEXT: [fuzz-exec] comparing func ;; CHECK-NEXT: [fuzz-exec] comparing init_active ;; CHECK-NEXT: [fuzz-exec] comparing init_active_in_bounds |