Skip to content

Commit 90378aa

Browse files
committed
LibWeb: Throw range error when initial is greater than maximum
constructing WebAssembly.Memory if initial is greater than maximum a range error will be thrown. fixes https://wpt.fyi/results/wasm/jsapi/memory/constructor.any.worker.html?product=ladybird Initial value exceeds maximum
1 parent 9ea8b5a commit 90378aa

File tree

4 files changed

+191
-0
lines changed

4 files changed

+191
-0
lines changed

Libraries/LibWeb/WebAssembly/Memory.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ WebIDL::ExceptionOr<GC::Ref<Memory>> Memory::construct_impl(JS::Realm& realm, Me
2323
auto& vm = realm.vm();
2424

2525
// https://webassembly.github.io/threads/js-api/index.html#dom-memory-memory
26+
// 3. If maximum is not empty and maximum < initial, throw a RangeError exception.
27+
if (descriptor.maximum.has_value()) {
28+
if (descriptor.maximum.value() < descriptor.initial) {
29+
return vm.throw_completion<JS::RangeError>("Initial is larger than maximum."sv);
30+
}
31+
}
32+
2633
// 4. Let share be shared if descriptor["shared"] is true and unshared otherwise.
2734
// 5. If share is shared and maximum is empty, throw a TypeError exception.
2835
auto shared = descriptor.shared.value_or(false);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Harness status: OK
2+
3+
Found 24 tests
4+
5+
24 Pass
6+
Pass name
7+
Pass length
8+
Pass No arguments
9+
Pass Calling
10+
Pass Invalid descriptor argument
11+
Pass Undefined initial value in descriptor
12+
Pass Out-of-range initial value in descriptor: NaN
13+
Pass Out-of-range maximum value in descriptor: NaN
14+
Pass Out-of-range initial value in descriptor: Infinity
15+
Pass Out-of-range maximum value in descriptor: Infinity
16+
Pass Out-of-range initial value in descriptor: -Infinity
17+
Pass Out-of-range maximum value in descriptor: -Infinity
18+
Pass Out-of-range initial value in descriptor: -1
19+
Pass Out-of-range maximum value in descriptor: -1
20+
Pass Out-of-range initial value in descriptor: 4294967296
21+
Pass Out-of-range maximum value in descriptor: 4294967296
22+
Pass Out-of-range initial value in descriptor: 68719476736
23+
Pass Out-of-range maximum value in descriptor: 68719476736
24+
Pass Initial value exceeds maximum
25+
Pass Proxy descriptor
26+
Pass Order of evaluation for descriptor
27+
Pass Zero initial
28+
Pass Non-zero initial
29+
Pass Stray argument
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!doctype html>
2+
<meta charset=utf-8>
3+
4+
<script>
5+
self.GLOBAL = {
6+
isWindow: function() { return true; },
7+
isWorker: function() { return false; },
8+
isShadowRealm: function() { return false; },
9+
};
10+
</script>
11+
<script src="../../../resources/testharness.js"></script>
12+
<script src="../../../resources/testharnessreport.js"></script>
13+
<script src="../../../wasm/jsapi/assertions.js"></script>
14+
<script src="../../../wasm/jsapi/memory/assertions.js"></script>
15+
<div id=log></div>
16+
<script src="../../../wasm/jsapi/memory/constructor.any.js"></script>
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// META: global=window,dedicatedworker,jsshell,shadowrealm
2+
// META: script=/wasm/jsapi/assertions.js
3+
// META: script=/wasm/jsapi/memory/assertions.js
4+
5+
test(() => {
6+
assert_function_name(WebAssembly.Memory, "Memory", "WebAssembly.Memory");
7+
}, "name");
8+
9+
test(() => {
10+
assert_function_length(WebAssembly.Memory, 1, "WebAssembly.Memory");
11+
}, "length");
12+
13+
test(() => {
14+
assert_throws_js(TypeError, () => new WebAssembly.Memory());
15+
}, "No arguments");
16+
17+
test(() => {
18+
const argument = { "initial": 0 };
19+
assert_throws_js(TypeError, () => WebAssembly.Memory(argument));
20+
}, "Calling");
21+
22+
test(() => {
23+
const invalidArguments = [
24+
undefined,
25+
null,
26+
false,
27+
true,
28+
"",
29+
"test",
30+
Symbol(),
31+
1,
32+
NaN,
33+
{},
34+
];
35+
for (const invalidArgument of invalidArguments) {
36+
assert_throws_js(TypeError,
37+
() => new WebAssembly.Memory(invalidArgument),
38+
`new Memory(${format_value(invalidArgument)})`);
39+
}
40+
}, "Invalid descriptor argument");
41+
42+
test(() => {
43+
assert_throws_js(TypeError, () => new WebAssembly.Memory({ "initial": undefined }));
44+
}, "Undefined initial value in descriptor");
45+
46+
const outOfRangeValues = [
47+
NaN,
48+
Infinity,
49+
-Infinity,
50+
-1,
51+
0x100000000,
52+
0x1000000000,
53+
];
54+
55+
for (const value of outOfRangeValues) {
56+
test(() => {
57+
assert_throws_js(TypeError, () => new WebAssembly.Memory({ "initial": value }));
58+
}, `Out-of-range initial value in descriptor: ${format_value(value)}`);
59+
60+
test(() => {
61+
assert_throws_js(TypeError, () => new WebAssembly.Memory({ "initial": 0, "maximum": value }));
62+
}, `Out-of-range maximum value in descriptor: ${format_value(value)}`);
63+
}
64+
65+
test(() => {
66+
assert_throws_js(RangeError, () => new WebAssembly.Memory({ "initial": 10, "maximum": 9 }));
67+
}, "Initial value exceeds maximum");
68+
69+
test(() => {
70+
const proxy = new Proxy({}, {
71+
has(o, x) {
72+
assert_unreached(`Should not call [[HasProperty]] with ${x}`);
73+
},
74+
get(o, x) {
75+
// Due to the requirement not to supply both minimum and initial, we need to ignore one of them.
76+
switch (x) {
77+
case "shared":
78+
return false;
79+
case "initial":
80+
case "maximum":
81+
return 0;
82+
default:
83+
return undefined;
84+
}
85+
},
86+
});
87+
new WebAssembly.Memory(proxy);
88+
}, "Proxy descriptor");
89+
90+
test(() => {
91+
const order = [];
92+
93+
new WebAssembly.Memory({
94+
get maximum() {
95+
order.push("maximum");
96+
return {
97+
valueOf() {
98+
order.push("maximum valueOf");
99+
return 1;
100+
},
101+
};
102+
},
103+
104+
get initial() {
105+
order.push("initial");
106+
return {
107+
valueOf() {
108+
order.push("initial valueOf");
109+
return 1;
110+
},
111+
};
112+
},
113+
});
114+
115+
assert_array_equals(order, [
116+
"initial",
117+
"initial valueOf",
118+
"maximum",
119+
"maximum valueOf",
120+
]);
121+
}, "Order of evaluation for descriptor");
122+
123+
test(() => {
124+
const argument = { "initial": 0 };
125+
const memory = new WebAssembly.Memory(argument);
126+
assert_Memory(memory, { "size": 0 });
127+
}, "Zero initial");
128+
129+
test(() => {
130+
const argument = { "initial": 4 };
131+
const memory = new WebAssembly.Memory(argument);
132+
assert_Memory(memory, { "size": 4 });
133+
}, "Non-zero initial");
134+
135+
test(() => {
136+
const argument = { "initial": 0 };
137+
const memory = new WebAssembly.Memory(argument, {});
138+
assert_Memory(memory, { "size": 0 });
139+
}, "Stray argument");

0 commit comments

Comments
 (0)