1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 *
4 * Copyright 2016 Mozilla Foundation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include "wasm/WasmValidate.h"
20
21 #include "mozilla/CheckedInt.h"
22 #include "mozilla/Utf8.h"
23
24 #include "jit/JitOptions.h"
25 #include "js/Printf.h"
26 #include "js/String.h" // JS::MaxStringLength
27 #include "vm/JSContext.h"
28 #include "vm/Realm.h"
29 #include "wasm/WasmOpIter.h"
30
31 using namespace js;
32 using namespace js::jit;
33 using namespace js::wasm;
34
35 using mozilla::AsChars;
36 using mozilla::CheckedInt;
37 using mozilla::CheckedInt32;
38 using mozilla::IsUtf8;
39 using mozilla::Span;
40
41 // Misc helpers.
42
EncodeLocalEntries(Encoder & e,const ValTypeVector & locals)43 bool wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals) {
44 if (locals.length() > MaxLocals) {
45 return false;
46 }
47
48 uint32_t numLocalEntries = 0;
49 if (locals.length()) {
50 ValType prev = locals[0];
51 numLocalEntries++;
52 for (ValType t : locals) {
53 if (t != prev) {
54 numLocalEntries++;
55 prev = t;
56 }
57 }
58 }
59
60 if (!e.writeVarU32(numLocalEntries)) {
61 return false;
62 }
63
64 if (numLocalEntries) {
65 ValType prev = locals[0];
66 uint32_t count = 1;
67 for (uint32_t i = 1; i < locals.length(); i++, count++) {
68 if (prev != locals[i]) {
69 if (!e.writeVarU32(count)) {
70 return false;
71 }
72 if (!e.writeValType(prev)) {
73 return false;
74 }
75 prev = locals[i];
76 count = 0;
77 }
78 }
79 if (!e.writeVarU32(count)) {
80 return false;
81 }
82 if (!e.writeValType(prev)) {
83 return false;
84 }
85 }
86
87 return true;
88 }
89
DecodeLocalEntries(Decoder & d,const TypeContext & types,const FeatureArgs & features,ValTypeVector * locals)90 bool wasm::DecodeLocalEntries(Decoder& d, const TypeContext& types,
91 const FeatureArgs& features,
92 ValTypeVector* locals) {
93 uint32_t numLocalEntries;
94 if (!d.readVarU32(&numLocalEntries)) {
95 return d.fail("failed to read number of local entries");
96 }
97
98 for (uint32_t i = 0; i < numLocalEntries; i++) {
99 uint32_t count;
100 if (!d.readVarU32(&count)) {
101 return d.fail("failed to read local entry count");
102 }
103
104 if (MaxLocals - locals->length() < count) {
105 return d.fail("too many locals");
106 }
107
108 ValType type;
109 if (!d.readValType(types, features, &type)) {
110 return false;
111 }
112
113 if (!type.isDefaultable()) {
114 return d.fail("cannot have a non-defaultable local");
115 }
116
117 if (!locals->appendN(type, count)) {
118 return false;
119 }
120 }
121
122 return true;
123 }
124
DecodeValidatedLocalEntries(Decoder & d,ValTypeVector * locals)125 bool wasm::DecodeValidatedLocalEntries(Decoder& d, ValTypeVector* locals) {
126 uint32_t numLocalEntries;
127 MOZ_ALWAYS_TRUE(d.readVarU32(&numLocalEntries));
128
129 for (uint32_t i = 0; i < numLocalEntries; i++) {
130 uint32_t count = d.uncheckedReadVarU32();
131 MOZ_ASSERT(MaxLocals - locals->length() >= count);
132 if (!locals->appendN(d.uncheckedReadValType(), count)) {
133 return false;
134 }
135 }
136
137 return true;
138 }
139
CheckIsSubtypeOf(Decoder & d,const ModuleEnvironment & env,size_t opcodeOffset,ValType actual,ValType expected,TypeCache * cache)140 bool wasm::CheckIsSubtypeOf(Decoder& d, const ModuleEnvironment& env,
141 size_t opcodeOffset, ValType actual,
142 ValType expected, TypeCache* cache) {
143 switch (env.types.isSubtypeOf(actual, expected, cache)) {
144 case TypeResult::OOM:
145 return false;
146 case TypeResult::True:
147 return true;
148 case TypeResult::False: {
149 UniqueChars actualText = ToString(actual);
150 if (!actualText) {
151 return false;
152 }
153
154 UniqueChars expectedText = ToString(expected);
155 if (!expectedText) {
156 return false;
157 }
158
159 UniqueChars error(
160 JS_smprintf("type mismatch: expression has type %s but expected %s",
161 actualText.get(), expectedText.get()));
162 if (!error) {
163 return false;
164 }
165
166 return d.fail(opcodeOffset, error.get());
167 }
168 default:
169 MOZ_CRASH();
170 }
171 }
172
173 // Function body validation.
174
DecodeFunctionBodyExprs(const ModuleEnvironment & env,uint32_t funcIndex,const ValTypeVector & locals,const uint8_t * bodyEnd,Decoder * d)175 static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env,
176 uint32_t funcIndex,
177 const ValTypeVector& locals,
178 const uint8_t* bodyEnd, Decoder* d) {
179 ValidatingOpIter iter(env, *d);
180
181 if (!iter.startFunction(funcIndex)) {
182 return false;
183 }
184
185 #define CHECK(c) \
186 if (!(c)) return false; \
187 break
188
189 while (true) {
190 OpBytes op;
191 if (!iter.readOp(&op)) {
192 return false;
193 }
194
195 Nothing nothing;
196 NothingVector nothings{};
197 ResultType unusedType;
198
199 switch (op.b0) {
200 case uint16_t(Op::End): {
201 LabelKind unusedKind;
202 if (!iter.readEnd(&unusedKind, &unusedType, ¬hings, ¬hings)) {
203 return false;
204 }
205 iter.popEnd();
206 if (iter.controlStackEmpty()) {
207 return iter.endFunction(bodyEnd);
208 }
209 break;
210 }
211 case uint16_t(Op::Nop):
212 CHECK(iter.readNop());
213 case uint16_t(Op::Drop):
214 CHECK(iter.readDrop());
215 case uint16_t(Op::Call): {
216 uint32_t unusedIndex;
217 NothingVector unusedArgs{};
218 CHECK(iter.readCall(&unusedIndex, &unusedArgs));
219 }
220 case uint16_t(Op::CallIndirect): {
221 uint32_t unusedIndex, unusedIndex2;
222 NothingVector unusedArgs{};
223 CHECK(iter.readCallIndirect(&unusedIndex, &unusedIndex2, ¬hing,
224 &unusedArgs));
225 }
226 case uint16_t(Op::I32Const): {
227 int32_t unused;
228 CHECK(iter.readI32Const(&unused));
229 }
230 case uint16_t(Op::I64Const): {
231 int64_t unused;
232 CHECK(iter.readI64Const(&unused));
233 }
234 case uint16_t(Op::F32Const): {
235 float unused;
236 CHECK(iter.readF32Const(&unused));
237 }
238 case uint16_t(Op::F64Const): {
239 double unused;
240 CHECK(iter.readF64Const(&unused));
241 }
242 case uint16_t(Op::GetLocal): {
243 uint32_t unused;
244 CHECK(iter.readGetLocal(locals, &unused));
245 }
246 case uint16_t(Op::SetLocal): {
247 uint32_t unused;
248 CHECK(iter.readSetLocal(locals, &unused, ¬hing));
249 }
250 case uint16_t(Op::TeeLocal): {
251 uint32_t unused;
252 CHECK(iter.readTeeLocal(locals, &unused, ¬hing));
253 }
254 case uint16_t(Op::GetGlobal): {
255 uint32_t unused;
256 CHECK(iter.readGetGlobal(&unused));
257 }
258 case uint16_t(Op::SetGlobal): {
259 uint32_t unused;
260 CHECK(iter.readSetGlobal(&unused, ¬hing));
261 }
262 case uint16_t(Op::TableGet): {
263 uint32_t unusedTableIndex;
264 CHECK(iter.readTableGet(&unusedTableIndex, ¬hing));
265 }
266 case uint16_t(Op::TableSet): {
267 uint32_t unusedTableIndex;
268 CHECK(iter.readTableSet(&unusedTableIndex, ¬hing, ¬hing));
269 }
270 case uint16_t(Op::SelectNumeric): {
271 StackType unused;
272 CHECK(iter.readSelect(/*typed*/ false, &unused, ¬hing, ¬hing,
273 ¬hing));
274 }
275 case uint16_t(Op::SelectTyped): {
276 StackType unused;
277 CHECK(iter.readSelect(/*typed*/ true, &unused, ¬hing, ¬hing,
278 ¬hing));
279 }
280 case uint16_t(Op::Block):
281 CHECK(iter.readBlock(&unusedType));
282 case uint16_t(Op::Loop):
283 CHECK(iter.readLoop(&unusedType));
284 case uint16_t(Op::If):
285 CHECK(iter.readIf(&unusedType, ¬hing));
286 case uint16_t(Op::Else):
287 CHECK(iter.readElse(&unusedType, &unusedType, ¬hings));
288 case uint16_t(Op::I32Clz):
289 case uint16_t(Op::I32Ctz):
290 case uint16_t(Op::I32Popcnt):
291 CHECK(iter.readUnary(ValType::I32, ¬hing));
292 case uint16_t(Op::I64Clz):
293 case uint16_t(Op::I64Ctz):
294 case uint16_t(Op::I64Popcnt):
295 CHECK(iter.readUnary(ValType::I64, ¬hing));
296 case uint16_t(Op::F32Abs):
297 case uint16_t(Op::F32Neg):
298 case uint16_t(Op::F32Ceil):
299 case uint16_t(Op::F32Floor):
300 case uint16_t(Op::F32Sqrt):
301 case uint16_t(Op::F32Trunc):
302 case uint16_t(Op::F32Nearest):
303 CHECK(iter.readUnary(ValType::F32, ¬hing));
304 case uint16_t(Op::F64Abs):
305 case uint16_t(Op::F64Neg):
306 case uint16_t(Op::F64Ceil):
307 case uint16_t(Op::F64Floor):
308 case uint16_t(Op::F64Sqrt):
309 case uint16_t(Op::F64Trunc):
310 case uint16_t(Op::F64Nearest):
311 CHECK(iter.readUnary(ValType::F64, ¬hing));
312 case uint16_t(Op::I32Add):
313 case uint16_t(Op::I32Sub):
314 case uint16_t(Op::I32Mul):
315 case uint16_t(Op::I32DivS):
316 case uint16_t(Op::I32DivU):
317 case uint16_t(Op::I32RemS):
318 case uint16_t(Op::I32RemU):
319 case uint16_t(Op::I32And):
320 case uint16_t(Op::I32Or):
321 case uint16_t(Op::I32Xor):
322 case uint16_t(Op::I32Shl):
323 case uint16_t(Op::I32ShrS):
324 case uint16_t(Op::I32ShrU):
325 case uint16_t(Op::I32Rotl):
326 case uint16_t(Op::I32Rotr):
327 CHECK(iter.readBinary(ValType::I32, ¬hing, ¬hing));
328 case uint16_t(Op::I64Add):
329 case uint16_t(Op::I64Sub):
330 case uint16_t(Op::I64Mul):
331 case uint16_t(Op::I64DivS):
332 case uint16_t(Op::I64DivU):
333 case uint16_t(Op::I64RemS):
334 case uint16_t(Op::I64RemU):
335 case uint16_t(Op::I64And):
336 case uint16_t(Op::I64Or):
337 case uint16_t(Op::I64Xor):
338 case uint16_t(Op::I64Shl):
339 case uint16_t(Op::I64ShrS):
340 case uint16_t(Op::I64ShrU):
341 case uint16_t(Op::I64Rotl):
342 case uint16_t(Op::I64Rotr):
343 CHECK(iter.readBinary(ValType::I64, ¬hing, ¬hing));
344 case uint16_t(Op::F32Add):
345 case uint16_t(Op::F32Sub):
346 case uint16_t(Op::F32Mul):
347 case uint16_t(Op::F32Div):
348 case uint16_t(Op::F32Min):
349 case uint16_t(Op::F32Max):
350 case uint16_t(Op::F32CopySign):
351 CHECK(iter.readBinary(ValType::F32, ¬hing, ¬hing));
352 case uint16_t(Op::F64Add):
353 case uint16_t(Op::F64Sub):
354 case uint16_t(Op::F64Mul):
355 case uint16_t(Op::F64Div):
356 case uint16_t(Op::F64Min):
357 case uint16_t(Op::F64Max):
358 case uint16_t(Op::F64CopySign):
359 CHECK(iter.readBinary(ValType::F64, ¬hing, ¬hing));
360 case uint16_t(Op::I32Eq):
361 case uint16_t(Op::I32Ne):
362 case uint16_t(Op::I32LtS):
363 case uint16_t(Op::I32LtU):
364 case uint16_t(Op::I32LeS):
365 case uint16_t(Op::I32LeU):
366 case uint16_t(Op::I32GtS):
367 case uint16_t(Op::I32GtU):
368 case uint16_t(Op::I32GeS):
369 case uint16_t(Op::I32GeU):
370 CHECK(iter.readComparison(ValType::I32, ¬hing, ¬hing));
371 case uint16_t(Op::I64Eq):
372 case uint16_t(Op::I64Ne):
373 case uint16_t(Op::I64LtS):
374 case uint16_t(Op::I64LtU):
375 case uint16_t(Op::I64LeS):
376 case uint16_t(Op::I64LeU):
377 case uint16_t(Op::I64GtS):
378 case uint16_t(Op::I64GtU):
379 case uint16_t(Op::I64GeS):
380 case uint16_t(Op::I64GeU):
381 CHECK(iter.readComparison(ValType::I64, ¬hing, ¬hing));
382 case uint16_t(Op::F32Eq):
383 case uint16_t(Op::F32Ne):
384 case uint16_t(Op::F32Lt):
385 case uint16_t(Op::F32Le):
386 case uint16_t(Op::F32Gt):
387 case uint16_t(Op::F32Ge):
388 CHECK(iter.readComparison(ValType::F32, ¬hing, ¬hing));
389 case uint16_t(Op::F64Eq):
390 case uint16_t(Op::F64Ne):
391 case uint16_t(Op::F64Lt):
392 case uint16_t(Op::F64Le):
393 case uint16_t(Op::F64Gt):
394 case uint16_t(Op::F64Ge):
395 CHECK(iter.readComparison(ValType::F64, ¬hing, ¬hing));
396 case uint16_t(Op::I32Eqz):
397 CHECK(iter.readConversion(ValType::I32, ValType::I32, ¬hing));
398 case uint16_t(Op::I64Eqz):
399 case uint16_t(Op::I32WrapI64):
400 CHECK(iter.readConversion(ValType::I64, ValType::I32, ¬hing));
401 case uint16_t(Op::I32TruncSF32):
402 case uint16_t(Op::I32TruncUF32):
403 case uint16_t(Op::I32ReinterpretF32):
404 CHECK(iter.readConversion(ValType::F32, ValType::I32, ¬hing));
405 case uint16_t(Op::I32TruncSF64):
406 case uint16_t(Op::I32TruncUF64):
407 CHECK(iter.readConversion(ValType::F64, ValType::I32, ¬hing));
408 case uint16_t(Op::I64ExtendSI32):
409 case uint16_t(Op::I64ExtendUI32):
410 CHECK(iter.readConversion(ValType::I32, ValType::I64, ¬hing));
411 case uint16_t(Op::I64TruncSF32):
412 case uint16_t(Op::I64TruncUF32):
413 CHECK(iter.readConversion(ValType::F32, ValType::I64, ¬hing));
414 case uint16_t(Op::I64TruncSF64):
415 case uint16_t(Op::I64TruncUF64):
416 case uint16_t(Op::I64ReinterpretF64):
417 CHECK(iter.readConversion(ValType::F64, ValType::I64, ¬hing));
418 case uint16_t(Op::F32ConvertSI32):
419 case uint16_t(Op::F32ConvertUI32):
420 case uint16_t(Op::F32ReinterpretI32):
421 CHECK(iter.readConversion(ValType::I32, ValType::F32, ¬hing));
422 case uint16_t(Op::F32ConvertSI64):
423 case uint16_t(Op::F32ConvertUI64):
424 CHECK(iter.readConversion(ValType::I64, ValType::F32, ¬hing));
425 case uint16_t(Op::F32DemoteF64):
426 CHECK(iter.readConversion(ValType::F64, ValType::F32, ¬hing));
427 case uint16_t(Op::F64ConvertSI32):
428 case uint16_t(Op::F64ConvertUI32):
429 CHECK(iter.readConversion(ValType::I32, ValType::F64, ¬hing));
430 case uint16_t(Op::F64ConvertSI64):
431 case uint16_t(Op::F64ConvertUI64):
432 case uint16_t(Op::F64ReinterpretI64):
433 CHECK(iter.readConversion(ValType::I64, ValType::F64, ¬hing));
434 case uint16_t(Op::F64PromoteF32):
435 CHECK(iter.readConversion(ValType::F32, ValType::F64, ¬hing));
436 case uint16_t(Op::I32Extend8S):
437 case uint16_t(Op::I32Extend16S):
438 CHECK(iter.readConversion(ValType::I32, ValType::I32, ¬hing));
439 case uint16_t(Op::I64Extend8S):
440 case uint16_t(Op::I64Extend16S):
441 case uint16_t(Op::I64Extend32S):
442 CHECK(iter.readConversion(ValType::I64, ValType::I64, ¬hing));
443 case uint16_t(Op::I32Load8S):
444 case uint16_t(Op::I32Load8U): {
445 LinearMemoryAddress<Nothing> addr;
446 CHECK(iter.readLoad(ValType::I32, 1, &addr));
447 }
448 case uint16_t(Op::I32Load16S):
449 case uint16_t(Op::I32Load16U): {
450 LinearMemoryAddress<Nothing> addr;
451 CHECK(iter.readLoad(ValType::I32, 2, &addr));
452 }
453 case uint16_t(Op::I32Load): {
454 LinearMemoryAddress<Nothing> addr;
455 CHECK(iter.readLoad(ValType::I32, 4, &addr));
456 }
457 case uint16_t(Op::I64Load8S):
458 case uint16_t(Op::I64Load8U): {
459 LinearMemoryAddress<Nothing> addr;
460 CHECK(iter.readLoad(ValType::I64, 1, &addr));
461 }
462 case uint16_t(Op::I64Load16S):
463 case uint16_t(Op::I64Load16U): {
464 LinearMemoryAddress<Nothing> addr;
465 CHECK(iter.readLoad(ValType::I64, 2, &addr));
466 }
467 case uint16_t(Op::I64Load32S):
468 case uint16_t(Op::I64Load32U): {
469 LinearMemoryAddress<Nothing> addr;
470 CHECK(iter.readLoad(ValType::I64, 4, &addr));
471 }
472 case uint16_t(Op::I64Load): {
473 LinearMemoryAddress<Nothing> addr;
474 CHECK(iter.readLoad(ValType::I64, 8, &addr));
475 }
476 case uint16_t(Op::F32Load): {
477 LinearMemoryAddress<Nothing> addr;
478 CHECK(iter.readLoad(ValType::F32, 4, &addr));
479 }
480 case uint16_t(Op::F64Load): {
481 LinearMemoryAddress<Nothing> addr;
482 CHECK(iter.readLoad(ValType::F64, 8, &addr));
483 }
484 case uint16_t(Op::I32Store8): {
485 LinearMemoryAddress<Nothing> addr;
486 CHECK(iter.readStore(ValType::I32, 1, &addr, ¬hing));
487 }
488 case uint16_t(Op::I32Store16): {
489 LinearMemoryAddress<Nothing> addr;
490 CHECK(iter.readStore(ValType::I32, 2, &addr, ¬hing));
491 }
492 case uint16_t(Op::I32Store): {
493 LinearMemoryAddress<Nothing> addr;
494 CHECK(iter.readStore(ValType::I32, 4, &addr, ¬hing));
495 }
496 case uint16_t(Op::I64Store8): {
497 LinearMemoryAddress<Nothing> addr;
498 CHECK(iter.readStore(ValType::I64, 1, &addr, ¬hing));
499 }
500 case uint16_t(Op::I64Store16): {
501 LinearMemoryAddress<Nothing> addr;
502 CHECK(iter.readStore(ValType::I64, 2, &addr, ¬hing));
503 }
504 case uint16_t(Op::I64Store32): {
505 LinearMemoryAddress<Nothing> addr;
506 CHECK(iter.readStore(ValType::I64, 4, &addr, ¬hing));
507 }
508 case uint16_t(Op::I64Store): {
509 LinearMemoryAddress<Nothing> addr;
510 CHECK(iter.readStore(ValType::I64, 8, &addr, ¬hing));
511 }
512 case uint16_t(Op::F32Store): {
513 LinearMemoryAddress<Nothing> addr;
514 CHECK(iter.readStore(ValType::F32, 4, &addr, ¬hing));
515 }
516 case uint16_t(Op::F64Store): {
517 LinearMemoryAddress<Nothing> addr;
518 CHECK(iter.readStore(ValType::F64, 8, &addr, ¬hing));
519 }
520 case uint16_t(Op::MemoryGrow):
521 CHECK(iter.readMemoryGrow(¬hing));
522 case uint16_t(Op::MemorySize):
523 CHECK(iter.readMemorySize());
524 case uint16_t(Op::Br): {
525 uint32_t unusedDepth;
526 CHECK(iter.readBr(&unusedDepth, &unusedType, ¬hings));
527 }
528 case uint16_t(Op::BrIf): {
529 uint32_t unusedDepth;
530 CHECK(iter.readBrIf(&unusedDepth, &unusedType, ¬hings, ¬hing));
531 }
532 case uint16_t(Op::BrTable): {
533 Uint32Vector unusedDepths;
534 uint32_t unusedDefault;
535 CHECK(iter.readBrTable(&unusedDepths, &unusedDefault, &unusedType,
536 ¬hings, ¬hing));
537 }
538 case uint16_t(Op::Return):
539 CHECK(iter.readReturn(¬hings));
540 case uint16_t(Op::Unreachable):
541 CHECK(iter.readUnreachable());
542 #ifdef ENABLE_WASM_GC
543 case uint16_t(Op::GcPrefix): {
544 if (!env.gcEnabled()) {
545 return iter.unrecognizedOpcode(&op);
546 }
547 switch (op.b1) {
548 case uint32_t(GcOp::StructNewWithRtt): {
549 uint32_t unusedUint;
550 NothingVector unusedArgs{};
551 CHECK(
552 iter.readStructNewWithRtt(&unusedUint, ¬hing, &unusedArgs));
553 }
554 case uint32_t(GcOp::StructNewDefaultWithRtt): {
555 uint32_t unusedUint;
556 CHECK(iter.readStructNewDefaultWithRtt(&unusedUint, ¬hing));
557 }
558 case uint32_t(GcOp::StructGet): {
559 uint32_t unusedUint1, unusedUint2;
560 CHECK(iter.readStructGet(&unusedUint1, &unusedUint2,
561 FieldExtension::None, ¬hing));
562 }
563 case uint32_t(GcOp::StructGetS): {
564 uint32_t unusedUint1, unusedUint2;
565 CHECK(iter.readStructGet(&unusedUint1, &unusedUint2,
566 FieldExtension::Signed, ¬hing));
567 }
568 case uint32_t(GcOp::StructGetU): {
569 uint32_t unusedUint1, unusedUint2;
570 CHECK(iter.readStructGet(&unusedUint1, &unusedUint2,
571 FieldExtension::Unsigned, ¬hing));
572 }
573 case uint32_t(GcOp::StructSet): {
574 uint32_t unusedUint1, unusedUint2;
575 CHECK(iter.readStructSet(&unusedUint1, &unusedUint2, ¬hing,
576 ¬hing));
577 }
578 case uint32_t(GcOp::ArrayNewWithRtt): {
579 uint32_t unusedUint;
580 CHECK(iter.readArrayNewWithRtt(&unusedUint, ¬hing, ¬hing,
581 ¬hing));
582 }
583 case uint32_t(GcOp::ArrayNewDefaultWithRtt): {
584 uint32_t unusedUint;
585 CHECK(iter.readArrayNewDefaultWithRtt(&unusedUint, ¬hing,
586 ¬hing));
587 }
588 case uint32_t(GcOp::ArrayGet): {
589 uint32_t unusedUint1;
590 CHECK(iter.readArrayGet(&unusedUint1, FieldExtension::None,
591 ¬hing, ¬hing));
592 }
593 case uint32_t(GcOp::ArrayGetS): {
594 uint32_t unusedUint1;
595 CHECK(iter.readArrayGet(&unusedUint1, FieldExtension::Signed,
596 ¬hing, ¬hing));
597 }
598 case uint32_t(GcOp::ArrayGetU): {
599 uint32_t unusedUint1;
600 CHECK(iter.readArrayGet(&unusedUint1, FieldExtension::Unsigned,
601 ¬hing, ¬hing));
602 }
603 case uint32_t(GcOp::ArraySet): {
604 uint32_t unusedUint1;
605 CHECK(
606 iter.readArraySet(&unusedUint1, ¬hing, ¬hing, ¬hing));
607 }
608 case uint32_t(GcOp::ArrayLen): {
609 uint32_t unusedUint1;
610 CHECK(iter.readArrayLen(&unusedUint1, ¬hing));
611 }
612 case uint16_t(GcOp::RttCanon): {
613 ValType unusedTy;
614 CHECK(iter.readRttCanon(&unusedTy));
615 }
616 case uint16_t(GcOp::RttSub): {
617 CHECK(iter.readRttSub(¬hing));
618 }
619 case uint16_t(GcOp::RefTest): {
620 uint32_t unusedRttTypeIndex;
621 uint32_t unusedRttDepth;
622 CHECK(iter.readRefTest(¬hing, &unusedRttTypeIndex,
623 &unusedRttDepth, ¬hing));
624 }
625 case uint16_t(GcOp::RefCast): {
626 uint32_t unusedRttTypeIndex;
627 uint32_t unusedRttDepth;
628 CHECK(iter.readRefCast(¬hing, &unusedRttTypeIndex,
629 &unusedRttDepth, ¬hing));
630 }
631 case uint16_t(GcOp::BrOnCast): {
632 uint32_t unusedRelativeDepth;
633 uint32_t unusedRttTypeIndex;
634 uint32_t unusedRttDepth;
635 CHECK(iter.readBrOnCast(&unusedRelativeDepth, ¬hing,
636 &unusedRttTypeIndex, &unusedRttDepth,
637 &unusedType, ¬hings));
638 }
639 default:
640 return iter.unrecognizedOpcode(&op);
641 }
642 break;
643 }
644 #endif
645
646 #ifdef ENABLE_WASM_SIMD
647 case uint16_t(Op::SimdPrefix): {
648 if (!env.v128Enabled()) {
649 return iter.unrecognizedOpcode(&op);
650 }
651 uint32_t noIndex;
652 switch (op.b1) {
653 case uint32_t(SimdOp::I8x16ExtractLaneS):
654 case uint32_t(SimdOp::I8x16ExtractLaneU):
655 CHECK(iter.readExtractLane(ValType::I32, 16, &noIndex, ¬hing));
656 case uint32_t(SimdOp::I16x8ExtractLaneS):
657 case uint32_t(SimdOp::I16x8ExtractLaneU):
658 CHECK(iter.readExtractLane(ValType::I32, 8, &noIndex, ¬hing));
659 case uint32_t(SimdOp::I32x4ExtractLane):
660 CHECK(iter.readExtractLane(ValType::I32, 4, &noIndex, ¬hing));
661 case uint32_t(SimdOp::I64x2ExtractLane):
662 CHECK(iter.readExtractLane(ValType::I64, 2, &noIndex, ¬hing));
663 case uint32_t(SimdOp::F32x4ExtractLane):
664 CHECK(iter.readExtractLane(ValType::F32, 4, &noIndex, ¬hing));
665 case uint32_t(SimdOp::F64x2ExtractLane):
666 CHECK(iter.readExtractLane(ValType::F64, 2, &noIndex, ¬hing));
667
668 case uint32_t(SimdOp::I8x16Splat):
669 case uint32_t(SimdOp::I16x8Splat):
670 case uint32_t(SimdOp::I32x4Splat):
671 CHECK(iter.readConversion(ValType::I32, ValType::V128, ¬hing));
672 case uint32_t(SimdOp::I64x2Splat):
673 CHECK(iter.readConversion(ValType::I64, ValType::V128, ¬hing));
674 case uint32_t(SimdOp::F32x4Splat):
675 CHECK(iter.readConversion(ValType::F32, ValType::V128, ¬hing));
676 case uint32_t(SimdOp::F64x2Splat):
677 CHECK(iter.readConversion(ValType::F64, ValType::V128, ¬hing));
678
679 case uint32_t(SimdOp::V128AnyTrue):
680 case uint32_t(SimdOp::I8x16AllTrue):
681 case uint32_t(SimdOp::I16x8AllTrue):
682 case uint32_t(SimdOp::I32x4AllTrue):
683 case uint32_t(SimdOp::I64x2AllTrue):
684 case uint32_t(SimdOp::I8x16Bitmask):
685 case uint32_t(SimdOp::I16x8Bitmask):
686 case uint32_t(SimdOp::I32x4Bitmask):
687 case uint32_t(SimdOp::I64x2Bitmask):
688 CHECK(iter.readConversion(ValType::V128, ValType::I32, ¬hing));
689
690 case uint32_t(SimdOp::I8x16ReplaceLane):
691 CHECK(iter.readReplaceLane(ValType::I32, 16, &noIndex, ¬hing,
692 ¬hing));
693 case uint32_t(SimdOp::I16x8ReplaceLane):
694 CHECK(iter.readReplaceLane(ValType::I32, 8, &noIndex, ¬hing,
695 ¬hing));
696 case uint32_t(SimdOp::I32x4ReplaceLane):
697 CHECK(iter.readReplaceLane(ValType::I32, 4, &noIndex, ¬hing,
698 ¬hing));
699 case uint32_t(SimdOp::I64x2ReplaceLane):
700 CHECK(iter.readReplaceLane(ValType::I64, 2, &noIndex, ¬hing,
701 ¬hing));
702 case uint32_t(SimdOp::F32x4ReplaceLane):
703 CHECK(iter.readReplaceLane(ValType::F32, 4, &noIndex, ¬hing,
704 ¬hing));
705 case uint32_t(SimdOp::F64x2ReplaceLane):
706 CHECK(iter.readReplaceLane(ValType::F64, 2, &noIndex, ¬hing,
707 ¬hing));
708
709 case uint32_t(SimdOp::I8x16Eq):
710 case uint32_t(SimdOp::I8x16Ne):
711 case uint32_t(SimdOp::I8x16LtS):
712 case uint32_t(SimdOp::I8x16LtU):
713 case uint32_t(SimdOp::I8x16GtS):
714 case uint32_t(SimdOp::I8x16GtU):
715 case uint32_t(SimdOp::I8x16LeS):
716 case uint32_t(SimdOp::I8x16LeU):
717 case uint32_t(SimdOp::I8x16GeS):
718 case uint32_t(SimdOp::I8x16GeU):
719 case uint32_t(SimdOp::I16x8Eq):
720 case uint32_t(SimdOp::I16x8Ne):
721 case uint32_t(SimdOp::I16x8LtS):
722 case uint32_t(SimdOp::I16x8LtU):
723 case uint32_t(SimdOp::I16x8GtS):
724 case uint32_t(SimdOp::I16x8GtU):
725 case uint32_t(SimdOp::I16x8LeS):
726 case uint32_t(SimdOp::I16x8LeU):
727 case uint32_t(SimdOp::I16x8GeS):
728 case uint32_t(SimdOp::I16x8GeU):
729 case uint32_t(SimdOp::I32x4Eq):
730 case uint32_t(SimdOp::I32x4Ne):
731 case uint32_t(SimdOp::I32x4LtS):
732 case uint32_t(SimdOp::I32x4LtU):
733 case uint32_t(SimdOp::I32x4GtS):
734 case uint32_t(SimdOp::I32x4GtU):
735 case uint32_t(SimdOp::I32x4LeS):
736 case uint32_t(SimdOp::I32x4LeU):
737 case uint32_t(SimdOp::I32x4GeS):
738 case uint32_t(SimdOp::I32x4GeU):
739 case uint32_t(SimdOp::I64x2Eq):
740 case uint32_t(SimdOp::I64x2Ne):
741 case uint32_t(SimdOp::I64x2LtS):
742 case uint32_t(SimdOp::I64x2GtS):
743 case uint32_t(SimdOp::I64x2LeS):
744 case uint32_t(SimdOp::I64x2GeS):
745 case uint32_t(SimdOp::F32x4Eq):
746 case uint32_t(SimdOp::F32x4Ne):
747 case uint32_t(SimdOp::F32x4Lt):
748 case uint32_t(SimdOp::F32x4Gt):
749 case uint32_t(SimdOp::F32x4Le):
750 case uint32_t(SimdOp::F32x4Ge):
751 case uint32_t(SimdOp::F64x2Eq):
752 case uint32_t(SimdOp::F64x2Ne):
753 case uint32_t(SimdOp::F64x2Lt):
754 case uint32_t(SimdOp::F64x2Gt):
755 case uint32_t(SimdOp::F64x2Le):
756 case uint32_t(SimdOp::F64x2Ge):
757 case uint32_t(SimdOp::V128And):
758 case uint32_t(SimdOp::V128Or):
759 case uint32_t(SimdOp::V128Xor):
760 case uint32_t(SimdOp::V128AndNot):
761 case uint32_t(SimdOp::I8x16AvgrU):
762 case uint32_t(SimdOp::I16x8AvgrU):
763 case uint32_t(SimdOp::I8x16Add):
764 case uint32_t(SimdOp::I8x16AddSaturateS):
765 case uint32_t(SimdOp::I8x16AddSaturateU):
766 case uint32_t(SimdOp::I8x16Sub):
767 case uint32_t(SimdOp::I8x16SubSaturateS):
768 case uint32_t(SimdOp::I8x16SubSaturateU):
769 case uint32_t(SimdOp::I8x16MinS):
770 case uint32_t(SimdOp::I8x16MinU):
771 case uint32_t(SimdOp::I8x16MaxS):
772 case uint32_t(SimdOp::I8x16MaxU):
773 case uint32_t(SimdOp::I16x8Add):
774 case uint32_t(SimdOp::I16x8AddSaturateS):
775 case uint32_t(SimdOp::I16x8AddSaturateU):
776 case uint32_t(SimdOp::I16x8Sub):
777 case uint32_t(SimdOp::I16x8SubSaturateS):
778 case uint32_t(SimdOp::I16x8SubSaturateU):
779 case uint32_t(SimdOp::I16x8Mul):
780 case uint32_t(SimdOp::I16x8MinS):
781 case uint32_t(SimdOp::I16x8MinU):
782 case uint32_t(SimdOp::I16x8MaxS):
783 case uint32_t(SimdOp::I16x8MaxU):
784 case uint32_t(SimdOp::I32x4Add):
785 case uint32_t(SimdOp::I32x4Sub):
786 case uint32_t(SimdOp::I32x4Mul):
787 case uint32_t(SimdOp::I32x4MinS):
788 case uint32_t(SimdOp::I32x4MinU):
789 case uint32_t(SimdOp::I32x4MaxS):
790 case uint32_t(SimdOp::I32x4MaxU):
791 case uint32_t(SimdOp::I64x2Add):
792 case uint32_t(SimdOp::I64x2Sub):
793 case uint32_t(SimdOp::I64x2Mul):
794 case uint32_t(SimdOp::F32x4Add):
795 case uint32_t(SimdOp::F32x4Sub):
796 case uint32_t(SimdOp::F32x4Mul):
797 case uint32_t(SimdOp::F32x4Div):
798 case uint32_t(SimdOp::F32x4Min):
799 case uint32_t(SimdOp::F32x4Max):
800 case uint32_t(SimdOp::F64x2Add):
801 case uint32_t(SimdOp::F64x2Sub):
802 case uint32_t(SimdOp::F64x2Mul):
803 case uint32_t(SimdOp::F64x2Div):
804 case uint32_t(SimdOp::F64x2Min):
805 case uint32_t(SimdOp::F64x2Max):
806 case uint32_t(SimdOp::I8x16NarrowSI16x8):
807 case uint32_t(SimdOp::I8x16NarrowUI16x8):
808 case uint32_t(SimdOp::I16x8NarrowSI32x4):
809 case uint32_t(SimdOp::I16x8NarrowUI32x4):
810 case uint32_t(SimdOp::V8x16Swizzle):
811 case uint32_t(SimdOp::F32x4PMax):
812 case uint32_t(SimdOp::F32x4PMin):
813 case uint32_t(SimdOp::F64x2PMax):
814 case uint32_t(SimdOp::F64x2PMin):
815 case uint32_t(SimdOp::I32x4DotSI16x8):
816 case uint32_t(SimdOp::I16x8ExtMulLowSI8x16):
817 case uint32_t(SimdOp::I16x8ExtMulHighSI8x16):
818 case uint32_t(SimdOp::I16x8ExtMulLowUI8x16):
819 case uint32_t(SimdOp::I16x8ExtMulHighUI8x16):
820 case uint32_t(SimdOp::I32x4ExtMulLowSI16x8):
821 case uint32_t(SimdOp::I32x4ExtMulHighSI16x8):
822 case uint32_t(SimdOp::I32x4ExtMulLowUI16x8):
823 case uint32_t(SimdOp::I32x4ExtMulHighUI16x8):
824 case uint32_t(SimdOp::I64x2ExtMulLowSI32x4):
825 case uint32_t(SimdOp::I64x2ExtMulHighSI32x4):
826 case uint32_t(SimdOp::I64x2ExtMulLowUI32x4):
827 case uint32_t(SimdOp::I64x2ExtMulHighUI32x4):
828 case uint32_t(SimdOp::I16x8Q15MulrSatS):
829 CHECK(iter.readBinary(ValType::V128, ¬hing, ¬hing));
830
831 case uint32_t(SimdOp::I8x16Neg):
832 case uint32_t(SimdOp::I16x8Neg):
833 case uint32_t(SimdOp::I16x8WidenLowSI8x16):
834 case uint32_t(SimdOp::I16x8WidenHighSI8x16):
835 case uint32_t(SimdOp::I16x8WidenLowUI8x16):
836 case uint32_t(SimdOp::I16x8WidenHighUI8x16):
837 case uint32_t(SimdOp::I32x4Neg):
838 case uint32_t(SimdOp::I32x4WidenLowSI16x8):
839 case uint32_t(SimdOp::I32x4WidenHighSI16x8):
840 case uint32_t(SimdOp::I32x4WidenLowUI16x8):
841 case uint32_t(SimdOp::I32x4WidenHighUI16x8):
842 case uint32_t(SimdOp::I32x4TruncSSatF32x4):
843 case uint32_t(SimdOp::I32x4TruncUSatF32x4):
844 case uint32_t(SimdOp::I64x2Neg):
845 case uint32_t(SimdOp::I64x2WidenLowSI32x4):
846 case uint32_t(SimdOp::I64x2WidenHighSI32x4):
847 case uint32_t(SimdOp::I64x2WidenLowUI32x4):
848 case uint32_t(SimdOp::I64x2WidenHighUI32x4):
849 case uint32_t(SimdOp::F32x4Abs):
850 case uint32_t(SimdOp::F32x4Neg):
851 case uint32_t(SimdOp::F32x4Sqrt):
852 case uint32_t(SimdOp::F32x4ConvertSI32x4):
853 case uint32_t(SimdOp::F32x4ConvertUI32x4):
854 case uint32_t(SimdOp::F64x2Abs):
855 case uint32_t(SimdOp::F64x2Neg):
856 case uint32_t(SimdOp::F64x2Sqrt):
857 case uint32_t(SimdOp::V128Not):
858 case uint32_t(SimdOp::I8x16Popcnt):
859 case uint32_t(SimdOp::I8x16Abs):
860 case uint32_t(SimdOp::I16x8Abs):
861 case uint32_t(SimdOp::I32x4Abs):
862 case uint32_t(SimdOp::I64x2Abs):
863 case uint32_t(SimdOp::F32x4Ceil):
864 case uint32_t(SimdOp::F32x4Floor):
865 case uint32_t(SimdOp::F32x4Trunc):
866 case uint32_t(SimdOp::F32x4Nearest):
867 case uint32_t(SimdOp::F64x2Ceil):
868 case uint32_t(SimdOp::F64x2Floor):
869 case uint32_t(SimdOp::F64x2Trunc):
870 case uint32_t(SimdOp::F64x2Nearest):
871 case uint32_t(SimdOp::F32x4DemoteF64x2Zero):
872 case uint32_t(SimdOp::F64x2PromoteLowF32x4):
873 case uint32_t(SimdOp::F64x2ConvertLowI32x4S):
874 case uint32_t(SimdOp::F64x2ConvertLowI32x4U):
875 case uint32_t(SimdOp::I32x4TruncSatF64x2SZero):
876 case uint32_t(SimdOp::I32x4TruncSatF64x2UZero):
877 case uint32_t(SimdOp::I16x8ExtAddPairwiseI8x16S):
878 case uint32_t(SimdOp::I16x8ExtAddPairwiseI8x16U):
879 case uint32_t(SimdOp::I32x4ExtAddPairwiseI16x8S):
880 case uint32_t(SimdOp::I32x4ExtAddPairwiseI16x8U):
881 CHECK(iter.readUnary(ValType::V128, ¬hing));
882
883 case uint32_t(SimdOp::I8x16Shl):
884 case uint32_t(SimdOp::I8x16ShrS):
885 case uint32_t(SimdOp::I8x16ShrU):
886 case uint32_t(SimdOp::I16x8Shl):
887 case uint32_t(SimdOp::I16x8ShrS):
888 case uint32_t(SimdOp::I16x8ShrU):
889 case uint32_t(SimdOp::I32x4Shl):
890 case uint32_t(SimdOp::I32x4ShrS):
891 case uint32_t(SimdOp::I32x4ShrU):
892 case uint32_t(SimdOp::I64x2Shl):
893 case uint32_t(SimdOp::I64x2ShrS):
894 case uint32_t(SimdOp::I64x2ShrU):
895 CHECK(iter.readVectorShift(¬hing, ¬hing));
896
897 case uint32_t(SimdOp::V128Bitselect):
898 CHECK(iter.readVectorSelect(¬hing, ¬hing, ¬hing));
899
900 case uint32_t(SimdOp::V8x16Shuffle): {
901 V128 mask;
902 CHECK(iter.readVectorShuffle(¬hing, ¬hing, &mask));
903 }
904
905 case uint32_t(SimdOp::V128Const): {
906 V128 noVector;
907 CHECK(iter.readV128Const(&noVector));
908 }
909
910 case uint32_t(SimdOp::V128Load): {
911 LinearMemoryAddress<Nothing> addr;
912 CHECK(iter.readLoad(ValType::V128, 16, &addr));
913 }
914
915 case uint32_t(SimdOp::V8x16LoadSplat): {
916 LinearMemoryAddress<Nothing> addr;
917 CHECK(iter.readLoadSplat(1, &addr));
918 }
919
920 case uint32_t(SimdOp::V16x8LoadSplat): {
921 LinearMemoryAddress<Nothing> addr;
922 CHECK(iter.readLoadSplat(2, &addr));
923 }
924
925 case uint32_t(SimdOp::V32x4LoadSplat): {
926 LinearMemoryAddress<Nothing> addr;
927 CHECK(iter.readLoadSplat(4, &addr));
928 }
929
930 case uint32_t(SimdOp::V64x2LoadSplat): {
931 LinearMemoryAddress<Nothing> addr;
932 CHECK(iter.readLoadSplat(8, &addr));
933 }
934
935 case uint32_t(SimdOp::I16x8LoadS8x8):
936 case uint32_t(SimdOp::I16x8LoadU8x8): {
937 LinearMemoryAddress<Nothing> addr;
938 CHECK(iter.readLoadExtend(&addr));
939 }
940
941 case uint32_t(SimdOp::I32x4LoadS16x4):
942 case uint32_t(SimdOp::I32x4LoadU16x4): {
943 LinearMemoryAddress<Nothing> addr;
944 CHECK(iter.readLoadExtend(&addr));
945 }
946
947 case uint32_t(SimdOp::I64x2LoadS32x2):
948 case uint32_t(SimdOp::I64x2LoadU32x2): {
949 LinearMemoryAddress<Nothing> addr;
950 CHECK(iter.readLoadExtend(&addr));
951 }
952
953 case uint32_t(SimdOp::V128Store): {
954 LinearMemoryAddress<Nothing> addr;
955 CHECK(iter.readStore(ValType::V128, 16, &addr, ¬hing));
956 }
957
958 case uint32_t(SimdOp::V128Load32Zero): {
959 LinearMemoryAddress<Nothing> addr;
960 CHECK(iter.readLoadSplat(4, &addr));
961 }
962
963 case uint32_t(SimdOp::V128Load64Zero): {
964 LinearMemoryAddress<Nothing> addr;
965 CHECK(iter.readLoadSplat(8, &addr));
966 }
967
968 case uint32_t(SimdOp::V128Load8Lane): {
969 LinearMemoryAddress<Nothing> addr;
970 CHECK(iter.readLoadLane(1, &addr, &noIndex, ¬hing));
971 }
972
973 case uint32_t(SimdOp::V128Load16Lane): {
974 LinearMemoryAddress<Nothing> addr;
975 CHECK(iter.readLoadLane(2, &addr, &noIndex, ¬hing));
976 }
977
978 case uint32_t(SimdOp::V128Load32Lane): {
979 LinearMemoryAddress<Nothing> addr;
980 CHECK(iter.readLoadLane(4, &addr, &noIndex, ¬hing));
981 }
982
983 case uint32_t(SimdOp::V128Load64Lane): {
984 LinearMemoryAddress<Nothing> addr;
985 CHECK(iter.readLoadLane(8, &addr, &noIndex, ¬hing));
986 }
987
988 case uint32_t(SimdOp::V128Store8Lane): {
989 LinearMemoryAddress<Nothing> addr;
990 CHECK(iter.readStoreLane(1, &addr, &noIndex, ¬hing));
991 }
992
993 case uint32_t(SimdOp::V128Store16Lane): {
994 LinearMemoryAddress<Nothing> addr;
995 CHECK(iter.readStoreLane(2, &addr, &noIndex, ¬hing));
996 }
997
998 case uint32_t(SimdOp::V128Store32Lane): {
999 LinearMemoryAddress<Nothing> addr;
1000 CHECK(iter.readStoreLane(4, &addr, &noIndex, ¬hing));
1001 }
1002
1003 case uint32_t(SimdOp::V128Store64Lane): {
1004 LinearMemoryAddress<Nothing> addr;
1005 CHECK(iter.readStoreLane(8, &addr, &noIndex, ¬hing));
1006 }
1007
1008 default:
1009 return iter.unrecognizedOpcode(&op);
1010 }
1011 break;
1012 }
1013 #endif // ENABLE_WASM_SIMD
1014
1015 case uint16_t(Op::MiscPrefix): {
1016 switch (op.b1) {
1017 case uint32_t(MiscOp::I32TruncSSatF32):
1018 case uint32_t(MiscOp::I32TruncUSatF32):
1019 CHECK(iter.readConversion(ValType::F32, ValType::I32, ¬hing));
1020 case uint32_t(MiscOp::I32TruncSSatF64):
1021 case uint32_t(MiscOp::I32TruncUSatF64):
1022 CHECK(iter.readConversion(ValType::F64, ValType::I32, ¬hing));
1023 case uint32_t(MiscOp::I64TruncSSatF32):
1024 case uint32_t(MiscOp::I64TruncUSatF32):
1025 CHECK(iter.readConversion(ValType::F32, ValType::I64, ¬hing));
1026 case uint32_t(MiscOp::I64TruncSSatF64):
1027 case uint32_t(MiscOp::I64TruncUSatF64):
1028 CHECK(iter.readConversion(ValType::F64, ValType::I64, ¬hing));
1029 case uint32_t(MiscOp::MemCopy): {
1030 uint32_t unusedDestMemIndex;
1031 uint32_t unusedSrcMemIndex;
1032 CHECK(iter.readMemOrTableCopy(/*isMem=*/true, &unusedDestMemIndex,
1033 ¬hing, &unusedSrcMemIndex,
1034 ¬hing, ¬hing));
1035 }
1036 case uint32_t(MiscOp::DataDrop): {
1037 uint32_t unusedSegIndex;
1038 CHECK(iter.readDataOrElemDrop(/*isData=*/true, &unusedSegIndex));
1039 }
1040 case uint32_t(MiscOp::MemFill):
1041 CHECK(iter.readMemFill(¬hing, ¬hing, ¬hing));
1042 case uint32_t(MiscOp::MemInit): {
1043 uint32_t unusedSegIndex;
1044 uint32_t unusedTableIndex;
1045 CHECK(iter.readMemOrTableInit(/*isMem=*/true, &unusedSegIndex,
1046 &unusedTableIndex, ¬hing, ¬hing,
1047 ¬hing));
1048 }
1049 case uint32_t(MiscOp::TableCopy): {
1050 uint32_t unusedDestTableIndex;
1051 uint32_t unusedSrcTableIndex;
1052 CHECK(iter.readMemOrTableCopy(
1053 /*isMem=*/false, &unusedDestTableIndex, ¬hing,
1054 &unusedSrcTableIndex, ¬hing, ¬hing));
1055 }
1056 case uint32_t(MiscOp::ElemDrop): {
1057 uint32_t unusedSegIndex;
1058 CHECK(iter.readDataOrElemDrop(/*isData=*/false, &unusedSegIndex));
1059 }
1060 case uint32_t(MiscOp::TableInit): {
1061 uint32_t unusedSegIndex;
1062 uint32_t unusedTableIndex;
1063 CHECK(iter.readMemOrTableInit(/*isMem=*/false, &unusedSegIndex,
1064 &unusedTableIndex, ¬hing, ¬hing,
1065 ¬hing));
1066 }
1067 case uint32_t(MiscOp::TableFill): {
1068 uint32_t unusedTableIndex;
1069 CHECK(iter.readTableFill(&unusedTableIndex, ¬hing, ¬hing,
1070 ¬hing));
1071 }
1072 case uint32_t(MiscOp::TableGrow): {
1073 uint32_t unusedTableIndex;
1074 CHECK(iter.readTableGrow(&unusedTableIndex, ¬hing, ¬hing));
1075 }
1076 case uint32_t(MiscOp::TableSize): {
1077 uint32_t unusedTableIndex;
1078 CHECK(iter.readTableSize(&unusedTableIndex));
1079 }
1080 default:
1081 return iter.unrecognizedOpcode(&op);
1082 }
1083 break;
1084 }
1085 #ifdef ENABLE_WASM_FUNCTION_REFERENCES
1086 case uint16_t(Op::RefAsNonNull): {
1087 if (!env.functionReferencesEnabled()) {
1088 return iter.unrecognizedOpcode(&op);
1089 }
1090 CHECK(iter.readRefAsNonNull(¬hing));
1091 }
1092 case uint16_t(Op::BrOnNull): {
1093 if (!env.functionReferencesEnabled()) {
1094 return iter.unrecognizedOpcode(&op);
1095 }
1096 uint32_t unusedDepth;
1097 CHECK(
1098 iter.readBrOnNull(&unusedDepth, &unusedType, ¬hings, ¬hing));
1099 }
1100 #endif
1101 #ifdef ENABLE_WASM_GC
1102 case uint16_t(Op::RefEq): {
1103 if (!env.gcEnabled()) {
1104 return iter.unrecognizedOpcode(&op);
1105 }
1106 CHECK(iter.readComparison(RefType::eq(), ¬hing, ¬hing));
1107 }
1108 #endif
1109 case uint16_t(Op::RefFunc): {
1110 uint32_t unusedIndex;
1111 CHECK(iter.readRefFunc(&unusedIndex));
1112 }
1113 case uint16_t(Op::RefNull): {
1114 RefType type;
1115 CHECK(iter.readRefNull(&type));
1116 }
1117 case uint16_t(Op::RefIsNull): {
1118 Nothing nothing;
1119 CHECK(iter.readRefIsNull(¬hing));
1120 }
1121 #ifdef ENABLE_WASM_EXCEPTIONS
1122 case uint16_t(Op::Try):
1123 if (!env.exceptionsEnabled()) {
1124 return iter.unrecognizedOpcode(&op);
1125 }
1126 CHECK(iter.readTry(&unusedType));
1127 case uint16_t(Op::Catch): {
1128 if (!env.exceptionsEnabled()) {
1129 return iter.unrecognizedOpcode(&op);
1130 }
1131 LabelKind unusedKind;
1132 uint32_t unusedIndex;
1133 CHECK(iter.readCatch(&unusedKind, &unusedIndex, &unusedType,
1134 &unusedType, ¬hings));
1135 }
1136 case uint16_t(Op::CatchAll): {
1137 if (!env.exceptionsEnabled()) {
1138 return iter.unrecognizedOpcode(&op);
1139 }
1140 LabelKind unusedKind;
1141 CHECK(iter.readCatchAll(&unusedKind, &unusedType, &unusedType,
1142 ¬hings));
1143 }
1144 case uint16_t(Op::Delegate): {
1145 if (!env.exceptionsEnabled()) {
1146 return iter.unrecognizedOpcode(&op);
1147 }
1148 uint32_t unusedDepth;
1149 if (!iter.readDelegate(&unusedDepth, &unusedType, ¬hings)) {
1150 return false;
1151 }
1152 iter.popDelegate();
1153 break;
1154 }
1155 case uint16_t(Op::Throw): {
1156 if (!env.exceptionsEnabled()) {
1157 return iter.unrecognizedOpcode(&op);
1158 }
1159 uint32_t unusedIndex;
1160 CHECK(iter.readThrow(&unusedIndex, ¬hings));
1161 }
1162 case uint16_t(Op::Rethrow): {
1163 if (!env.exceptionsEnabled()) {
1164 return iter.unrecognizedOpcode(&op);
1165 }
1166 uint32_t unusedDepth;
1167 CHECK(iter.readRethrow(&unusedDepth));
1168 }
1169 #endif
1170 case uint16_t(Op::ThreadPrefix): {
1171 // Though thread ops can be used on nonshared memories, we make them
1172 // unavailable if shared memory has been disabled in the prefs, for
1173 // maximum predictability and safety and consistency with JS.
1174 if (env.sharedMemoryEnabled() == Shareable::False) {
1175 return iter.unrecognizedOpcode(&op);
1176 }
1177 switch (op.b1) {
1178 case uint32_t(ThreadOp::Wake): {
1179 LinearMemoryAddress<Nothing> addr;
1180 CHECK(iter.readWake(&addr, ¬hing));
1181 }
1182 case uint32_t(ThreadOp::I32Wait): {
1183 LinearMemoryAddress<Nothing> addr;
1184 CHECK(iter.readWait(&addr, ValType::I32, 4, ¬hing, ¬hing));
1185 }
1186 case uint32_t(ThreadOp::I64Wait): {
1187 LinearMemoryAddress<Nothing> addr;
1188 CHECK(iter.readWait(&addr, ValType::I64, 8, ¬hing, ¬hing));
1189 }
1190 case uint32_t(ThreadOp::Fence): {
1191 CHECK(iter.readFence());
1192 }
1193 case uint32_t(ThreadOp::I32AtomicLoad): {
1194 LinearMemoryAddress<Nothing> addr;
1195 CHECK(iter.readAtomicLoad(&addr, ValType::I32, 4));
1196 }
1197 case uint32_t(ThreadOp::I64AtomicLoad): {
1198 LinearMemoryAddress<Nothing> addr;
1199 CHECK(iter.readAtomicLoad(&addr, ValType::I64, 8));
1200 }
1201 case uint32_t(ThreadOp::I32AtomicLoad8U): {
1202 LinearMemoryAddress<Nothing> addr;
1203 CHECK(iter.readAtomicLoad(&addr, ValType::I32, 1));
1204 }
1205 case uint32_t(ThreadOp::I32AtomicLoad16U): {
1206 LinearMemoryAddress<Nothing> addr;
1207 CHECK(iter.readAtomicLoad(&addr, ValType::I32, 2));
1208 }
1209 case uint32_t(ThreadOp::I64AtomicLoad8U): {
1210 LinearMemoryAddress<Nothing> addr;
1211 CHECK(iter.readAtomicLoad(&addr, ValType::I64, 1));
1212 }
1213 case uint32_t(ThreadOp::I64AtomicLoad16U): {
1214 LinearMemoryAddress<Nothing> addr;
1215 CHECK(iter.readAtomicLoad(&addr, ValType::I64, 2));
1216 }
1217 case uint32_t(ThreadOp::I64AtomicLoad32U): {
1218 LinearMemoryAddress<Nothing> addr;
1219 CHECK(iter.readAtomicLoad(&addr, ValType::I64, 4));
1220 }
1221 case uint32_t(ThreadOp::I32AtomicStore): {
1222 LinearMemoryAddress<Nothing> addr;
1223 CHECK(iter.readAtomicStore(&addr, ValType::I32, 4, ¬hing));
1224 }
1225 case uint32_t(ThreadOp::I64AtomicStore): {
1226 LinearMemoryAddress<Nothing> addr;
1227 CHECK(iter.readAtomicStore(&addr, ValType::I64, 8, ¬hing));
1228 }
1229 case uint32_t(ThreadOp::I32AtomicStore8U): {
1230 LinearMemoryAddress<Nothing> addr;
1231 CHECK(iter.readAtomicStore(&addr, ValType::I32, 1, ¬hing));
1232 }
1233 case uint32_t(ThreadOp::I32AtomicStore16U): {
1234 LinearMemoryAddress<Nothing> addr;
1235 CHECK(iter.readAtomicStore(&addr, ValType::I32, 2, ¬hing));
1236 }
1237 case uint32_t(ThreadOp::I64AtomicStore8U): {
1238 LinearMemoryAddress<Nothing> addr;
1239 CHECK(iter.readAtomicStore(&addr, ValType::I64, 1, ¬hing));
1240 }
1241 case uint32_t(ThreadOp::I64AtomicStore16U): {
1242 LinearMemoryAddress<Nothing> addr;
1243 CHECK(iter.readAtomicStore(&addr, ValType::I64, 2, ¬hing));
1244 }
1245 case uint32_t(ThreadOp::I64AtomicStore32U): {
1246 LinearMemoryAddress<Nothing> addr;
1247 CHECK(iter.readAtomicStore(&addr, ValType::I64, 4, ¬hing));
1248 }
1249 case uint32_t(ThreadOp::I32AtomicAdd):
1250 case uint32_t(ThreadOp::I32AtomicSub):
1251 case uint32_t(ThreadOp::I32AtomicAnd):
1252 case uint32_t(ThreadOp::I32AtomicOr):
1253 case uint32_t(ThreadOp::I32AtomicXor):
1254 case uint32_t(ThreadOp::I32AtomicXchg): {
1255 LinearMemoryAddress<Nothing> addr;
1256 CHECK(iter.readAtomicRMW(&addr, ValType::I32, 4, ¬hing));
1257 }
1258 case uint32_t(ThreadOp::I64AtomicAdd):
1259 case uint32_t(ThreadOp::I64AtomicSub):
1260 case uint32_t(ThreadOp::I64AtomicAnd):
1261 case uint32_t(ThreadOp::I64AtomicOr):
1262 case uint32_t(ThreadOp::I64AtomicXor):
1263 case uint32_t(ThreadOp::I64AtomicXchg): {
1264 LinearMemoryAddress<Nothing> addr;
1265 CHECK(iter.readAtomicRMW(&addr, ValType::I64, 8, ¬hing));
1266 }
1267 case uint32_t(ThreadOp::I32AtomicAdd8U):
1268 case uint32_t(ThreadOp::I32AtomicSub8U):
1269 case uint32_t(ThreadOp::I32AtomicAnd8U):
1270 case uint32_t(ThreadOp::I32AtomicOr8U):
1271 case uint32_t(ThreadOp::I32AtomicXor8U):
1272 case uint32_t(ThreadOp::I32AtomicXchg8U): {
1273 LinearMemoryAddress<Nothing> addr;
1274 CHECK(iter.readAtomicRMW(&addr, ValType::I32, 1, ¬hing));
1275 }
1276 case uint32_t(ThreadOp::I32AtomicAdd16U):
1277 case uint32_t(ThreadOp::I32AtomicSub16U):
1278 case uint32_t(ThreadOp::I32AtomicAnd16U):
1279 case uint32_t(ThreadOp::I32AtomicOr16U):
1280 case uint32_t(ThreadOp::I32AtomicXor16U):
1281 case uint32_t(ThreadOp::I32AtomicXchg16U): {
1282 LinearMemoryAddress<Nothing> addr;
1283 CHECK(iter.readAtomicRMW(&addr, ValType::I32, 2, ¬hing));
1284 }
1285 case uint32_t(ThreadOp::I64AtomicAdd8U):
1286 case uint32_t(ThreadOp::I64AtomicSub8U):
1287 case uint32_t(ThreadOp::I64AtomicAnd8U):
1288 case uint32_t(ThreadOp::I64AtomicOr8U):
1289 case uint32_t(ThreadOp::I64AtomicXor8U):
1290 case uint32_t(ThreadOp::I64AtomicXchg8U): {
1291 LinearMemoryAddress<Nothing> addr;
1292 CHECK(iter.readAtomicRMW(&addr, ValType::I64, 1, ¬hing));
1293 }
1294 case uint32_t(ThreadOp::I64AtomicAdd16U):
1295 case uint32_t(ThreadOp::I64AtomicSub16U):
1296 case uint32_t(ThreadOp::I64AtomicAnd16U):
1297 case uint32_t(ThreadOp::I64AtomicOr16U):
1298 case uint32_t(ThreadOp::I64AtomicXor16U):
1299 case uint32_t(ThreadOp::I64AtomicXchg16U): {
1300 LinearMemoryAddress<Nothing> addr;
1301 CHECK(iter.readAtomicRMW(&addr, ValType::I64, 2, ¬hing));
1302 }
1303 case uint32_t(ThreadOp::I64AtomicAdd32U):
1304 case uint32_t(ThreadOp::I64AtomicSub32U):
1305 case uint32_t(ThreadOp::I64AtomicAnd32U):
1306 case uint32_t(ThreadOp::I64AtomicOr32U):
1307 case uint32_t(ThreadOp::I64AtomicXor32U):
1308 case uint32_t(ThreadOp::I64AtomicXchg32U): {
1309 LinearMemoryAddress<Nothing> addr;
1310 CHECK(iter.readAtomicRMW(&addr, ValType::I64, 4, ¬hing));
1311 }
1312 case uint32_t(ThreadOp::I32AtomicCmpXchg): {
1313 LinearMemoryAddress<Nothing> addr;
1314 CHECK(iter.readAtomicCmpXchg(&addr, ValType::I32, 4, ¬hing,
1315 ¬hing));
1316 }
1317 case uint32_t(ThreadOp::I64AtomicCmpXchg): {
1318 LinearMemoryAddress<Nothing> addr;
1319 CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 8, ¬hing,
1320 ¬hing));
1321 }
1322 case uint32_t(ThreadOp::I32AtomicCmpXchg8U): {
1323 LinearMemoryAddress<Nothing> addr;
1324 CHECK(iter.readAtomicCmpXchg(&addr, ValType::I32, 1, ¬hing,
1325 ¬hing));
1326 }
1327 case uint32_t(ThreadOp::I32AtomicCmpXchg16U): {
1328 LinearMemoryAddress<Nothing> addr;
1329 CHECK(iter.readAtomicCmpXchg(&addr, ValType::I32, 2, ¬hing,
1330 ¬hing));
1331 }
1332 case uint32_t(ThreadOp::I64AtomicCmpXchg8U): {
1333 LinearMemoryAddress<Nothing> addr;
1334 CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 1, ¬hing,
1335 ¬hing));
1336 }
1337 case uint32_t(ThreadOp::I64AtomicCmpXchg16U): {
1338 LinearMemoryAddress<Nothing> addr;
1339 CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 2, ¬hing,
1340 ¬hing));
1341 }
1342 case uint32_t(ThreadOp::I64AtomicCmpXchg32U): {
1343 LinearMemoryAddress<Nothing> addr;
1344 CHECK(iter.readAtomicCmpXchg(&addr, ValType::I64, 4, ¬hing,
1345 ¬hing));
1346 }
1347 default:
1348 return iter.unrecognizedOpcode(&op);
1349 }
1350 break;
1351 }
1352 case uint16_t(Op::MozPrefix):
1353 return iter.unrecognizedOpcode(&op);
1354 default:
1355 return iter.unrecognizedOpcode(&op);
1356 }
1357 }
1358
1359 MOZ_CRASH("unreachable");
1360
1361 #undef CHECK
1362 }
1363
ValidateFunctionBody(const ModuleEnvironment & env,uint32_t funcIndex,uint32_t bodySize,Decoder & d)1364 bool wasm::ValidateFunctionBody(const ModuleEnvironment& env,
1365 uint32_t funcIndex, uint32_t bodySize,
1366 Decoder& d) {
1367 ValTypeVector locals;
1368 if (!locals.appendAll(env.funcs[funcIndex].type->args())) {
1369 return false;
1370 }
1371
1372 const uint8_t* bodyBegin = d.currentPosition();
1373
1374 if (!DecodeLocalEntries(d, env.types, env.features, &locals)) {
1375 return false;
1376 }
1377
1378 if (!DecodeFunctionBodyExprs(env, funcIndex, locals, bodyBegin + bodySize,
1379 &d)) {
1380 return false;
1381 }
1382
1383 return true;
1384 }
1385
1386 // Section macros.
1387
DecodePreamble(Decoder & d)1388 static bool DecodePreamble(Decoder& d) {
1389 if (d.bytesRemain() > MaxModuleBytes) {
1390 return d.fail("module too big");
1391 }
1392
1393 uint32_t u32;
1394 if (!d.readFixedU32(&u32) || u32 != MagicNumber) {
1395 return d.fail("failed to match magic number");
1396 }
1397
1398 if (!d.readFixedU32(&u32) || u32 != EncodingVersion) {
1399 return d.failf("binary version 0x%" PRIx32
1400 " does not match expected version 0x%" PRIx32,
1401 u32, EncodingVersion);
1402 }
1403
1404 return true;
1405 }
1406
1407 enum class TypeState { None, Gc, ForwardGc, Func };
1408
1409 using TypeStateVector = Vector<TypeState, 0, SystemAllocPolicy>;
1410
1411 template <class T>
ValidateTypeState(Decoder & d,TypeStateVector * typeState,T type)1412 static bool ValidateTypeState(Decoder& d, TypeStateVector* typeState, T type) {
1413 if (!type.isTypeIndex()) {
1414 return true;
1415 }
1416
1417 uint32_t refTypeIndex = type.refType().typeIndex();
1418 switch ((*typeState)[refTypeIndex]) {
1419 case TypeState::None:
1420 (*typeState)[refTypeIndex] = TypeState::ForwardGc;
1421 break;
1422 case TypeState::Gc:
1423 case TypeState::ForwardGc:
1424 break;
1425 case TypeState::Func:
1426 return d.fail("ref does not reference a gc type");
1427 }
1428 return true;
1429 }
1430
1431 #ifdef WASM_PRIVATE_REFTYPES
FuncTypeIsJSCompatible(Decoder & d,const FuncType & ft)1432 static bool FuncTypeIsJSCompatible(Decoder& d, const FuncType& ft) {
1433 if (ft.exposesTypeIndex()) {
1434 return d.fail("cannot expose indexed reference type");
1435 }
1436 return true;
1437 }
1438 #endif
1439
DecodeTypeVector(Decoder & d,ModuleEnvironment * env,TypeStateVector * typeState,uint32_t count,ValTypeVector * types)1440 static bool DecodeTypeVector(Decoder& d, ModuleEnvironment* env,
1441 TypeStateVector* typeState, uint32_t count,
1442 ValTypeVector* types) {
1443 if (!types->resize(count)) {
1444 return false;
1445 }
1446
1447 for (uint32_t i = 0; i < count; i++) {
1448 if (!d.readValType(env->types.length(), env->features, &(*types)[i])) {
1449 return false;
1450 }
1451 if (!ValidateTypeState(d, typeState, (*types)[i])) {
1452 return false;
1453 }
1454 }
1455 return true;
1456 }
1457
DecodeFuncType(Decoder & d,ModuleEnvironment * env,TypeStateVector * typeState,uint32_t typeIndex)1458 static bool DecodeFuncType(Decoder& d, ModuleEnvironment* env,
1459 TypeStateVector* typeState, uint32_t typeIndex) {
1460 uint32_t numArgs;
1461 if (!d.readVarU32(&numArgs)) {
1462 return d.fail("bad number of function args");
1463 }
1464 if (numArgs > MaxParams) {
1465 return d.fail("too many arguments in signature");
1466 }
1467 ValTypeVector args;
1468 if (!DecodeTypeVector(d, env, typeState, numArgs, &args)) {
1469 return false;
1470 }
1471
1472 uint32_t numResults;
1473 if (!d.readVarU32(&numResults)) {
1474 return d.fail("bad number of function returns");
1475 }
1476 if (numResults > MaxResults) {
1477 return d.fail("too many returns in signature");
1478 }
1479 ValTypeVector results;
1480 if (!DecodeTypeVector(d, env, typeState, numResults, &results)) {
1481 return false;
1482 }
1483
1484 if ((*typeState)[typeIndex] != TypeState::None) {
1485 return d.fail("function type entry referenced as gc");
1486 }
1487
1488 env->types[typeIndex] =
1489 TypeDef(FuncType(std::move(args), std::move(results)));
1490 (*typeState)[typeIndex] = TypeState::Func;
1491
1492 return true;
1493 }
1494
DecodeStructType(Decoder & d,ModuleEnvironment * env,TypeStateVector * typeState,uint32_t typeIndex)1495 static bool DecodeStructType(Decoder& d, ModuleEnvironment* env,
1496 TypeStateVector* typeState, uint32_t typeIndex) {
1497 if (!env->gcEnabled()) {
1498 return d.fail("Structure types not enabled");
1499 }
1500
1501 if ((*typeState)[typeIndex] != TypeState::None &&
1502 (*typeState)[typeIndex] != TypeState::ForwardGc) {
1503 return d.fail("gc type entry referenced as function");
1504 }
1505
1506 uint32_t numFields;
1507 if (!d.readVarU32(&numFields)) {
1508 return d.fail("Bad number of fields");
1509 }
1510
1511 if (numFields > MaxStructFields) {
1512 return d.fail("too many fields in struct");
1513 }
1514
1515 StructFieldVector fields;
1516 if (!fields.resize(numFields)) {
1517 return false;
1518 }
1519
1520 for (uint32_t i = 0; i < numFields; i++) {
1521 if (!d.readPackedType(env->types.length(), env->features,
1522 &fields[i].type)) {
1523 return false;
1524 }
1525
1526 uint8_t flags;
1527 if (!d.readFixedU8(&flags)) {
1528 return d.fail("expected flag");
1529 }
1530 if ((flags & ~uint8_t(FieldFlags::AllowedMask)) != 0) {
1531 return d.fail("garbage flag bits");
1532 }
1533 fields[i].isMutable = flags & uint8_t(FieldFlags::Mutable);
1534
1535 if (!ValidateTypeState(d, typeState, fields[i].type)) {
1536 return false;
1537 }
1538 }
1539
1540 StructType structType = StructType(std::move(fields));
1541
1542 if (!structType.computeLayout()) {
1543 return d.fail("Struct type too large");
1544 }
1545
1546 env->types[typeIndex] = TypeDef(std::move(structType));
1547 (*typeState)[typeIndex] = TypeState::Gc;
1548
1549 return true;
1550 }
1551
DecodeArrayType(Decoder & d,ModuleEnvironment * env,TypeStateVector * typeState,uint32_t typeIndex)1552 static bool DecodeArrayType(Decoder& d, ModuleEnvironment* env,
1553 TypeStateVector* typeState, uint32_t typeIndex) {
1554 if (!env->gcEnabled()) {
1555 return d.fail("gc types not enabled");
1556 }
1557
1558 if ((*typeState)[typeIndex] != TypeState::None &&
1559 (*typeState)[typeIndex] != TypeState::ForwardGc) {
1560 return d.fail("gc type entry referenced as function");
1561 }
1562
1563 FieldType elementType;
1564 if (!d.readFieldType(env->types.length(), env->features, &elementType)) {
1565 return false;
1566 }
1567
1568 uint8_t flags;
1569 if (!d.readFixedU8(&flags)) {
1570 return d.fail("expected flag");
1571 }
1572 if ((flags & ~uint8_t(FieldFlags::AllowedMask)) != 0) {
1573 return d.fail("garbage flag bits");
1574 }
1575 bool isMutable = flags & uint8_t(FieldFlags::Mutable);
1576
1577 if (!ValidateTypeState(d, typeState, elementType)) {
1578 return false;
1579 }
1580
1581 env->types[typeIndex] = TypeDef(ArrayType(elementType, isMutable));
1582 (*typeState)[typeIndex] = TypeState::Gc;
1583
1584 return true;
1585 }
1586
DecodeTypeSection(Decoder & d,ModuleEnvironment * env)1587 static bool DecodeTypeSection(Decoder& d, ModuleEnvironment* env) {
1588 MaybeSectionRange range;
1589 if (!d.startSection(SectionId::Type, env, &range, "type")) {
1590 return false;
1591 }
1592 if (!range) {
1593 return true;
1594 }
1595
1596 uint32_t numTypes;
1597 if (!d.readVarU32(&numTypes)) {
1598 return d.fail("expected number of types");
1599 }
1600
1601 if (numTypes > MaxTypes) {
1602 return d.fail("too many types");
1603 }
1604
1605 if (!env->types.resize(numTypes) || !env->typeIds.resize(numTypes)) {
1606 return false;
1607 }
1608
1609 TypeStateVector typeState;
1610 if (!typeState.appendN(TypeState::None, numTypes)) {
1611 return false;
1612 }
1613
1614 for (uint32_t typeIndex = 0; typeIndex < numTypes; typeIndex++) {
1615 uint8_t form;
1616 if (!d.readFixedU8(&form)) {
1617 return d.fail("expected type form");
1618 }
1619
1620 switch (form) {
1621 case uint8_t(TypeCode::Func):
1622 if (!DecodeFuncType(d, env, &typeState, typeIndex)) {
1623 return false;
1624 }
1625 break;
1626 case uint8_t(TypeCode::Struct):
1627 if (!DecodeStructType(d, env, &typeState, typeIndex)) {
1628 return false;
1629 }
1630 break;
1631 case uint8_t(TypeCode::Array):
1632 if (!DecodeArrayType(d, env, &typeState, typeIndex)) {
1633 return false;
1634 }
1635 break;
1636 default:
1637 return d.fail("expected type form");
1638 }
1639 }
1640
1641 return d.finishSection(*range, "type");
1642 }
1643
DecodeName(Decoder & d)1644 static UniqueChars DecodeName(Decoder& d) {
1645 uint32_t numBytes;
1646 if (!d.readVarU32(&numBytes)) {
1647 return nullptr;
1648 }
1649
1650 if (numBytes > MaxStringBytes) {
1651 return nullptr;
1652 }
1653
1654 const uint8_t* bytes;
1655 if (!d.readBytes(numBytes, &bytes)) {
1656 return nullptr;
1657 }
1658
1659 if (!IsUtf8(AsChars(Span(bytes, numBytes)))) {
1660 return nullptr;
1661 }
1662
1663 UniqueChars name(js_pod_malloc<char>(numBytes + 1));
1664 if (!name) {
1665 return nullptr;
1666 }
1667
1668 memcpy(name.get(), bytes, numBytes);
1669 name[numBytes] = '\0';
1670
1671 return name;
1672 }
1673
DecodeFuncTypeIndex(Decoder & d,const TypeContext & types,uint32_t * funcTypeIndex)1674 static bool DecodeFuncTypeIndex(Decoder& d, const TypeContext& types,
1675 uint32_t* funcTypeIndex) {
1676 if (!d.readVarU32(funcTypeIndex)) {
1677 return d.fail("expected signature index");
1678 }
1679
1680 if (*funcTypeIndex >= types.length()) {
1681 return d.fail("signature index out of range");
1682 }
1683
1684 const TypeDef& def = types[*funcTypeIndex];
1685
1686 if (!def.isFuncType()) {
1687 return d.fail("signature index references non-signature");
1688 }
1689
1690 return true;
1691 }
1692
DecodeLimits(Decoder & d,Limits * limits,Shareable allowShared=Shareable::False)1693 static bool DecodeLimits(Decoder& d, Limits* limits,
1694 Shareable allowShared = Shareable::False) {
1695 uint8_t flags;
1696 if (!d.readFixedU8(&flags)) {
1697 return d.fail("expected flags");
1698 }
1699
1700 uint8_t mask = allowShared == Shareable::True
1701 ? uint8_t(MemoryMasks::AllowShared)
1702 : uint8_t(MemoryMasks::AllowUnshared);
1703
1704 if (flags & ~uint8_t(mask)) {
1705 return d.failf("unexpected bits set in flags: %" PRIu32,
1706 uint32_t(flags & ~uint8_t(mask)));
1707 }
1708
1709 uint32_t initial;
1710 if (!d.readVarU32(&initial)) {
1711 return d.fail("expected initial length");
1712 }
1713 limits->initial = initial;
1714
1715 if (flags & uint8_t(MemoryTableFlags::HasMaximum)) {
1716 uint32_t maximum;
1717 if (!d.readVarU32(&maximum)) {
1718 return d.fail("expected maximum length");
1719 }
1720
1721 if (limits->initial > maximum) {
1722 return d.failf(
1723 "memory size minimum must not be greater than maximum; "
1724 "maximum length %" PRIu32 " is less than initial length %" PRIu64,
1725 maximum, limits->initial);
1726 }
1727
1728 limits->maximum.emplace(uint64_t(maximum));
1729 }
1730
1731 limits->shared = Shareable::False;
1732
1733 if (allowShared == Shareable::True) {
1734 if ((flags & uint8_t(MemoryTableFlags::IsShared)) &&
1735 !(flags & uint8_t(MemoryTableFlags::HasMaximum))) {
1736 return d.fail("maximum length required for shared memory");
1737 }
1738
1739 limits->shared = (flags & uint8_t(MemoryTableFlags::IsShared))
1740 ? Shareable::True
1741 : Shareable::False;
1742 }
1743
1744 return true;
1745 }
1746
DecodeTableTypeAndLimits(Decoder & d,const FeatureArgs & features,const TypeContext & types,TableDescVector * tables)1747 static bool DecodeTableTypeAndLimits(Decoder& d, const FeatureArgs& features,
1748 const TypeContext& types,
1749 TableDescVector* tables) {
1750 RefType tableElemType;
1751 if (!d.readRefType(types, features, &tableElemType)) {
1752 return false;
1753 }
1754 if (!tableElemType.isNullable()) {
1755 return d.fail("non-nullable references not supported in tables");
1756 }
1757
1758 Limits limits;
1759 if (!DecodeLimits(d, &limits)) {
1760 return false;
1761 }
1762
1763 // If there's a maximum, check it is in range. The check to exclude
1764 // initial > maximum is carried out by the DecodeLimits call above, so
1765 // we don't repeat it here.
1766 if (limits.initial > MaxTableLimitField ||
1767 ((limits.maximum.isSome() &&
1768 limits.maximum.value() > MaxTableLimitField))) {
1769 return d.fail("too many table elements");
1770 }
1771
1772 if (tables->length() >= MaxTables) {
1773 return d.fail("too many tables");
1774 }
1775
1776 // The rest of the runtime expects table limits to be within a 32-bit range.
1777 static_assert(MaxTableLimitField <= UINT32_MAX, "invariant");
1778 uint32_t initialLength = uint32_t(limits.initial);
1779 Maybe<uint32_t> maximumLength;
1780 if (limits.maximum) {
1781 maximumLength = Some(uint32_t(*limits.maximum));
1782 }
1783
1784 return tables->emplaceBack(tableElemType, initialLength, maximumLength,
1785 /* isAsmJS */ false);
1786 }
1787
GlobalIsJSCompatible(Decoder & d,ValType type)1788 static bool GlobalIsJSCompatible(Decoder& d, ValType type) {
1789 switch (type.kind()) {
1790 case ValType::I32:
1791 case ValType::F32:
1792 case ValType::F64:
1793 case ValType::I64:
1794 case ValType::V128:
1795 break;
1796 case ValType::Ref:
1797 switch (type.refTypeKind()) {
1798 case RefType::Func:
1799 case RefType::Extern:
1800 case RefType::Eq:
1801 break;
1802 case RefType::TypeIndex:
1803 #ifdef WASM_PRIVATE_REFTYPES
1804 return d.fail("cannot expose indexed reference type");
1805 #else
1806 break;
1807 #endif
1808 default:
1809 return d.fail("unexpected variable type in global import/export");
1810 }
1811 break;
1812 default:
1813 return d.fail("unexpected variable type in global import/export");
1814 }
1815
1816 return true;
1817 }
1818
DecodeGlobalType(Decoder & d,const TypeContext & types,const FeatureArgs & features,ValType * type,bool * isMutable)1819 static bool DecodeGlobalType(Decoder& d, const TypeContext& types,
1820 const FeatureArgs& features, ValType* type,
1821 bool* isMutable) {
1822 if (!d.readValType(types, features, type)) {
1823 return d.fail("expected global type");
1824 }
1825
1826 if (type->isReference() && !type->isNullable()) {
1827 return d.fail("non-nullable references not supported in globals");
1828 }
1829
1830 uint8_t flags;
1831 if (!d.readFixedU8(&flags)) {
1832 return d.fail("expected global flags");
1833 }
1834
1835 if (flags & ~uint8_t(GlobalTypeImmediate::AllowedMask)) {
1836 return d.fail("unexpected bits set in global flags");
1837 }
1838
1839 *isMutable = flags & uint8_t(GlobalTypeImmediate::IsMutable);
1840 return true;
1841 }
1842
DecodeMemoryLimits(Decoder & d,ModuleEnvironment * env)1843 static bool DecodeMemoryLimits(Decoder& d, ModuleEnvironment* env) {
1844 if (env->usesMemory()) {
1845 return d.fail("already have default memory");
1846 }
1847
1848 Limits limits;
1849 if (!DecodeLimits(d, &limits, Shareable::True)) {
1850 return false;
1851 }
1852
1853 if (limits.initial > MaxMemory32LimitField) {
1854 return d.fail("initial memory size too big");
1855 }
1856
1857 if (limits.maximum && *limits.maximum > MaxMemory32LimitField) {
1858 return d.fail("maximum memory size too big");
1859 }
1860
1861 if (limits.shared == Shareable::True &&
1862 env->sharedMemoryEnabled() == Shareable::False) {
1863 return d.fail("shared memory is disabled");
1864 }
1865
1866 env->memory = Some(MemoryDesc(MemoryKind::Memory32, limits));
1867 return true;
1868 }
1869
1870 #ifdef ENABLE_WASM_EXCEPTIONS
EventIsJSCompatible(Decoder & d,const ValTypeVector & type)1871 static bool EventIsJSCompatible(Decoder& d, const ValTypeVector& type) {
1872 for (auto t : type) {
1873 if (t.isTypeIndex()) {
1874 return d.fail("cannot expose indexed reference type");
1875 }
1876 }
1877
1878 return true;
1879 }
1880
DecodeEvent(Decoder & d,ModuleEnvironment * env,EventKind * eventKind,uint32_t * funcTypeIndex)1881 static bool DecodeEvent(Decoder& d, ModuleEnvironment* env,
1882 EventKind* eventKind, uint32_t* funcTypeIndex) {
1883 uint32_t eventCode;
1884 if (!d.readVarU32(&eventCode)) {
1885 return d.fail("expected event kind");
1886 }
1887
1888 if (EventKind(eventCode) != EventKind::Exception) {
1889 return d.fail("illegal event kind");
1890 }
1891 *eventKind = EventKind(eventCode);
1892
1893 if (!d.readVarU32(funcTypeIndex)) {
1894 return d.fail("expected function index in event");
1895 }
1896 if (*funcTypeIndex >= env->numTypes()) {
1897 return d.fail("function type index in event out of bounds");
1898 }
1899 if (!env->types[*funcTypeIndex].isFuncType()) {
1900 return d.fail("function type index must index a function type");
1901 }
1902 if (env->types[*funcTypeIndex].funcType().results().length() != 0) {
1903 return d.fail("exception function types must not return anything");
1904 }
1905 return true;
1906 }
1907 #endif
1908
1909 struct CStringPair {
1910 const char* first;
1911 const char* second;
1912
CStringPairCStringPair1913 CStringPair(const char* first, const char* second)
1914 : first(first), second(second) {}
1915
1916 using Key = CStringPair;
1917 using Lookup = CStringPair;
1918
hashCStringPair1919 static mozilla::HashNumber hash(const Lookup& l) {
1920 return mozilla::AddToHash(mozilla::HashString(l.first),
1921 mozilla::HashString(l.second));
1922 }
matchCStringPair1923 static bool match(const Key& k, const Lookup& l) {
1924 return !strcmp(k.first, l.first) && !strcmp(k.second, l.second);
1925 }
1926 };
1927
1928 using CStringPairSet = HashSet<CStringPair, CStringPair, SystemAllocPolicy>;
1929
DecodeImport(Decoder & d,ModuleEnvironment * env,CStringPairSet * dupSet)1930 static bool DecodeImport(Decoder& d, ModuleEnvironment* env,
1931 CStringPairSet* dupSet) {
1932 UniqueChars moduleName = DecodeName(d);
1933 if (!moduleName) {
1934 return d.fail("expected valid import module name");
1935 }
1936
1937 UniqueChars funcName = DecodeName(d);
1938 if (!funcName) {
1939 return d.fail("expected valid import func name");
1940 }
1941
1942 // It is valid to store raw pointers in dupSet because moduleName and funcName
1943 // become owned by env->imports on all non-error paths, outliving dupSet.
1944 CStringPair pair(moduleName.get(), funcName.get());
1945 CStringPairSet::AddPtr p = dupSet->lookupForAdd(pair);
1946 if (p) {
1947 env->usesDuplicateImports = true;
1948 } else if (!dupSet->add(p, pair)) {
1949 return false;
1950 }
1951
1952 uint8_t rawImportKind;
1953 if (!d.readFixedU8(&rawImportKind)) {
1954 return d.fail("failed to read import kind");
1955 }
1956
1957 DefinitionKind importKind = DefinitionKind(rawImportKind);
1958
1959 switch (importKind) {
1960 case DefinitionKind::Function: {
1961 uint32_t funcTypeIndex;
1962 if (!DecodeFuncTypeIndex(d, env->types, &funcTypeIndex)) {
1963 return false;
1964 }
1965 #ifdef WASM_PRIVATE_REFTYPES
1966 if (!FuncTypeIsJSCompatible(d, env->types.funcType(funcTypeIndex))) {
1967 return false;
1968 }
1969 #endif
1970 if (!env->funcs.append(FuncDesc(&env->types.funcType(funcTypeIndex),
1971 &env->typeIds[funcTypeIndex],
1972 funcTypeIndex))) {
1973 return false;
1974 }
1975 if (env->funcs.length() > MaxFuncs) {
1976 return d.fail("too many functions");
1977 }
1978 break;
1979 }
1980 case DefinitionKind::Table: {
1981 if (!DecodeTableTypeAndLimits(d, env->features, env->types,
1982 &env->tables)) {
1983 return false;
1984 }
1985 env->tables.back().importedOrExported = true;
1986 break;
1987 }
1988 case DefinitionKind::Memory: {
1989 if (!DecodeMemoryLimits(d, env)) {
1990 return false;
1991 }
1992 break;
1993 }
1994 case DefinitionKind::Global: {
1995 ValType type;
1996 bool isMutable;
1997 if (!DecodeGlobalType(d, env->types, env->features, &type, &isMutable)) {
1998 return false;
1999 }
2000 if (!GlobalIsJSCompatible(d, type)) {
2001 return false;
2002 }
2003 if (!env->globals.append(
2004 GlobalDesc(type, isMutable, env->globals.length()))) {
2005 return false;
2006 }
2007 if (env->globals.length() > MaxGlobals) {
2008 return d.fail("too many globals");
2009 }
2010 break;
2011 }
2012 #ifdef ENABLE_WASM_EXCEPTIONS
2013 case DefinitionKind::Event: {
2014 EventKind eventKind;
2015 uint32_t funcTypeIndex;
2016 if (!DecodeEvent(d, env, &eventKind, &funcTypeIndex)) {
2017 return false;
2018 }
2019 const ValTypeVector& args = env->types[funcTypeIndex].funcType().args();
2020 # ifdef WASM_PRIVATE_REFTYPES
2021 if (!EventIsJSCompatible(d, args)) {
2022 return false;
2023 }
2024 # endif
2025 ValTypeVector eventArgs;
2026 if (!eventArgs.appendAll(args)) {
2027 return false;
2028 }
2029 if (!env->events.emplaceBack(eventKind, std::move(eventArgs))) {
2030 return false;
2031 }
2032 if (env->events.length() > MaxEvents) {
2033 return d.fail("too many events");
2034 }
2035 break;
2036 }
2037 #endif
2038 default:
2039 return d.fail("unsupported import kind");
2040 }
2041
2042 return env->imports.emplaceBack(std::move(moduleName), std::move(funcName),
2043 importKind);
2044 }
2045
DecodeImportSection(Decoder & d,ModuleEnvironment * env)2046 static bool DecodeImportSection(Decoder& d, ModuleEnvironment* env) {
2047 MaybeSectionRange range;
2048 if (!d.startSection(SectionId::Import, env, &range, "import")) {
2049 return false;
2050 }
2051 if (!range) {
2052 return true;
2053 }
2054
2055 uint32_t numImports;
2056 if (!d.readVarU32(&numImports)) {
2057 return d.fail("failed to read number of imports");
2058 }
2059
2060 if (numImports > MaxImports) {
2061 return d.fail("too many imports");
2062 }
2063
2064 CStringPairSet dupSet;
2065 for (uint32_t i = 0; i < numImports; i++) {
2066 if (!DecodeImport(d, env, &dupSet)) {
2067 return false;
2068 }
2069 }
2070
2071 if (!d.finishSection(*range, "import")) {
2072 return false;
2073 }
2074
2075 // The global data offsets will be filled in by ModuleGenerator::init.
2076 if (!env->funcImportGlobalDataOffsets.resize(env->funcs.length())) {
2077 return false;
2078 }
2079
2080 return true;
2081 }
2082
DecodeFunctionSection(Decoder & d,ModuleEnvironment * env)2083 static bool DecodeFunctionSection(Decoder& d, ModuleEnvironment* env) {
2084 MaybeSectionRange range;
2085 if (!d.startSection(SectionId::Function, env, &range, "function")) {
2086 return false;
2087 }
2088 if (!range) {
2089 return true;
2090 }
2091
2092 uint32_t numDefs;
2093 if (!d.readVarU32(&numDefs)) {
2094 return d.fail("expected number of function definitions");
2095 }
2096
2097 CheckedInt<uint32_t> numFuncs = env->funcs.length();
2098 numFuncs += numDefs;
2099 if (!numFuncs.isValid() || numFuncs.value() > MaxFuncs) {
2100 return d.fail("too many functions");
2101 }
2102
2103 if (!env->funcs.reserve(numFuncs.value())) {
2104 return false;
2105 }
2106
2107 for (uint32_t i = 0; i < numDefs; i++) {
2108 uint32_t funcTypeIndex;
2109 if (!DecodeFuncTypeIndex(d, env->types, &funcTypeIndex)) {
2110 return false;
2111 }
2112 env->funcs.infallibleAppend(FuncDesc(&env->types.funcType(funcTypeIndex),
2113 &env->typeIds[funcTypeIndex],
2114 funcTypeIndex));
2115 }
2116
2117 return d.finishSection(*range, "function");
2118 }
2119
DecodeTableSection(Decoder & d,ModuleEnvironment * env)2120 static bool DecodeTableSection(Decoder& d, ModuleEnvironment* env) {
2121 MaybeSectionRange range;
2122 if (!d.startSection(SectionId::Table, env, &range, "table")) {
2123 return false;
2124 }
2125 if (!range) {
2126 return true;
2127 }
2128
2129 uint32_t numTables;
2130 if (!d.readVarU32(&numTables)) {
2131 return d.fail("failed to read number of tables");
2132 }
2133
2134 for (uint32_t i = 0; i < numTables; ++i) {
2135 if (!DecodeTableTypeAndLimits(d, env->features, env->types, &env->tables)) {
2136 return false;
2137 }
2138 }
2139
2140 return d.finishSection(*range, "table");
2141 }
2142
DecodeMemorySection(Decoder & d,ModuleEnvironment * env)2143 static bool DecodeMemorySection(Decoder& d, ModuleEnvironment* env) {
2144 MaybeSectionRange range;
2145 if (!d.startSection(SectionId::Memory, env, &range, "memory")) {
2146 return false;
2147 }
2148 if (!range) {
2149 return true;
2150 }
2151
2152 uint32_t numMemories;
2153 if (!d.readVarU32(&numMemories)) {
2154 return d.fail("failed to read number of memories");
2155 }
2156
2157 if (numMemories > 1) {
2158 return d.fail("the number of memories must be at most one");
2159 }
2160
2161 for (uint32_t i = 0; i < numMemories; ++i) {
2162 if (!DecodeMemoryLimits(d, env)) {
2163 return false;
2164 }
2165 }
2166
2167 return d.finishSection(*range, "memory");
2168 }
2169
DecodeGlobalSection(Decoder & d,ModuleEnvironment * env)2170 static bool DecodeGlobalSection(Decoder& d, ModuleEnvironment* env) {
2171 MaybeSectionRange range;
2172 if (!d.startSection(SectionId::Global, env, &range, "global")) {
2173 return false;
2174 }
2175 if (!range) {
2176 return true;
2177 }
2178
2179 uint32_t numDefs;
2180 if (!d.readVarU32(&numDefs)) {
2181 return d.fail("expected number of globals");
2182 }
2183
2184 CheckedInt<uint32_t> numGlobals = env->globals.length();
2185 numGlobals += numDefs;
2186 if (!numGlobals.isValid() || numGlobals.value() > MaxGlobals) {
2187 return d.fail("too many globals");
2188 }
2189
2190 if (!env->globals.reserve(numGlobals.value())) {
2191 return false;
2192 }
2193
2194 for (uint32_t i = 0; i < numDefs; i++) {
2195 ValType type;
2196 bool isMutable;
2197 if (!DecodeGlobalType(d, env->types, env->features, &type, &isMutable)) {
2198 return false;
2199 }
2200
2201 InitExpr initializer;
2202 if (!InitExpr::decodeAndValidate(d, env, type, &initializer)) {
2203 return false;
2204 }
2205
2206 env->globals.infallibleAppend(
2207 GlobalDesc(std::move(initializer), isMutable));
2208 }
2209
2210 return d.finishSection(*range, "global");
2211 }
2212
2213 #ifdef ENABLE_WASM_EXCEPTIONS
DecodeEventSection(Decoder & d,ModuleEnvironment * env)2214 static bool DecodeEventSection(Decoder& d, ModuleEnvironment* env) {
2215 MaybeSectionRange range;
2216 if (!d.startSection(SectionId::Event, env, &range, "event")) {
2217 return false;
2218 }
2219 if (!range) {
2220 return true;
2221 }
2222
2223 if (!env->exceptionsEnabled()) {
2224 return d.fail("exceptions not enabled");
2225 }
2226
2227 uint32_t numDefs;
2228 if (!d.readVarU32(&numDefs)) {
2229 return d.fail("expected number of events");
2230 }
2231
2232 CheckedInt<uint32_t> numEvents = env->events.length();
2233 numEvents += numDefs;
2234 if (!numEvents.isValid() || numEvents.value() > MaxEvents) {
2235 return d.fail("too many events");
2236 }
2237
2238 if (!env->events.reserve(numEvents.value())) {
2239 return false;
2240 }
2241
2242 for (uint32_t i = 0; i < numDefs; i++) {
2243 EventKind eventKind;
2244 uint32_t funcTypeIndex;
2245 if (!DecodeEvent(d, env, &eventKind, &funcTypeIndex)) {
2246 return false;
2247 }
2248 const ValTypeVector& args = env->types[funcTypeIndex].funcType().args();
2249 ValTypeVector eventArgs;
2250 if (!eventArgs.appendAll(args)) {
2251 return false;
2252 }
2253 env->events.infallibleEmplaceBack(eventKind, std::move(eventArgs));
2254 }
2255
2256 return d.finishSection(*range, "event");
2257 }
2258 #endif
2259
2260 using CStringSet =
2261 HashSet<const char*, mozilla::CStringHasher, SystemAllocPolicy>;
2262
DecodeExportName(Decoder & d,CStringSet * dupSet)2263 static UniqueChars DecodeExportName(Decoder& d, CStringSet* dupSet) {
2264 UniqueChars exportName = DecodeName(d);
2265 if (!exportName) {
2266 d.fail("expected valid export name");
2267 return nullptr;
2268 }
2269
2270 CStringSet::AddPtr p = dupSet->lookupForAdd(exportName.get());
2271 if (p) {
2272 d.fail("duplicate export");
2273 return nullptr;
2274 }
2275
2276 if (!dupSet->add(p, exportName.get())) {
2277 return nullptr;
2278 }
2279
2280 return exportName;
2281 }
2282
DecodeExport(Decoder & d,ModuleEnvironment * env,CStringSet * dupSet)2283 static bool DecodeExport(Decoder& d, ModuleEnvironment* env,
2284 CStringSet* dupSet) {
2285 UniqueChars fieldName = DecodeExportName(d, dupSet);
2286 if (!fieldName) {
2287 return false;
2288 }
2289
2290 uint8_t exportKind;
2291 if (!d.readFixedU8(&exportKind)) {
2292 return d.fail("failed to read export kind");
2293 }
2294
2295 switch (DefinitionKind(exportKind)) {
2296 case DefinitionKind::Function: {
2297 uint32_t funcIndex;
2298 if (!d.readVarU32(&funcIndex)) {
2299 return d.fail("expected function index");
2300 }
2301
2302 if (funcIndex >= env->numFuncs()) {
2303 return d.fail("exported function index out of bounds");
2304 }
2305 #ifdef WASM_PRIVATE_REFTYPES
2306 if (!FuncTypeIsJSCompatible(d, *env->funcs[funcIndex].type)) {
2307 return false;
2308 }
2309 #endif
2310
2311 env->declareFuncExported(funcIndex, /* eager */ true,
2312 /* canRefFunc */ true);
2313 return env->exports.emplaceBack(std::move(fieldName), funcIndex,
2314 DefinitionKind::Function);
2315 }
2316 case DefinitionKind::Table: {
2317 uint32_t tableIndex;
2318 if (!d.readVarU32(&tableIndex)) {
2319 return d.fail("expected table index");
2320 }
2321
2322 if (tableIndex >= env->tables.length()) {
2323 return d.fail("exported table index out of bounds");
2324 }
2325 env->tables[tableIndex].importedOrExported = true;
2326 return env->exports.emplaceBack(std::move(fieldName), tableIndex,
2327 DefinitionKind::Table);
2328 }
2329 case DefinitionKind::Memory: {
2330 uint32_t memoryIndex;
2331 if (!d.readVarU32(&memoryIndex)) {
2332 return d.fail("expected memory index");
2333 }
2334
2335 if (memoryIndex > 0 || !env->usesMemory()) {
2336 return d.fail("exported memory index out of bounds");
2337 }
2338
2339 return env->exports.emplaceBack(std::move(fieldName),
2340 DefinitionKind::Memory);
2341 }
2342 case DefinitionKind::Global: {
2343 uint32_t globalIndex;
2344 if (!d.readVarU32(&globalIndex)) {
2345 return d.fail("expected global index");
2346 }
2347
2348 if (globalIndex >= env->globals.length()) {
2349 return d.fail("exported global index out of bounds");
2350 }
2351
2352 GlobalDesc* global = &env->globals[globalIndex];
2353 global->setIsExport();
2354 if (!GlobalIsJSCompatible(d, global->type())) {
2355 return false;
2356 }
2357
2358 return env->exports.emplaceBack(std::move(fieldName), globalIndex,
2359 DefinitionKind::Global);
2360 }
2361 #ifdef ENABLE_WASM_EXCEPTIONS
2362 case DefinitionKind::Event: {
2363 uint32_t eventIndex;
2364 if (!d.readVarU32(&eventIndex)) {
2365 return d.fail("expected event index");
2366 }
2367 if (eventIndex >= env->events.length()) {
2368 return d.fail("exported event index out of bounds");
2369 }
2370
2371 # ifdef WASM_PRIVATE_REFTYPES
2372 if (!EventIsJSCompatible(d, env->events[eventIndex].type)) {
2373 return false;
2374 }
2375 # endif
2376
2377 env->events[eventIndex].isExport = true;
2378 return env->exports.emplaceBack(std::move(fieldName), eventIndex,
2379 DefinitionKind::Event);
2380 }
2381 #endif
2382 default:
2383 return d.fail("unexpected export kind");
2384 }
2385
2386 MOZ_CRASH("unreachable");
2387 }
2388
DecodeExportSection(Decoder & d,ModuleEnvironment * env)2389 static bool DecodeExportSection(Decoder& d, ModuleEnvironment* env) {
2390 MaybeSectionRange range;
2391 if (!d.startSection(SectionId::Export, env, &range, "export")) {
2392 return false;
2393 }
2394 if (!range) {
2395 return true;
2396 }
2397
2398 CStringSet dupSet;
2399
2400 uint32_t numExports;
2401 if (!d.readVarU32(&numExports)) {
2402 return d.fail("failed to read number of exports");
2403 }
2404
2405 if (numExports > MaxExports) {
2406 return d.fail("too many exports");
2407 }
2408
2409 for (uint32_t i = 0; i < numExports; i++) {
2410 if (!DecodeExport(d, env, &dupSet)) {
2411 return false;
2412 }
2413 }
2414
2415 return d.finishSection(*range, "export");
2416 }
2417
DecodeStartSection(Decoder & d,ModuleEnvironment * env)2418 static bool DecodeStartSection(Decoder& d, ModuleEnvironment* env) {
2419 MaybeSectionRange range;
2420 if (!d.startSection(SectionId::Start, env, &range, "start")) {
2421 return false;
2422 }
2423 if (!range) {
2424 return true;
2425 }
2426
2427 uint32_t funcIndex;
2428 if (!d.readVarU32(&funcIndex)) {
2429 return d.fail("failed to read start func index");
2430 }
2431
2432 if (funcIndex >= env->numFuncs()) {
2433 return d.fail("unknown start function");
2434 }
2435
2436 const FuncType& funcType = *env->funcs[funcIndex].type;
2437 if (funcType.results().length() > 0) {
2438 return d.fail("start function must not return anything");
2439 }
2440
2441 if (funcType.args().length()) {
2442 return d.fail("start function must be nullary");
2443 }
2444
2445 env->declareFuncExported(funcIndex, /* eager */ true, /* canFuncRef */ false);
2446 env->startFuncIndex = Some(funcIndex);
2447
2448 return d.finishSection(*range, "start");
2449 }
2450
NormalizeElemSegmentKind(ElemSegmentKind decodedKind)2451 static inline ElemSegment::Kind NormalizeElemSegmentKind(
2452 ElemSegmentKind decodedKind) {
2453 switch (decodedKind) {
2454 case ElemSegmentKind::Active:
2455 case ElemSegmentKind::ActiveWithTableIndex: {
2456 return ElemSegment::Kind::Active;
2457 }
2458 case ElemSegmentKind::Passive: {
2459 return ElemSegment::Kind::Passive;
2460 }
2461 case ElemSegmentKind::Declared: {
2462 return ElemSegment::Kind::Declared;
2463 }
2464 }
2465 MOZ_CRASH("unexpected elem segment kind");
2466 }
2467
DecodeElemSection(Decoder & d,ModuleEnvironment * env)2468 static bool DecodeElemSection(Decoder& d, ModuleEnvironment* env) {
2469 MaybeSectionRange range;
2470 if (!d.startSection(SectionId::Elem, env, &range, "elem")) {
2471 return false;
2472 }
2473 if (!range) {
2474 return true;
2475 }
2476
2477 uint32_t numSegments;
2478 if (!d.readVarU32(&numSegments)) {
2479 return d.fail("failed to read number of elem segments");
2480 }
2481
2482 if (numSegments > MaxElemSegments) {
2483 return d.fail("too many elem segments");
2484 }
2485
2486 if (!env->elemSegments.reserve(numSegments)) {
2487 return false;
2488 }
2489
2490 for (uint32_t i = 0; i < numSegments; i++) {
2491 uint32_t segmentFlags;
2492 if (!d.readVarU32(&segmentFlags)) {
2493 return d.fail("expected elem segment flags field");
2494 }
2495
2496 Maybe<ElemSegmentFlags> flags = ElemSegmentFlags::construct(segmentFlags);
2497 if (!flags) {
2498 return d.fail("invalid elem segment flags field");
2499 }
2500
2501 MutableElemSegment seg = js_new<ElemSegment>();
2502 if (!seg) {
2503 return false;
2504 }
2505
2506 ElemSegmentKind kind = flags->kind();
2507 seg->kind = NormalizeElemSegmentKind(kind);
2508
2509 if (kind == ElemSegmentKind::Active ||
2510 kind == ElemSegmentKind::ActiveWithTableIndex) {
2511 if (env->tables.length() == 0) {
2512 return d.fail("active elem segment requires a table");
2513 }
2514
2515 uint32_t tableIndex = 0;
2516 if (kind == ElemSegmentKind::ActiveWithTableIndex &&
2517 !d.readVarU32(&tableIndex)) {
2518 return d.fail("expected table index");
2519 }
2520 if (tableIndex >= env->tables.length()) {
2521 return d.fail("table index out of range for element segment");
2522 }
2523 seg->tableIndex = tableIndex;
2524
2525 InitExpr offset;
2526 if (!InitExpr::decodeAndValidate(d, env, ValType::I32, &offset)) {
2527 return false;
2528 }
2529 seg->offsetIfActive.emplace(std::move(offset));
2530 } else {
2531 // Too many bugs result from keeping this value zero. For passive
2532 // or declared segments, there really is no table index, and we should
2533 // never touch the field.
2534 MOZ_ASSERT(kind == ElemSegmentKind::Passive ||
2535 kind == ElemSegmentKind::Declared);
2536 seg->tableIndex = (uint32_t)-1;
2537 }
2538
2539 ElemSegmentPayload payload = flags->payload();
2540 RefType elemType;
2541
2542 // `ActiveWithTableIndex`, `Declared`, and `Passive` element segments encode
2543 // the type or definition kind of the payload. `Active` element segments are
2544 // restricted to MVP behavior, which assumes only function indices.
2545 if (kind == ElemSegmentKind::Active) {
2546 elemType = RefType::func();
2547 } else {
2548 switch (payload) {
2549 case ElemSegmentPayload::ElemExpression: {
2550 if (!d.readRefType(env->types, env->features, &elemType)) {
2551 return false;
2552 }
2553 break;
2554 }
2555 case ElemSegmentPayload::ExternIndex: {
2556 uint8_t form;
2557 if (!d.readFixedU8(&form)) {
2558 return d.fail("expected type or extern kind");
2559 }
2560
2561 if (form != uint8_t(DefinitionKind::Function)) {
2562 return d.fail(
2563 "segments with extern indices can only contain function "
2564 "references");
2565 }
2566 elemType = RefType::func();
2567 }
2568 }
2569 }
2570
2571 // Check constraints on the element type.
2572 switch (kind) {
2573 case ElemSegmentKind::Active:
2574 case ElemSegmentKind::ActiveWithTableIndex: {
2575 RefType tblElemType = env->tables[seg->tableIndex].elemType;
2576 TypeCache cache;
2577 if (!CheckIsSubtypeOf(d, *env, d.currentOffset(), ValType(elemType),
2578 ValType(tblElemType), &cache)) {
2579 return false;
2580 }
2581 break;
2582 }
2583 case ElemSegmentKind::Declared:
2584 case ElemSegmentKind::Passive: {
2585 // Passive segment element types are checked when used with a
2586 // `table.init` instruction.
2587 break;
2588 }
2589 }
2590 seg->elemType = elemType;
2591
2592 uint32_t numElems;
2593 if (!d.readVarU32(&numElems)) {
2594 return d.fail("expected segment size");
2595 }
2596
2597 if (numElems > MaxElemSegmentLength) {
2598 return d.fail("too many table elements");
2599 }
2600
2601 if (!seg->elemFuncIndices.reserve(numElems)) {
2602 return false;
2603 }
2604
2605 #ifdef WASM_PRIVATE_REFTYPES
2606 // We assume that passive or declared segments may be applied to external
2607 // tables. We can do slightly better: if there are no external tables in
2608 // the module then we don't need to worry about passive or declared
2609 // segments either. But this is a temporary restriction.
2610 bool exportedTable = kind == ElemSegmentKind::Passive ||
2611 kind == ElemSegmentKind::Declared ||
2612 env->tables[seg->tableIndex].importedOrExported;
2613 #endif
2614 bool isAsmJS = seg->active() && env->tables[seg->tableIndex].isAsmJS;
2615
2616 // For passive segments we should use InitExpr but we don't really want to
2617 // generalize the ElemSection data structure yet, so instead read the
2618 // required Ref.Func and End here.
2619
2620 TypeCache cache;
2621 for (uint32_t i = 0; i < numElems; i++) {
2622 bool needIndex = true;
2623
2624 if (payload == ElemSegmentPayload::ElemExpression) {
2625 OpBytes op;
2626 if (!d.readOp(&op)) {
2627 return d.fail("failed to read initializer operation");
2628 }
2629
2630 RefType initType = RefType::extern_();
2631 switch (op.b0) {
2632 case uint16_t(Op::RefFunc):
2633 initType = RefType::func();
2634 break;
2635 case uint16_t(Op::RefNull):
2636 if (!d.readHeapType(env->types, env->features, true, &initType)) {
2637 return false;
2638 }
2639 needIndex = false;
2640 break;
2641 default:
2642 return d.fail("failed to read initializer operation");
2643 }
2644 if (!CheckIsSubtypeOf(d, *env, d.currentOffset(), ValType(initType),
2645 ValType(elemType), &cache)) {
2646 return false;
2647 }
2648 }
2649
2650 uint32_t funcIndex = NullFuncIndex;
2651 if (needIndex) {
2652 if (!d.readVarU32(&funcIndex)) {
2653 return d.fail("failed to read element function index");
2654 }
2655 if (funcIndex >= env->numFuncs()) {
2656 return d.fail("table element out of range");
2657 }
2658 #ifdef WASM_PRIVATE_REFTYPES
2659 if (exportedTable &&
2660 !FuncTypeIsJSCompatible(d, *env->funcs[funcIndex].type)) {
2661 return false;
2662 }
2663 #endif
2664 }
2665
2666 if (payload == ElemSegmentPayload::ElemExpression) {
2667 OpBytes end;
2668 if (!d.readOp(&end) || end.b0 != uint16_t(Op::End)) {
2669 return d.fail("failed to read end of initializer expression");
2670 }
2671 }
2672
2673 seg->elemFuncIndices.infallibleAppend(funcIndex);
2674 if (funcIndex != NullFuncIndex && !isAsmJS) {
2675 env->declareFuncExported(funcIndex, /* eager */ false,
2676 /* canRefFunc */ true);
2677 }
2678 }
2679
2680 env->elemSegments.infallibleAppend(std::move(seg));
2681 }
2682
2683 return d.finishSection(*range, "elem");
2684 }
2685
DecodeDataCountSection(Decoder & d,ModuleEnvironment * env)2686 static bool DecodeDataCountSection(Decoder& d, ModuleEnvironment* env) {
2687 MaybeSectionRange range;
2688 if (!d.startSection(SectionId::DataCount, env, &range, "datacount")) {
2689 return false;
2690 }
2691 if (!range) {
2692 return true;
2693 }
2694
2695 uint32_t dataCount;
2696 if (!d.readVarU32(&dataCount)) {
2697 return d.fail("expected data segment count");
2698 }
2699
2700 env->dataCount.emplace(dataCount);
2701
2702 return d.finishSection(*range, "datacount");
2703 }
2704
StartsCodeSection(const uint8_t * begin,const uint8_t * end,SectionRange * codeSection)2705 bool wasm::StartsCodeSection(const uint8_t* begin, const uint8_t* end,
2706 SectionRange* codeSection) {
2707 UniqueChars unused;
2708 Decoder d(begin, end, 0, &unused);
2709
2710 if (!DecodePreamble(d)) {
2711 return false;
2712 }
2713
2714 while (!d.done()) {
2715 uint8_t id;
2716 SectionRange range;
2717 if (!d.readSectionHeader(&id, &range)) {
2718 return false;
2719 }
2720
2721 if (id == uint8_t(SectionId::Code)) {
2722 *codeSection = range;
2723 return true;
2724 }
2725
2726 if (!d.readBytes(range.size)) {
2727 return false;
2728 }
2729 }
2730
2731 return false;
2732 }
2733
DecodeModuleEnvironment(Decoder & d,ModuleEnvironment * env)2734 bool wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env) {
2735 if (!DecodePreamble(d)) {
2736 return false;
2737 }
2738
2739 if (!DecodeTypeSection(d, env)) {
2740 return false;
2741 }
2742
2743 if (!DecodeImportSection(d, env)) {
2744 return false;
2745 }
2746
2747 if (!DecodeFunctionSection(d, env)) {
2748 return false;
2749 }
2750
2751 if (!DecodeTableSection(d, env)) {
2752 return false;
2753 }
2754
2755 if (!DecodeMemorySection(d, env)) {
2756 return false;
2757 }
2758
2759 #ifdef ENABLE_WASM_EXCEPTIONS
2760 if (!DecodeEventSection(d, env)) {
2761 return false;
2762 }
2763 #endif
2764
2765 if (!DecodeGlobalSection(d, env)) {
2766 return false;
2767 }
2768
2769 if (!DecodeExportSection(d, env)) {
2770 return false;
2771 }
2772
2773 if (!DecodeStartSection(d, env)) {
2774 return false;
2775 }
2776
2777 if (!DecodeElemSection(d, env)) {
2778 return false;
2779 }
2780
2781 if (!DecodeDataCountSection(d, env)) {
2782 return false;
2783 }
2784
2785 if (!d.startSection(SectionId::Code, env, &env->codeSection, "code")) {
2786 return false;
2787 }
2788
2789 if (env->codeSection && env->codeSection->size > MaxCodeSectionBytes) {
2790 return d.fail("code section too big");
2791 }
2792
2793 return true;
2794 }
2795
DecodeFunctionBody(Decoder & d,const ModuleEnvironment & env,uint32_t funcIndex)2796 static bool DecodeFunctionBody(Decoder& d, const ModuleEnvironment& env,
2797 uint32_t funcIndex) {
2798 uint32_t bodySize;
2799 if (!d.readVarU32(&bodySize)) {
2800 return d.fail("expected number of function body bytes");
2801 }
2802
2803 if (bodySize > MaxFunctionBytes) {
2804 return d.fail("function body too big");
2805 }
2806
2807 if (d.bytesRemain() < bodySize) {
2808 return d.fail("function body length too big");
2809 }
2810
2811 return ValidateFunctionBody(env, funcIndex, bodySize, d);
2812 }
2813
DecodeCodeSection(Decoder & d,ModuleEnvironment * env)2814 static bool DecodeCodeSection(Decoder& d, ModuleEnvironment* env) {
2815 if (!env->codeSection) {
2816 if (env->numFuncDefs() != 0) {
2817 return d.fail("expected code section");
2818 }
2819 return true;
2820 }
2821
2822 uint32_t numFuncDefs;
2823 if (!d.readVarU32(&numFuncDefs)) {
2824 return d.fail("expected function body count");
2825 }
2826
2827 if (numFuncDefs != env->numFuncDefs()) {
2828 return d.fail(
2829 "function body count does not match function signature count");
2830 }
2831
2832 for (uint32_t funcDefIndex = 0; funcDefIndex < numFuncDefs; funcDefIndex++) {
2833 if (!DecodeFunctionBody(d, *env, env->numFuncImports() + funcDefIndex)) {
2834 return false;
2835 }
2836 }
2837
2838 return d.finishSection(*env->codeSection, "code");
2839 }
2840
DecodeDataSection(Decoder & d,ModuleEnvironment * env)2841 static bool DecodeDataSection(Decoder& d, ModuleEnvironment* env) {
2842 MaybeSectionRange range;
2843 if (!d.startSection(SectionId::Data, env, &range, "data")) {
2844 return false;
2845 }
2846 if (!range) {
2847 if (env->dataCount.isSome() && *env->dataCount > 0) {
2848 return d.fail("number of data segments does not match declared count");
2849 }
2850 return true;
2851 }
2852
2853 uint32_t numSegments;
2854 if (!d.readVarU32(&numSegments)) {
2855 return d.fail("failed to read number of data segments");
2856 }
2857
2858 if (numSegments > MaxDataSegments) {
2859 return d.fail("too many data segments");
2860 }
2861
2862 if (env->dataCount.isSome() && numSegments != *env->dataCount) {
2863 return d.fail("number of data segments does not match declared count");
2864 }
2865
2866 for (uint32_t i = 0; i < numSegments; i++) {
2867 uint32_t initializerKindVal;
2868 if (!d.readVarU32(&initializerKindVal)) {
2869 return d.fail("expected data initializer-kind field");
2870 }
2871
2872 switch (initializerKindVal) {
2873 case uint32_t(DataSegmentKind::Active):
2874 case uint32_t(DataSegmentKind::Passive):
2875 case uint32_t(DataSegmentKind::ActiveWithMemoryIndex):
2876 break;
2877 default:
2878 return d.fail("invalid data initializer-kind field");
2879 }
2880
2881 DataSegmentKind initializerKind = DataSegmentKind(initializerKindVal);
2882
2883 if (initializerKind != DataSegmentKind::Passive && !env->usesMemory()) {
2884 return d.fail("active data segment requires a memory section");
2885 }
2886
2887 uint32_t memIndex = 0;
2888 if (initializerKind == DataSegmentKind::ActiveWithMemoryIndex) {
2889 if (!d.readVarU32(&memIndex)) {
2890 return d.fail("expected memory index");
2891 }
2892 if (memIndex > 0) {
2893 return d.fail("memory index must be zero");
2894 }
2895 }
2896
2897 DataSegmentEnv seg;
2898 if (initializerKind == DataSegmentKind::Active ||
2899 initializerKind == DataSegmentKind::ActiveWithMemoryIndex) {
2900 InitExpr segOffset;
2901 if (!InitExpr::decodeAndValidate(d, env, ValType::I32, &segOffset)) {
2902 return false;
2903 }
2904 seg.offsetIfActive.emplace(std::move(segOffset));
2905 }
2906
2907 if (!d.readVarU32(&seg.length)) {
2908 return d.fail("expected segment size");
2909 }
2910
2911 if (seg.length > MaxDataSegmentLengthPages * PageSize) {
2912 return d.fail("segment size too big");
2913 }
2914
2915 seg.bytecodeOffset = d.currentOffset();
2916
2917 if (!d.readBytes(seg.length)) {
2918 return d.fail("data segment shorter than declared");
2919 }
2920
2921 if (!env->dataSegments.append(std::move(seg))) {
2922 return false;
2923 }
2924 }
2925
2926 return d.finishSection(*range, "data");
2927 }
2928
DecodeModuleNameSubsection(Decoder & d,const CustomSectionEnv & nameSection,ModuleEnvironment * env)2929 static bool DecodeModuleNameSubsection(Decoder& d,
2930 const CustomSectionEnv& nameSection,
2931 ModuleEnvironment* env) {
2932 Maybe<uint32_t> endOffset;
2933 if (!d.startNameSubsection(NameType::Module, &endOffset)) {
2934 return false;
2935 }
2936 if (!endOffset) {
2937 return true;
2938 }
2939
2940 Name moduleName;
2941 if (!d.readVarU32(&moduleName.length)) {
2942 return d.fail("failed to read module name length");
2943 }
2944
2945 MOZ_ASSERT(d.currentOffset() >= nameSection.payloadOffset);
2946 moduleName.offsetInNamePayload =
2947 d.currentOffset() - nameSection.payloadOffset;
2948
2949 const uint8_t* bytes;
2950 if (!d.readBytes(moduleName.length, &bytes)) {
2951 return d.fail("failed to read module name bytes");
2952 }
2953
2954 if (!d.finishNameSubsection(*endOffset)) {
2955 return false;
2956 }
2957
2958 // Only save the module name if the whole subsection validates.
2959 env->moduleName.emplace(moduleName);
2960 return true;
2961 }
2962
DecodeFunctionNameSubsection(Decoder & d,const CustomSectionEnv & nameSection,ModuleEnvironment * env)2963 static bool DecodeFunctionNameSubsection(Decoder& d,
2964 const CustomSectionEnv& nameSection,
2965 ModuleEnvironment* env) {
2966 Maybe<uint32_t> endOffset;
2967 if (!d.startNameSubsection(NameType::Function, &endOffset)) {
2968 return false;
2969 }
2970 if (!endOffset) {
2971 return true;
2972 }
2973
2974 uint32_t nameCount = 0;
2975 if (!d.readVarU32(&nameCount) || nameCount > MaxFuncs) {
2976 return d.fail("bad function name count");
2977 }
2978
2979 NameVector funcNames;
2980
2981 for (uint32_t i = 0; i < nameCount; ++i) {
2982 uint32_t funcIndex = 0;
2983 if (!d.readVarU32(&funcIndex)) {
2984 return d.fail("unable to read function index");
2985 }
2986
2987 // Names must refer to real functions and be given in ascending order.
2988 if (funcIndex >= env->numFuncs() || funcIndex < funcNames.length()) {
2989 return d.fail("invalid function index");
2990 }
2991
2992 Name funcName;
2993 if (!d.readVarU32(&funcName.length) ||
2994 funcName.length > JS::MaxStringLength) {
2995 return d.fail("unable to read function name length");
2996 }
2997
2998 if (!funcName.length) {
2999 continue;
3000 }
3001
3002 if (!funcNames.resize(funcIndex + 1)) {
3003 return false;
3004 }
3005
3006 MOZ_ASSERT(d.currentOffset() >= nameSection.payloadOffset);
3007 funcName.offsetInNamePayload =
3008 d.currentOffset() - nameSection.payloadOffset;
3009
3010 if (!d.readBytes(funcName.length)) {
3011 return d.fail("unable to read function name bytes");
3012 }
3013
3014 funcNames[funcIndex] = funcName;
3015 }
3016
3017 if (!d.finishNameSubsection(*endOffset)) {
3018 return false;
3019 }
3020
3021 // To encourage fully valid function names subsections; only save names if
3022 // the entire subsection decoded correctly.
3023 env->funcNames = std::move(funcNames);
3024 return true;
3025 }
3026
DecodeNameSection(Decoder & d,ModuleEnvironment * env)3027 static bool DecodeNameSection(Decoder& d, ModuleEnvironment* env) {
3028 MaybeSectionRange range;
3029 if (!d.startCustomSection(NameSectionName, env, &range)) {
3030 return false;
3031 }
3032 if (!range) {
3033 return true;
3034 }
3035
3036 env->nameCustomSectionIndex = Some(env->customSections.length() - 1);
3037 const CustomSectionEnv& nameSection = env->customSections.back();
3038
3039 // Once started, custom sections do not report validation errors.
3040
3041 if (!DecodeModuleNameSubsection(d, nameSection, env)) {
3042 goto finish;
3043 }
3044
3045 if (!DecodeFunctionNameSubsection(d, nameSection, env)) {
3046 goto finish;
3047 }
3048
3049 while (d.currentOffset() < range->end()) {
3050 if (!d.skipNameSubsection()) {
3051 goto finish;
3052 }
3053 }
3054
3055 finish:
3056 d.finishCustomSection(NameSectionName, *range);
3057 return true;
3058 }
3059
DecodeModuleTail(Decoder & d,ModuleEnvironment * env)3060 bool wasm::DecodeModuleTail(Decoder& d, ModuleEnvironment* env) {
3061 if (!DecodeDataSection(d, env)) {
3062 return false;
3063 }
3064
3065 if (!DecodeNameSection(d, env)) {
3066 return false;
3067 }
3068
3069 while (!d.done()) {
3070 if (!d.skipCustomSection(env)) {
3071 if (d.resilientMode()) {
3072 d.clearError();
3073 return true;
3074 }
3075 return false;
3076 }
3077 }
3078
3079 return true;
3080 }
3081
3082 // Validate algorithm.
3083
Validate(JSContext * cx,const ShareableBytes & bytecode,const FeatureOptions & options,UniqueChars * error)3084 bool wasm::Validate(JSContext* cx, const ShareableBytes& bytecode,
3085 const FeatureOptions& options, UniqueChars* error) {
3086 Decoder d(bytecode.bytes, 0, error);
3087
3088 FeatureArgs features = FeatureArgs::build(cx, options);
3089 ModuleEnvironment env(features);
3090 if (!DecodeModuleEnvironment(d, &env)) {
3091 return false;
3092 }
3093
3094 if (!DecodeCodeSection(d, &env)) {
3095 return false;
3096 }
3097
3098 if (!DecodeModuleTail(d, &env)) {
3099 return false;
3100 }
3101
3102 MOZ_ASSERT(!*error, "unreported error in decoding");
3103 return true;
3104 }
3105