Skip to content

Commit 31c988b

Browse files
authored
[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.
1 parent b1c5a00 commit 31c988b

2 files changed

Lines changed: 33 additions & 3 deletions

File tree

src/wasm-interpreter.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4022,16 +4022,25 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
40224022

40234023
const auto& seg = *wasm.getDataSegment(curr->segment);
40244024
auto elemBytes = element.getByteSize();
4025-
auto end = offset + size * elemBytes;
4026-
if ((size != 0ull && droppedDataSegments.count(curr->segment)) ||
4027-
end > seg.data.size()) {
4025+
4026+
#pragma GCC diagnostic push
4027+
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
4028+
4029+
uint64_t end;
4030+
if (std::ckd_add(&end, offset, size * elemBytes) || end > seg.data.size()) {
40284031
trap("out of bounds segment access in array.new_data");
40294032
}
4033+
if (droppedDataSegments.count(curr->segment) && end > 0) {
4034+
trap("dropped segment access in array.new_data");
4035+
}
40304036
contents.reserve(size);
40314037
for (Index i = offset; i < end; i += elemBytes) {
40324038
auto addr = (void*)&seg.data[i];
40334039
contents.push_back(this->makeFromMemory(addr, element));
40344040
}
4041+
4042+
#pragma GCC diagnostic pop
4043+
40354044
return self()->makeGCData(std::move(contents), curr->type);
40364045
}
40374046
Flow visitArrayNewElem(ArrayNewElem* curr) {

test/lit/exec/array.wast

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
(elem $passive $func)
1515

16+
(data $data "a")
17+
1618
;; CHECK: [fuzz-exec] calling func
1719
;; CHECK-NEXT: [fuzz-exec] note result: func => 1
1820
(func $func (export "func") (result i32)
@@ -98,6 +100,21 @@
98100
(i32.const 0)
99101
)
100102
)
103+
104+
;; CHECK: [fuzz-exec] calling drop_array.new_data
105+
;; CHECK-NEXT: [trap dropped segment access in array.new_data]
106+
(func $drop_array.new_data (export "drop_array.new_data")
107+
;; Dropping the data segment causes the next instruction to trap, even though
108+
;; the size there is 0, because the offset is > 0.
109+
(data.drop $data)
110+
(drop
111+
(array.new_data $array $data
112+
(i32.const 1)
113+
(i32.const 0)
114+
)
115+
)
116+
)
117+
101118
)
102119
;; CHECK: [fuzz-exec] calling func
103120
;; CHECK-NEXT: [fuzz-exec] note result: func => 1
@@ -115,6 +132,10 @@
115132
;; CHECK: [fuzz-exec] calling init_active_in_bounds
116133

117134
;; CHECK: [fuzz-exec] calling init_passive
135+
136+
;; CHECK: [fuzz-exec] calling drop_array.new_data
137+
;; CHECK-NEXT: [trap dropped segment access in array.new_data]
138+
;; CHECK-NEXT: [fuzz-exec] comparing drop_array.new_data
118139
;; CHECK-NEXT: [fuzz-exec] comparing func
119140
;; CHECK-NEXT: [fuzz-exec] comparing init_active
120141
;; CHECK-NEXT: [fuzz-exec] comparing init_active_in_bounds

0 commit comments

Comments
 (0)