Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
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 :
23 : #include "jsprf.h"
24 :
25 : #include "jit/JitOptions.h"
26 : #include "wasm/WasmBinaryIterator.h"
27 :
28 : using namespace js;
29 : using namespace js::jit;
30 : using namespace js::wasm;
31 :
32 : using mozilla::CheckedInt;
33 :
34 : // Decoder implementation.
35 :
36 : bool
37 0 : Decoder::failf(const char* msg, ...)
38 : {
39 : va_list ap;
40 0 : va_start(ap, msg);
41 0 : UniqueChars str(JS_vsmprintf(msg, ap));
42 0 : va_end(ap);
43 0 : if (!str)
44 0 : return false;
45 :
46 0 : return fail(str.get());
47 : }
48 :
49 : bool
50 0 : Decoder::fail(size_t errorOffset, const char* msg)
51 : {
52 0 : MOZ_ASSERT(error_);
53 0 : UniqueChars strWithOffset(JS_smprintf("at offset %" PRIuSIZE ": %s", errorOffset, msg));
54 0 : if (!strWithOffset)
55 0 : return false;
56 :
57 0 : *error_ = Move(strWithOffset);
58 0 : return false;
59 : }
60 :
61 : bool
62 0 : Decoder::startSection(SectionId id, ModuleEnvironment* env, uint32_t* sectionStart,
63 : uint32_t* sectionSize, const char* sectionName)
64 : {
65 : // Record state at beginning of section to allow rewinding to this point
66 : // if, after skipping through several custom sections, we don't find the
67 : // section 'id'.
68 0 : const uint8_t* const initialCur = cur_;
69 0 : const size_t initialCustomSectionsLength = env->customSections.length();
70 :
71 : // Maintain a pointer to the current section that gets updated as custom
72 : // sections are skipped.
73 0 : const uint8_t* currentSectionStart = cur_;
74 :
75 : // Only start a section with 'id', skipping any custom sections before it.
76 :
77 : uint32_t idValue;
78 0 : if (!readVarU32(&idValue))
79 0 : goto rewind;
80 :
81 0 : while (idValue != uint32_t(id)) {
82 0 : if (idValue != uint32_t(SectionId::Custom))
83 0 : goto rewind;
84 :
85 : // Rewind to the beginning of the current section since this is what
86 : // skipCustomSection() assumes.
87 0 : cur_ = currentSectionStart;
88 0 : if (!skipCustomSection(env))
89 0 : return false;
90 :
91 : // Having successfully skipped a custom section, consider the next
92 : // section.
93 0 : currentSectionStart = cur_;
94 0 : if (!readVarU32(&idValue))
95 0 : goto rewind;
96 : }
97 :
98 : // Found it, now start the section.
99 :
100 0 : if (!readVarU32(sectionSize) || bytesRemain() < *sectionSize)
101 0 : goto fail;
102 :
103 0 : *sectionStart = cur_ - beg_;
104 0 : return true;
105 :
106 : rewind:
107 0 : cur_ = initialCur;
108 0 : env->customSections.shrinkTo(initialCustomSectionsLength);
109 0 : *sectionStart = NotStarted;
110 0 : return true;
111 :
112 : fail:
113 0 : return failf("failed to start %s section", sectionName);
114 : }
115 :
116 : bool
117 0 : Decoder::finishSection(uint32_t sectionStart, uint32_t sectionSize, const char* sectionName)
118 : {
119 0 : if (resilientMode_)
120 0 : return true;
121 0 : if (sectionSize != (cur_ - beg_) - sectionStart)
122 0 : return failf("byte size mismatch in %s section", sectionName);
123 0 : return true;
124 : }
125 :
126 : bool
127 0 : Decoder::startCustomSection(const char* expected, size_t expectedLength, ModuleEnvironment* env,
128 : uint32_t* sectionStart, uint32_t* sectionSize)
129 : {
130 : // Record state at beginning of section to allow rewinding to this point
131 : // if, after skipping through several custom sections, we don't find the
132 : // section 'id'.
133 0 : const uint8_t* const initialCur = cur_;
134 0 : const size_t initialCustomSectionsLength = env->customSections.length();
135 :
136 : while (true) {
137 : // Try to start a custom section. If we can't, rewind to the beginning
138 : // since we may have skipped several custom sections already looking for
139 : // 'expected'.
140 0 : if (!startSection(SectionId::Custom, env, sectionStart, sectionSize, "custom"))
141 0 : return false;
142 0 : if (*sectionStart == NotStarted)
143 0 : goto rewind;
144 :
145 0 : NameInBytecode name;
146 0 : if (!readVarU32(&name.length) || name.length > bytesRemain())
147 0 : goto fail;
148 :
149 0 : name.offset = currentOffset();
150 0 : uint32_t payloadOffset = name.offset + name.length;
151 0 : uint32_t payloadEnd = *sectionStart + *sectionSize;
152 0 : if (payloadOffset > payloadEnd)
153 0 : goto fail;
154 :
155 : // Now that we have a valid custom section, record its offsets in the
156 : // metadata which can be queried by the user via Module.customSections.
157 : // Note: after an entry is appended, it may be popped if this loop or
158 : // the loop in startSection needs to rewind.
159 0 : if (!env->customSections.emplaceBack(name, payloadOffset, payloadEnd - payloadOffset))
160 0 : return false;
161 :
162 : // If this is the expected custom section, we're done.
163 0 : if (!expected || (expectedLength == name.length && !memcmp(cur_, expected, name.length))) {
164 0 : cur_ += name.length;
165 0 : return true;
166 : }
167 :
168 : // Otherwise, blindly skip the custom section and keep looking.
169 0 : finishCustomSection(*sectionStart, *sectionSize);
170 0 : }
171 : MOZ_CRASH("unreachable");
172 :
173 : rewind:
174 0 : cur_ = initialCur;
175 0 : env->customSections.shrinkTo(initialCustomSectionsLength);
176 0 : return true;
177 :
178 : fail:
179 0 : return fail("failed to start custom section");
180 : }
181 :
182 : void
183 0 : Decoder::finishCustomSection(uint32_t sectionStart, uint32_t sectionSize)
184 : {
185 0 : MOZ_ASSERT(cur_ >= beg_);
186 0 : MOZ_ASSERT(cur_ <= end_);
187 0 : cur_ = (beg_ + sectionStart) + sectionSize;
188 0 : MOZ_ASSERT(cur_ <= end_);
189 0 : clearError();
190 0 : }
191 :
192 : bool
193 0 : Decoder::skipCustomSection(ModuleEnvironment* env)
194 : {
195 : uint32_t sectionStart, sectionSize;
196 0 : if (!startCustomSection(nullptr, 0, env, §ionStart, §ionSize))
197 0 : return false;
198 0 : if (sectionStart == NotStarted)
199 0 : return fail("expected custom section");
200 :
201 0 : finishCustomSection(sectionStart, sectionSize);
202 0 : return true;
203 : }
204 :
205 : bool
206 0 : Decoder::startNameSubsection(NameType nameType, uint32_t* endOffset)
207 : {
208 0 : const uint8_t* initialPosition = cur_;
209 :
210 : uint32_t nameTypeValue;
211 0 : if (!readVarU32(&nameTypeValue))
212 0 : return false;
213 :
214 0 : if (nameTypeValue != uint8_t(nameType)) {
215 0 : cur_ = initialPosition;
216 0 : *endOffset = NotStarted;
217 0 : return true;
218 : }
219 :
220 : uint32_t payloadLength;
221 0 : if (!readVarU32(&payloadLength) || payloadLength > bytesRemain())
222 0 : return false;
223 :
224 0 : *endOffset = (cur_ - beg_) + payloadLength;
225 0 : return true;
226 : }
227 :
228 : bool
229 0 : Decoder::finishNameSubsection(uint32_t endOffset)
230 : {
231 0 : MOZ_ASSERT(endOffset != NotStarted);
232 0 : return endOffset == uint32_t(cur_ - beg_);
233 : }
234 :
235 : // Misc helpers.
236 :
237 : bool
238 0 : wasm::EncodeLocalEntries(Encoder& e, const ValTypeVector& locals)
239 : {
240 0 : uint32_t numLocalEntries = 0;
241 0 : ValType prev = ValType(TypeCode::Limit);
242 0 : for (ValType t : locals) {
243 0 : if (t != prev) {
244 0 : numLocalEntries++;
245 0 : prev = t;
246 : }
247 : }
248 :
249 0 : if (!e.writeVarU32(numLocalEntries))
250 0 : return false;
251 :
252 0 : if (numLocalEntries) {
253 0 : prev = locals[0];
254 0 : uint32_t count = 1;
255 0 : for (uint32_t i = 1; i < locals.length(); i++, count++) {
256 0 : if (prev != locals[i]) {
257 0 : if (!e.writeVarU32(count))
258 0 : return false;
259 0 : if (!e.writeValType(prev))
260 0 : return false;
261 0 : prev = locals[i];
262 0 : count = 0;
263 : }
264 : }
265 0 : if (!e.writeVarU32(count))
266 0 : return false;
267 0 : if (!e.writeValType(prev))
268 0 : return false;
269 : }
270 :
271 0 : return true;
272 : }
273 :
274 : static bool
275 0 : DecodeValType(Decoder& d, ModuleKind kind, ValType* type)
276 : {
277 : uint8_t unchecked;
278 0 : if (!d.readValType(&unchecked))
279 0 : return false;
280 :
281 0 : switch (unchecked) {
282 : case uint8_t(ValType::I32):
283 : case uint8_t(ValType::F32):
284 : case uint8_t(ValType::F64):
285 : case uint8_t(ValType::I64):
286 0 : *type = ValType(unchecked);
287 0 : return true;
288 : case uint8_t(ValType::I8x16):
289 : case uint8_t(ValType::I16x8):
290 : case uint8_t(ValType::I32x4):
291 : case uint8_t(ValType::F32x4):
292 : case uint8_t(ValType::B8x16):
293 : case uint8_t(ValType::B16x8):
294 : case uint8_t(ValType::B32x4):
295 0 : if (kind != ModuleKind::AsmJS)
296 0 : return d.fail("bad type");
297 0 : *type = ValType(unchecked);
298 0 : return true;
299 : default:
300 0 : break;
301 : }
302 0 : return d.fail("bad type");
303 : }
304 :
305 : bool
306 0 : wasm::DecodeLocalEntries(Decoder& d, ModuleKind kind, ValTypeVector* locals)
307 : {
308 : uint32_t numLocalEntries;
309 0 : if (!d.readVarU32(&numLocalEntries))
310 0 : return d.fail("failed to read number of local entries");
311 :
312 0 : for (uint32_t i = 0; i < numLocalEntries; i++) {
313 : uint32_t count;
314 0 : if (!d.readVarU32(&count))
315 0 : return d.fail("failed to read local entry count");
316 :
317 0 : if (MaxLocals - locals->length() < count)
318 0 : return d.fail("too many locals");
319 :
320 : ValType type;
321 0 : if (!DecodeValType(d, kind, &type))
322 0 : return false;
323 :
324 0 : if (!locals->appendN(type, count))
325 0 : return false;
326 : }
327 :
328 0 : return true;
329 : }
330 :
331 : // Function body validation.
332 :
333 0 : struct ValidatingPolicy
334 : {
335 : typedef Nothing Value;
336 : typedef Nothing ControlItem;
337 : };
338 :
339 : typedef OpIter<ValidatingPolicy> ValidatingOpIter;
340 :
341 : static bool
342 0 : DecodeFunctionBodyExprs(const ModuleEnvironment& env, const Sig& sig, const ValTypeVector& locals,
343 : const uint8_t* bodyEnd, Decoder* d)
344 : {
345 0 : ValidatingOpIter iter(env, *d);
346 :
347 0 : if (!iter.readFunctionStart(sig.ret()))
348 0 : return false;
349 :
350 : #define CHECK(c) if (!(c)) return false; break
351 :
352 : while (true) {
353 0 : OpBytes op;
354 0 : if (!iter.readOp(&op))
355 0 : return false;
356 :
357 : Nothing nothing;
358 :
359 0 : switch (op.b0) {
360 : case uint16_t(Op::End): {
361 : LabelKind unusedKind;
362 : ExprType unusedType;
363 0 : if (!iter.readEnd(&unusedKind, &unusedType, ¬hing))
364 0 : return false;
365 0 : iter.popEnd();
366 0 : if (iter.controlStackEmpty())
367 0 : return iter.readFunctionEnd(bodyEnd);
368 0 : break;
369 : }
370 : case uint16_t(Op::Nop):
371 0 : CHECK(iter.readNop());
372 : case uint16_t(Op::Drop):
373 0 : CHECK(iter.readDrop());
374 : case uint16_t(Op::Call): {
375 : uint32_t unusedIndex;
376 0 : ValidatingOpIter::ValueVector unusedArgs;
377 0 : CHECK(iter.readCall(&unusedIndex, &unusedArgs));
378 : }
379 : case uint16_t(Op::CallIndirect): {
380 : uint32_t unusedIndex;
381 0 : ValidatingOpIter::ValueVector unusedArgs;
382 0 : CHECK(iter.readCallIndirect(&unusedIndex, ¬hing, &unusedArgs));
383 : }
384 : case uint16_t(Op::I32Const): {
385 : int32_t unused;
386 0 : CHECK(iter.readI32Const(&unused));
387 : }
388 : case uint16_t(Op::I64Const): {
389 : int64_t unused;
390 0 : CHECK(iter.readI64Const(&unused));
391 : }
392 : case uint16_t(Op::F32Const): {
393 : float unused;
394 0 : CHECK(iter.readF32Const(&unused));
395 : }
396 : case uint16_t(Op::F64Const): {
397 : double unused;
398 0 : CHECK(iter.readF64Const(&unused));
399 : }
400 : case uint16_t(Op::GetLocal): {
401 : uint32_t unused;
402 0 : CHECK(iter.readGetLocal(locals, &unused));
403 : }
404 : case uint16_t(Op::SetLocal): {
405 : uint32_t unused;
406 0 : CHECK(iter.readSetLocal(locals, &unused, ¬hing));
407 : }
408 : case uint16_t(Op::TeeLocal): {
409 : uint32_t unused;
410 0 : CHECK(iter.readTeeLocal(locals, &unused, ¬hing));
411 : }
412 : case uint16_t(Op::GetGlobal): {
413 : uint32_t unused;
414 0 : CHECK(iter.readGetGlobal(&unused));
415 : }
416 : case uint16_t(Op::SetGlobal): {
417 : uint32_t unused;
418 0 : CHECK(iter.readSetGlobal(&unused, ¬hing));
419 : }
420 : case uint16_t(Op::Select): {
421 : StackType unused;
422 0 : CHECK(iter.readSelect(&unused, ¬hing, ¬hing, ¬hing));
423 : }
424 : case uint16_t(Op::Block):
425 0 : CHECK(iter.readBlock());
426 : case uint16_t(Op::Loop):
427 0 : CHECK(iter.readLoop());
428 : case uint16_t(Op::If):
429 0 : CHECK(iter.readIf(¬hing));
430 : case uint16_t(Op::Else): {
431 : ExprType type;
432 0 : CHECK(iter.readElse(&type, ¬hing));
433 : }
434 : case uint16_t(Op::I32Clz):
435 : case uint16_t(Op::I32Ctz):
436 : case uint16_t(Op::I32Popcnt):
437 0 : CHECK(iter.readUnary(ValType::I32, ¬hing));
438 : case uint16_t(Op::I64Clz):
439 : case uint16_t(Op::I64Ctz):
440 : case uint16_t(Op::I64Popcnt):
441 0 : CHECK(iter.readUnary(ValType::I64, ¬hing));
442 : case uint16_t(Op::F32Abs):
443 : case uint16_t(Op::F32Neg):
444 : case uint16_t(Op::F32Ceil):
445 : case uint16_t(Op::F32Floor):
446 : case uint16_t(Op::F32Sqrt):
447 : case uint16_t(Op::F32Trunc):
448 : case uint16_t(Op::F32Nearest):
449 0 : CHECK(iter.readUnary(ValType::F32, ¬hing));
450 : case uint16_t(Op::F64Abs):
451 : case uint16_t(Op::F64Neg):
452 : case uint16_t(Op::F64Ceil):
453 : case uint16_t(Op::F64Floor):
454 : case uint16_t(Op::F64Sqrt):
455 : case uint16_t(Op::F64Trunc):
456 : case uint16_t(Op::F64Nearest):
457 0 : CHECK(iter.readUnary(ValType::F64, ¬hing));
458 : case uint16_t(Op::I32Add):
459 : case uint16_t(Op::I32Sub):
460 : case uint16_t(Op::I32Mul):
461 : case uint16_t(Op::I32DivS):
462 : case uint16_t(Op::I32DivU):
463 : case uint16_t(Op::I32RemS):
464 : case uint16_t(Op::I32RemU):
465 : case uint16_t(Op::I32And):
466 : case uint16_t(Op::I32Or):
467 : case uint16_t(Op::I32Xor):
468 : case uint16_t(Op::I32Shl):
469 : case uint16_t(Op::I32ShrS):
470 : case uint16_t(Op::I32ShrU):
471 : case uint16_t(Op::I32Rotl):
472 : case uint16_t(Op::I32Rotr):
473 0 : CHECK(iter.readBinary(ValType::I32, ¬hing, ¬hing));
474 : case uint16_t(Op::I64Add):
475 : case uint16_t(Op::I64Sub):
476 : case uint16_t(Op::I64Mul):
477 : case uint16_t(Op::I64DivS):
478 : case uint16_t(Op::I64DivU):
479 : case uint16_t(Op::I64RemS):
480 : case uint16_t(Op::I64RemU):
481 : case uint16_t(Op::I64And):
482 : case uint16_t(Op::I64Or):
483 : case uint16_t(Op::I64Xor):
484 : case uint16_t(Op::I64Shl):
485 : case uint16_t(Op::I64ShrS):
486 : case uint16_t(Op::I64ShrU):
487 : case uint16_t(Op::I64Rotl):
488 : case uint16_t(Op::I64Rotr):
489 0 : CHECK(iter.readBinary(ValType::I64, ¬hing, ¬hing));
490 : case uint16_t(Op::F32Add):
491 : case uint16_t(Op::F32Sub):
492 : case uint16_t(Op::F32Mul):
493 : case uint16_t(Op::F32Div):
494 : case uint16_t(Op::F32Min):
495 : case uint16_t(Op::F32Max):
496 : case uint16_t(Op::F32CopySign):
497 0 : CHECK(iter.readBinary(ValType::F32, ¬hing, ¬hing));
498 : case uint16_t(Op::F64Add):
499 : case uint16_t(Op::F64Sub):
500 : case uint16_t(Op::F64Mul):
501 : case uint16_t(Op::F64Div):
502 : case uint16_t(Op::F64Min):
503 : case uint16_t(Op::F64Max):
504 : case uint16_t(Op::F64CopySign):
505 0 : CHECK(iter.readBinary(ValType::F64, ¬hing, ¬hing));
506 : case uint16_t(Op::I32Eq):
507 : case uint16_t(Op::I32Ne):
508 : case uint16_t(Op::I32LtS):
509 : case uint16_t(Op::I32LtU):
510 : case uint16_t(Op::I32LeS):
511 : case uint16_t(Op::I32LeU):
512 : case uint16_t(Op::I32GtS):
513 : case uint16_t(Op::I32GtU):
514 : case uint16_t(Op::I32GeS):
515 : case uint16_t(Op::I32GeU):
516 0 : CHECK(iter.readComparison(ValType::I32, ¬hing, ¬hing));
517 : case uint16_t(Op::I64Eq):
518 : case uint16_t(Op::I64Ne):
519 : case uint16_t(Op::I64LtS):
520 : case uint16_t(Op::I64LtU):
521 : case uint16_t(Op::I64LeS):
522 : case uint16_t(Op::I64LeU):
523 : case uint16_t(Op::I64GtS):
524 : case uint16_t(Op::I64GtU):
525 : case uint16_t(Op::I64GeS):
526 : case uint16_t(Op::I64GeU):
527 0 : CHECK(iter.readComparison(ValType::I64, ¬hing, ¬hing));
528 : case uint16_t(Op::F32Eq):
529 : case uint16_t(Op::F32Ne):
530 : case uint16_t(Op::F32Lt):
531 : case uint16_t(Op::F32Le):
532 : case uint16_t(Op::F32Gt):
533 : case uint16_t(Op::F32Ge):
534 0 : CHECK(iter.readComparison(ValType::F32, ¬hing, ¬hing));
535 : case uint16_t(Op::F64Eq):
536 : case uint16_t(Op::F64Ne):
537 : case uint16_t(Op::F64Lt):
538 : case uint16_t(Op::F64Le):
539 : case uint16_t(Op::F64Gt):
540 : case uint16_t(Op::F64Ge):
541 0 : CHECK(iter.readComparison(ValType::F64, ¬hing, ¬hing));
542 : case uint16_t(Op::I32Eqz):
543 0 : CHECK(iter.readConversion(ValType::I32, ValType::I32, ¬hing));
544 : case uint16_t(Op::I64Eqz):
545 : case uint16_t(Op::I32WrapI64):
546 0 : CHECK(iter.readConversion(ValType::I64, ValType::I32, ¬hing));
547 : case uint16_t(Op::I32TruncSF32):
548 : case uint16_t(Op::I32TruncUF32):
549 : case uint16_t(Op::I32ReinterpretF32):
550 0 : CHECK(iter.readConversion(ValType::F32, ValType::I32, ¬hing));
551 : case uint16_t(Op::I32TruncSF64):
552 : case uint16_t(Op::I32TruncUF64):
553 0 : CHECK(iter.readConversion(ValType::F64, ValType::I32, ¬hing));
554 : case uint16_t(Op::I64ExtendSI32):
555 : case uint16_t(Op::I64ExtendUI32):
556 0 : CHECK(iter.readConversion(ValType::I32, ValType::I64, ¬hing));
557 : case uint16_t(Op::I64TruncSF32):
558 : case uint16_t(Op::I64TruncUF32):
559 0 : CHECK(iter.readConversion(ValType::F32, ValType::I64, ¬hing));
560 : case uint16_t(Op::I64TruncSF64):
561 : case uint16_t(Op::I64TruncUF64):
562 : case uint16_t(Op::I64ReinterpretF64):
563 0 : CHECK(iter.readConversion(ValType::F64, ValType::I64, ¬hing));
564 : case uint16_t(Op::F32ConvertSI32):
565 : case uint16_t(Op::F32ConvertUI32):
566 : case uint16_t(Op::F32ReinterpretI32):
567 0 : CHECK(iter.readConversion(ValType::I32, ValType::F32, ¬hing));
568 : case uint16_t(Op::F32ConvertSI64):
569 : case uint16_t(Op::F32ConvertUI64):
570 0 : CHECK(iter.readConversion(ValType::I64, ValType::F32, ¬hing));
571 : case uint16_t(Op::F32DemoteF64):
572 0 : CHECK(iter.readConversion(ValType::F64, ValType::F32, ¬hing));
573 : case uint16_t(Op::F64ConvertSI32):
574 : case uint16_t(Op::F64ConvertUI32):
575 0 : CHECK(iter.readConversion(ValType::I32, ValType::F64, ¬hing));
576 : case uint16_t(Op::F64ConvertSI64):
577 : case uint16_t(Op::F64ConvertUI64):
578 : case uint16_t(Op::F64ReinterpretI64):
579 0 : CHECK(iter.readConversion(ValType::I64, ValType::F64, ¬hing));
580 : case uint16_t(Op::F64PromoteF32):
581 0 : CHECK(iter.readConversion(ValType::F32, ValType::F64, ¬hing));
582 : case uint16_t(Op::I32Load8S):
583 : case uint16_t(Op::I32Load8U): {
584 0 : LinearMemoryAddress<Nothing> addr;
585 0 : CHECK(iter.readLoad(ValType::I32, 1, &addr));
586 : }
587 : case uint16_t(Op::I32Load16S):
588 : case uint16_t(Op::I32Load16U): {
589 0 : LinearMemoryAddress<Nothing> addr;
590 0 : CHECK(iter.readLoad(ValType::I32, 2, &addr));
591 : }
592 : case uint16_t(Op::I32Load): {
593 0 : LinearMemoryAddress<Nothing> addr;
594 0 : CHECK(iter.readLoad(ValType::I32, 4, &addr));
595 : }
596 : case uint16_t(Op::I64Load8S):
597 : case uint16_t(Op::I64Load8U): {
598 0 : LinearMemoryAddress<Nothing> addr;
599 0 : CHECK(iter.readLoad(ValType::I64, 1, &addr));
600 : }
601 : case uint16_t(Op::I64Load16S):
602 : case uint16_t(Op::I64Load16U): {
603 0 : LinearMemoryAddress<Nothing> addr;
604 0 : CHECK(iter.readLoad(ValType::I64, 2, &addr));
605 : }
606 : case uint16_t(Op::I64Load32S):
607 : case uint16_t(Op::I64Load32U): {
608 0 : LinearMemoryAddress<Nothing> addr;
609 0 : CHECK(iter.readLoad(ValType::I64, 4, &addr));
610 : }
611 : case uint16_t(Op::I64Load): {
612 0 : LinearMemoryAddress<Nothing> addr;
613 0 : CHECK(iter.readLoad(ValType::I64, 8, &addr));
614 : }
615 : case uint16_t(Op::F32Load): {
616 0 : LinearMemoryAddress<Nothing> addr;
617 0 : CHECK(iter.readLoad(ValType::F32, 4, &addr));
618 : }
619 : case uint16_t(Op::F64Load): {
620 0 : LinearMemoryAddress<Nothing> addr;
621 0 : CHECK(iter.readLoad(ValType::F64, 8, &addr));
622 : }
623 : case uint16_t(Op::I32Store8): {
624 0 : LinearMemoryAddress<Nothing> addr;
625 0 : CHECK(iter.readStore(ValType::I32, 1, &addr, ¬hing));
626 : }
627 : case uint16_t(Op::I32Store16): {
628 0 : LinearMemoryAddress<Nothing> addr;
629 0 : CHECK(iter.readStore(ValType::I32, 2, &addr, ¬hing));
630 : }
631 : case uint16_t(Op::I32Store): {
632 0 : LinearMemoryAddress<Nothing> addr;
633 0 : CHECK(iter.readStore(ValType::I32, 4, &addr, ¬hing));
634 : }
635 : case uint16_t(Op::I64Store8): {
636 0 : LinearMemoryAddress<Nothing> addr;
637 0 : CHECK(iter.readStore(ValType::I64, 1, &addr, ¬hing));
638 : }
639 : case uint16_t(Op::I64Store16): {
640 0 : LinearMemoryAddress<Nothing> addr;
641 0 : CHECK(iter.readStore(ValType::I64, 2, &addr, ¬hing));
642 : }
643 : case uint16_t(Op::I64Store32): {
644 0 : LinearMemoryAddress<Nothing> addr;
645 0 : CHECK(iter.readStore(ValType::I64, 4, &addr, ¬hing));
646 : }
647 : case uint16_t(Op::I64Store): {
648 0 : LinearMemoryAddress<Nothing> addr;
649 0 : CHECK(iter.readStore(ValType::I64, 8, &addr, ¬hing));
650 : }
651 : case uint16_t(Op::F32Store): {
652 0 : LinearMemoryAddress<Nothing> addr;
653 0 : CHECK(iter.readStore(ValType::F32, 4, &addr, ¬hing));
654 : }
655 : case uint16_t(Op::F64Store): {
656 0 : LinearMemoryAddress<Nothing> addr;
657 0 : CHECK(iter.readStore(ValType::F64, 8, &addr, ¬hing));
658 : }
659 : case uint16_t(Op::GrowMemory):
660 0 : CHECK(iter.readGrowMemory(¬hing));
661 : case uint16_t(Op::CurrentMemory):
662 0 : CHECK(iter.readCurrentMemory());
663 : case uint16_t(Op::Br): {
664 : uint32_t unusedDepth;
665 : ExprType unusedType;
666 0 : CHECK(iter.readBr(&unusedDepth, &unusedType, ¬hing));
667 : }
668 : case uint16_t(Op::BrIf): {
669 : uint32_t unusedDepth;
670 : ExprType unusedType;
671 0 : CHECK(iter.readBrIf(&unusedDepth, &unusedType, ¬hing, ¬hing));
672 : }
673 : case uint16_t(Op::BrTable): {
674 0 : Uint32Vector unusedDepths;
675 : uint32_t unusedDefault;
676 : ExprType unusedType;
677 0 : CHECK(iter.readBrTable(&unusedDepths, &unusedDefault, &unusedType, ¬hing, ¬hing));
678 : }
679 : case uint16_t(Op::Return):
680 0 : CHECK(iter.readReturn(¬hing));
681 : case uint16_t(Op::Unreachable):
682 0 : CHECK(iter.readUnreachable());
683 : default:
684 0 : return iter.unrecognizedOpcode(&op);
685 : }
686 0 : }
687 :
688 : MOZ_CRASH("unreachable");
689 :
690 : #undef CHECK
691 : }
692 :
693 : bool
694 0 : wasm::ValidateFunctionBody(const ModuleEnvironment& env, uint32_t funcIndex, uint32_t bodySize,
695 : Decoder& d)
696 : {
697 0 : const Sig& sig = *env.funcSigs[funcIndex];
698 :
699 0 : ValTypeVector locals;
700 0 : if (!locals.appendAll(sig.args()))
701 0 : return false;
702 :
703 0 : const uint8_t* bodyBegin = d.currentPosition();
704 :
705 0 : if (!DecodeLocalEntries(d, ModuleKind::Wasm, &locals))
706 0 : return false;
707 :
708 0 : if (!DecodeFunctionBodyExprs(env, sig, locals, bodyBegin + bodySize, &d))
709 0 : return false;
710 :
711 0 : return true;
712 : }
713 :
714 : // Section macros.
715 :
716 : static bool
717 0 : DecodePreamble(Decoder& d)
718 : {
719 0 : if (d.bytesRemain() > MaxModuleBytes)
720 0 : return d.fail("module too big");
721 :
722 : uint32_t u32;
723 0 : if (!d.readFixedU32(&u32) || u32 != MagicNumber)
724 0 : return d.fail("failed to match magic number");
725 :
726 0 : if (!d.readFixedU32(&u32) || u32 != EncodingVersion) {
727 0 : return d.failf("binary version 0x%" PRIx32 " does not match expected version 0x%" PRIx32,
728 0 : u32, EncodingVersion);
729 : }
730 :
731 0 : return true;
732 : }
733 :
734 : static bool
735 0 : DecodeTypeSection(Decoder& d, ModuleEnvironment* env)
736 : {
737 : uint32_t sectionStart, sectionSize;
738 0 : if (!d.startSection(SectionId::Type, env, §ionStart, §ionSize, "type"))
739 0 : return false;
740 0 : if (sectionStart == Decoder::NotStarted)
741 0 : return true;
742 :
743 : uint32_t numSigs;
744 0 : if (!d.readVarU32(&numSigs))
745 0 : return d.fail("expected number of signatures");
746 :
747 0 : if (numSigs > MaxTypes)
748 0 : return d.fail("too many signatures");
749 :
750 0 : if (!env->sigs.resize(numSigs))
751 0 : return false;
752 :
753 0 : for (uint32_t sigIndex = 0; sigIndex < numSigs; sigIndex++) {
754 : uint32_t form;
755 0 : if (!d.readVarU32(&form) || form != uint32_t(TypeCode::Func))
756 0 : return d.fail("expected function form");
757 :
758 : uint32_t numArgs;
759 0 : if (!d.readVarU32(&numArgs))
760 0 : return d.fail("bad number of function args");
761 :
762 0 : if (numArgs > MaxParams)
763 0 : return d.fail("too many arguments in signature");
764 :
765 0 : ValTypeVector args;
766 0 : if (!args.resize(numArgs))
767 0 : return false;
768 :
769 0 : for (uint32_t i = 0; i < numArgs; i++) {
770 0 : if (!DecodeValType(d, ModuleKind::Wasm, &args[i]))
771 0 : return false;
772 : }
773 :
774 : uint32_t numRets;
775 0 : if (!d.readVarU32(&numRets))
776 0 : return d.fail("bad number of function returns");
777 :
778 0 : if (numRets > 1)
779 0 : return d.fail("too many returns in signature");
780 :
781 0 : ExprType result = ExprType::Void;
782 :
783 0 : if (numRets == 1) {
784 : ValType type;
785 0 : if (!DecodeValType(d, ModuleKind::Wasm, &type))
786 0 : return false;
787 :
788 0 : result = ToExprType(type);
789 : }
790 :
791 0 : env->sigs[sigIndex] = Sig(Move(args), result);
792 : }
793 :
794 0 : if (!d.finishSection(sectionStart, sectionSize, "type"))
795 0 : return false;
796 :
797 0 : return true;
798 : }
799 :
800 : static UniqueChars
801 0 : DecodeName(Decoder& d)
802 : {
803 : uint32_t numBytes;
804 0 : if (!d.readVarU32(&numBytes))
805 0 : return nullptr;
806 :
807 0 : if (numBytes > MaxStringBytes)
808 0 : return nullptr;
809 :
810 : const uint8_t* bytes;
811 0 : if (!d.readBytes(numBytes, &bytes))
812 0 : return nullptr;
813 :
814 0 : UniqueChars name(js_pod_malloc<char>(numBytes + 1));
815 0 : if (!name)
816 0 : return nullptr;
817 :
818 0 : memcpy(name.get(), bytes, numBytes);
819 0 : name[numBytes] = '\0';
820 :
821 0 : return name;
822 : }
823 :
824 : static bool
825 0 : DecodeSignatureIndex(Decoder& d, const SigWithIdVector& sigs, uint32_t* sigIndex)
826 : {
827 0 : if (!d.readVarU32(sigIndex))
828 0 : return d.fail("expected signature index");
829 :
830 0 : if (*sigIndex >= sigs.length())
831 0 : return d.fail("signature index out of range");
832 :
833 0 : return true;
834 : }
835 :
836 : static bool
837 0 : DecodeLimits(Decoder& d, Limits* limits)
838 : {
839 : uint32_t flags;
840 0 : if (!d.readVarU32(&flags))
841 0 : return d.fail("expected flags");
842 :
843 0 : if (flags & ~uint32_t(0x1))
844 0 : return d.failf("unexpected bits set in flags: %" PRIu32, (flags & ~uint32_t(0x1)));
845 :
846 0 : if (!d.readVarU32(&limits->initial))
847 0 : return d.fail("expected initial length");
848 :
849 0 : if (flags & 0x1) {
850 : uint32_t maximum;
851 0 : if (!d.readVarU32(&maximum))
852 0 : return d.fail("expected maximum length");
853 :
854 0 : if (limits->initial > maximum) {
855 0 : return d.failf("memory size minimum must not be greater than maximum; "
856 : "maximum length %" PRIu32 " is less than initial length %" PRIu32,
857 0 : maximum, limits->initial);
858 : }
859 :
860 0 : limits->maximum.emplace(maximum);
861 : }
862 :
863 0 : return true;
864 : }
865 :
866 : static bool
867 0 : DecodeTableLimits(Decoder& d, TableDescVector* tables)
868 : {
869 : uint32_t elementType;
870 0 : if (!d.readVarU32(&elementType))
871 0 : return d.fail("expected table element type");
872 :
873 0 : if (elementType != uint32_t(TypeCode::AnyFunc))
874 0 : return d.fail("expected 'anyfunc' element type");
875 :
876 0 : Limits limits;
877 0 : if (!DecodeLimits(d, &limits))
878 0 : return false;
879 :
880 0 : if (limits.initial > MaxTableInitialLength)
881 0 : return d.fail("too many table elements");
882 :
883 0 : if (tables->length())
884 0 : return d.fail("already have default table");
885 :
886 0 : return tables->emplaceBack(TableKind::AnyFunction, limits);
887 : }
888 :
889 : static bool
890 0 : GlobalIsJSCompatible(Decoder& d, ValType type, bool isMutable)
891 : {
892 0 : switch (type) {
893 : case ValType::I32:
894 : case ValType::F32:
895 : case ValType::F64:
896 0 : break;
897 : case ValType::I64:
898 0 : if (!jit::JitOptions.wasmTestMode)
899 0 : return d.fail("can't import/export an Int64 global to JS");
900 0 : break;
901 : default:
902 0 : return d.fail("unexpected variable type in global import/export");
903 : }
904 :
905 0 : if (isMutable)
906 0 : return d.fail("can't import/export mutable globals in the MVP");
907 :
908 0 : return true;
909 : }
910 :
911 : static bool
912 0 : DecodeGlobalType(Decoder& d, ValType* type, bool* isMutable)
913 : {
914 0 : if (!DecodeValType(d, ModuleKind::Wasm, type))
915 0 : return false;
916 :
917 : uint32_t flags;
918 0 : if (!d.readVarU32(&flags))
919 0 : return d.fail("expected global flags");
920 :
921 0 : if (flags & ~uint32_t(GlobalTypeImmediate::AllowedMask))
922 0 : return d.fail("unexpected bits set in global flags");
923 :
924 0 : *isMutable = flags & uint32_t(GlobalTypeImmediate::IsMutable);
925 0 : return true;
926 : }
927 :
928 : static bool
929 0 : DecodeMemoryLimits(Decoder& d, ModuleEnvironment* env)
930 : {
931 0 : if (env->usesMemory())
932 0 : return d.fail("already have default memory");
933 :
934 0 : Limits memory;
935 0 : if (!DecodeLimits(d, &memory))
936 0 : return false;
937 :
938 0 : if (memory.initial > MaxMemoryInitialPages)
939 0 : return d.fail("initial memory size too big");
940 :
941 0 : CheckedInt<uint32_t> initialBytes = memory.initial;
942 0 : initialBytes *= PageSize;
943 0 : MOZ_ASSERT(initialBytes.isValid());
944 0 : memory.initial = initialBytes.value();
945 :
946 0 : if (memory.maximum) {
947 0 : if (*memory.maximum > MaxMemoryMaximumPages)
948 0 : return d.fail("maximum memory size too big");
949 :
950 0 : CheckedInt<uint32_t> maximumBytes = *memory.maximum;
951 0 : maximumBytes *= PageSize;
952 :
953 : // Clamp the maximum memory value to UINT32_MAX; it's not semantically
954 : // visible since growing will fail for values greater than INT32_MAX.
955 0 : memory.maximum = Some(maximumBytes.isValid() ? maximumBytes.value() : UINT32_MAX);
956 : }
957 :
958 0 : env->memoryUsage = MemoryUsage::Unshared;
959 0 : env->minMemoryLength = memory.initial;
960 0 : env->maxMemoryLength = memory.maximum;
961 0 : return true;
962 : }
963 :
964 : static bool
965 0 : DecodeImport(Decoder& d, ModuleEnvironment* env)
966 : {
967 0 : UniqueChars moduleName = DecodeName(d);
968 0 : if (!moduleName)
969 0 : return d.fail("expected valid import module name");
970 :
971 0 : UniqueChars funcName = DecodeName(d);
972 0 : if (!funcName)
973 0 : return d.fail("expected valid import func name");
974 :
975 : uint32_t rawImportKind;
976 0 : if (!d.readVarU32(&rawImportKind))
977 0 : return d.fail("failed to read import kind");
978 :
979 0 : DefinitionKind importKind = DefinitionKind(rawImportKind);
980 :
981 0 : switch (importKind) {
982 : case DefinitionKind::Function: {
983 : uint32_t sigIndex;
984 0 : if (!DecodeSignatureIndex(d, env->sigs, &sigIndex))
985 0 : return false;
986 0 : if (!env->funcSigs.append(&env->sigs[sigIndex]))
987 0 : return false;
988 0 : if (env->funcSigs.length() > MaxFuncs)
989 0 : return d.fail("too many functions");
990 0 : break;
991 : }
992 : case DefinitionKind::Table: {
993 0 : if (!DecodeTableLimits(d, &env->tables))
994 0 : return false;
995 0 : env->tables.back().external = true;
996 0 : break;
997 : }
998 : case DefinitionKind::Memory: {
999 0 : if (!DecodeMemoryLimits(d, env))
1000 0 : return false;
1001 0 : break;
1002 : }
1003 : case DefinitionKind::Global: {
1004 : ValType type;
1005 : bool isMutable;
1006 0 : if (!DecodeGlobalType(d, &type, &isMutable))
1007 0 : return false;
1008 0 : if (!GlobalIsJSCompatible(d, type, isMutable))
1009 0 : return false;
1010 0 : if (!env->globals.append(GlobalDesc(type, isMutable, env->globals.length())))
1011 0 : return false;
1012 0 : if (env->globals.length() > MaxGlobals)
1013 0 : return d.fail("too many globals");
1014 0 : break;
1015 : }
1016 : default:
1017 0 : return d.fail("unsupported import kind");
1018 : }
1019 :
1020 0 : return env->imports.emplaceBack(Move(moduleName), Move(funcName), importKind);
1021 : }
1022 :
1023 : static bool
1024 0 : DecodeImportSection(Decoder& d, ModuleEnvironment* env)
1025 : {
1026 : uint32_t sectionStart, sectionSize;
1027 0 : if (!d.startSection(SectionId::Import, env, §ionStart, §ionSize, "import"))
1028 0 : return false;
1029 0 : if (sectionStart == Decoder::NotStarted)
1030 0 : return true;
1031 :
1032 : uint32_t numImports;
1033 0 : if (!d.readVarU32(&numImports))
1034 0 : return d.fail("failed to read number of imports");
1035 :
1036 0 : if (numImports > MaxImports)
1037 0 : return d.fail("too many imports");
1038 :
1039 0 : for (uint32_t i = 0; i < numImports; i++) {
1040 0 : if (!DecodeImport(d, env))
1041 0 : return false;
1042 : }
1043 :
1044 0 : if (!d.finishSection(sectionStart, sectionSize, "import"))
1045 0 : return false;
1046 :
1047 : // The global data offsets will be filled in by ModuleGenerator::init.
1048 0 : if (!env->funcImportGlobalDataOffsets.resize(env->funcSigs.length()))
1049 0 : return false;
1050 :
1051 0 : return true;
1052 : }
1053 :
1054 : static bool
1055 0 : DecodeFunctionSection(Decoder& d, ModuleEnvironment* env)
1056 : {
1057 : uint32_t sectionStart, sectionSize;
1058 0 : if (!d.startSection(SectionId::Function, env, §ionStart, §ionSize, "function"))
1059 0 : return false;
1060 0 : if (sectionStart == Decoder::NotStarted)
1061 0 : return true;
1062 :
1063 : uint32_t numDefs;
1064 0 : if (!d.readVarU32(&numDefs))
1065 0 : return d.fail("expected number of function definitions");
1066 :
1067 0 : CheckedInt<uint32_t> numFuncs = env->funcSigs.length();
1068 0 : numFuncs += numDefs;
1069 0 : if (!numFuncs.isValid() || numFuncs.value() > MaxFuncs)
1070 0 : return d.fail("too many functions");
1071 :
1072 0 : if (!env->funcSigs.reserve(numFuncs.value()))
1073 0 : return false;
1074 :
1075 0 : for (uint32_t i = 0; i < numDefs; i++) {
1076 : uint32_t sigIndex;
1077 0 : if (!DecodeSignatureIndex(d, env->sigs, &sigIndex))
1078 0 : return false;
1079 0 : env->funcSigs.infallibleAppend(&env->sigs[sigIndex]);
1080 : }
1081 :
1082 0 : if (!d.finishSection(sectionStart, sectionSize, "function"))
1083 0 : return false;
1084 :
1085 0 : return true;
1086 : }
1087 :
1088 : static bool
1089 0 : DecodeTableSection(Decoder& d, ModuleEnvironment* env)
1090 : {
1091 : uint32_t sectionStart, sectionSize;
1092 0 : if (!d.startSection(SectionId::Table, env, §ionStart, §ionSize, "table"))
1093 0 : return false;
1094 0 : if (sectionStart == Decoder::NotStarted)
1095 0 : return true;
1096 :
1097 : uint32_t numTables;
1098 0 : if (!d.readVarU32(&numTables))
1099 0 : return d.fail("failed to read number of tables");
1100 :
1101 0 : if (numTables > 1)
1102 0 : return d.fail("the number of tables must be at most one");
1103 :
1104 0 : for (uint32_t i = 0; i < numTables; ++i) {
1105 0 : if (!DecodeTableLimits(d, &env->tables))
1106 0 : return false;
1107 : }
1108 :
1109 0 : if (!d.finishSection(sectionStart, sectionSize, "table"))
1110 0 : return false;
1111 :
1112 0 : return true;
1113 : }
1114 :
1115 : static bool
1116 0 : DecodeMemorySection(Decoder& d, ModuleEnvironment* env)
1117 : {
1118 : uint32_t sectionStart, sectionSize;
1119 0 : if (!d.startSection(SectionId::Memory, env, §ionStart, §ionSize, "memory"))
1120 0 : return false;
1121 0 : if (sectionStart == Decoder::NotStarted)
1122 0 : return true;
1123 :
1124 : uint32_t numMemories;
1125 0 : if (!d.readVarU32(&numMemories))
1126 0 : return d.fail("failed to read number of memories");
1127 :
1128 0 : if (numMemories > 1)
1129 0 : return d.fail("the number of memories must be at most one");
1130 :
1131 0 : for (uint32_t i = 0; i < numMemories; ++i) {
1132 0 : if (!DecodeMemoryLimits(d, env))
1133 0 : return false;
1134 : }
1135 :
1136 0 : if (!d.finishSection(sectionStart, sectionSize, "memory"))
1137 0 : return false;
1138 :
1139 0 : return true;
1140 : }
1141 :
1142 : static bool
1143 0 : DecodeInitializerExpression(Decoder& d, const GlobalDescVector& globals, ValType expected,
1144 : InitExpr* init)
1145 : {
1146 0 : OpBytes op;
1147 0 : if (!d.readOp(&op))
1148 0 : return d.fail("failed to read initializer type");
1149 :
1150 0 : switch (op.b0) {
1151 : case uint16_t(Op::I32Const): {
1152 : int32_t i32;
1153 0 : if (!d.readVarS32(&i32))
1154 0 : return d.fail("failed to read initializer i32 expression");
1155 0 : *init = InitExpr(Val(uint32_t(i32)));
1156 0 : break;
1157 : }
1158 : case uint16_t(Op::I64Const): {
1159 : int64_t i64;
1160 0 : if (!d.readVarS64(&i64))
1161 0 : return d.fail("failed to read initializer i64 expression");
1162 0 : *init = InitExpr(Val(uint64_t(i64)));
1163 0 : break;
1164 : }
1165 : case uint16_t(Op::F32Const): {
1166 : float f32;
1167 0 : if (!d.readFixedF32(&f32))
1168 0 : return d.fail("failed to read initializer f32 expression");
1169 0 : *init = InitExpr(Val(f32));
1170 0 : break;
1171 : }
1172 : case uint16_t(Op::F64Const): {
1173 : double f64;
1174 0 : if (!d.readFixedF64(&f64))
1175 0 : return d.fail("failed to read initializer f64 expression");
1176 0 : *init = InitExpr(Val(f64));
1177 0 : break;
1178 : }
1179 : case uint16_t(Op::GetGlobal): {
1180 : uint32_t i;
1181 0 : if (!d.readVarU32(&i))
1182 0 : return d.fail("failed to read get_global index in initializer expression");
1183 0 : if (i >= globals.length())
1184 0 : return d.fail("global index out of range in initializer expression");
1185 0 : if (!globals[i].isImport() || globals[i].isMutable())
1186 0 : return d.fail("initializer expression must reference a global immutable import");
1187 0 : *init = InitExpr(i, globals[i].type());
1188 0 : break;
1189 : }
1190 : default: {
1191 0 : return d.fail("unexpected initializer expression");
1192 : }
1193 : }
1194 :
1195 0 : if (expected != init->type())
1196 0 : return d.fail("type mismatch: initializer type and expected type don't match");
1197 :
1198 0 : OpBytes end;
1199 0 : if (!d.readOp(&end) || end.b0 != uint16_t(Op::End))
1200 0 : return d.fail("failed to read end of initializer expression");
1201 :
1202 0 : return true;
1203 : }
1204 :
1205 : static bool
1206 0 : DecodeGlobalSection(Decoder& d, ModuleEnvironment* env)
1207 : {
1208 : uint32_t sectionStart, sectionSize;
1209 0 : if (!d.startSection(SectionId::Global, env, §ionStart, §ionSize, "global"))
1210 0 : return false;
1211 0 : if (sectionStart == Decoder::NotStarted)
1212 0 : return true;
1213 :
1214 : uint32_t numDefs;
1215 0 : if (!d.readVarU32(&numDefs))
1216 0 : return d.fail("expected number of globals");
1217 :
1218 0 : CheckedInt<uint32_t> numGlobals = env->globals.length();
1219 0 : numGlobals += numDefs;
1220 0 : if (!numGlobals.isValid() || numGlobals.value() > MaxGlobals)
1221 0 : return d.fail("too many globals");
1222 :
1223 0 : if (!env->globals.reserve(numGlobals.value()))
1224 0 : return false;
1225 :
1226 0 : for (uint32_t i = 0; i < numDefs; i++) {
1227 : ValType type;
1228 : bool isMutable;
1229 0 : if (!DecodeGlobalType(d, &type, &isMutable))
1230 0 : return false;
1231 :
1232 0 : InitExpr initializer;
1233 0 : if (!DecodeInitializerExpression(d, env->globals, type, &initializer))
1234 0 : return false;
1235 :
1236 0 : env->globals.infallibleAppend(GlobalDesc(initializer, isMutable));
1237 : }
1238 :
1239 0 : if (!d.finishSection(sectionStart, sectionSize, "global"))
1240 0 : return false;
1241 :
1242 0 : return true;
1243 : }
1244 :
1245 : typedef HashSet<const char*, CStringHasher, SystemAllocPolicy> CStringSet;
1246 :
1247 : static UniqueChars
1248 0 : DecodeExportName(Decoder& d, CStringSet* dupSet)
1249 : {
1250 0 : UniqueChars exportName = DecodeName(d);
1251 0 : if (!exportName) {
1252 0 : d.fail("expected valid export name");
1253 0 : return nullptr;
1254 : }
1255 :
1256 0 : CStringSet::AddPtr p = dupSet->lookupForAdd(exportName.get());
1257 0 : if (p) {
1258 0 : d.fail("duplicate export");
1259 0 : return nullptr;
1260 : }
1261 :
1262 0 : if (!dupSet->add(p, exportName.get()))
1263 0 : return nullptr;
1264 :
1265 0 : return Move(exportName);
1266 : }
1267 :
1268 : static bool
1269 0 : DecodeExport(Decoder& d, ModuleEnvironment* env, CStringSet* dupSet)
1270 : {
1271 0 : UniqueChars fieldName = DecodeExportName(d, dupSet);
1272 0 : if (!fieldName)
1273 0 : return false;
1274 :
1275 : uint32_t exportKind;
1276 0 : if (!d.readVarU32(&exportKind))
1277 0 : return d.fail("failed to read export kind");
1278 :
1279 0 : switch (DefinitionKind(exportKind)) {
1280 : case DefinitionKind::Function: {
1281 : uint32_t funcIndex;
1282 0 : if (!d.readVarU32(&funcIndex))
1283 0 : return d.fail("expected function index");
1284 :
1285 0 : if (funcIndex >= env->numFuncs())
1286 0 : return d.fail("exported function index out of bounds");
1287 :
1288 0 : return env->exports.emplaceBack(Move(fieldName), funcIndex, DefinitionKind::Function);
1289 : }
1290 : case DefinitionKind::Table: {
1291 : uint32_t tableIndex;
1292 0 : if (!d.readVarU32(&tableIndex))
1293 0 : return d.fail("expected table index");
1294 :
1295 0 : if (tableIndex >= env->tables.length())
1296 0 : return d.fail("exported table index out of bounds");
1297 :
1298 0 : MOZ_ASSERT(env->tables.length() == 1);
1299 0 : env->tables[0].external = true;
1300 :
1301 0 : return env->exports.emplaceBack(Move(fieldName), DefinitionKind::Table);
1302 : }
1303 : case DefinitionKind::Memory: {
1304 : uint32_t memoryIndex;
1305 0 : if (!d.readVarU32(&memoryIndex))
1306 0 : return d.fail("expected memory index");
1307 :
1308 0 : if (memoryIndex > 0 || !env->usesMemory())
1309 0 : return d.fail("exported memory index out of bounds");
1310 :
1311 0 : return env->exports.emplaceBack(Move(fieldName), DefinitionKind::Memory);
1312 : }
1313 : case DefinitionKind::Global: {
1314 : uint32_t globalIndex;
1315 0 : if (!d.readVarU32(&globalIndex))
1316 0 : return d.fail("expected global index");
1317 :
1318 0 : if (globalIndex >= env->globals.length())
1319 0 : return d.fail("exported global index out of bounds");
1320 :
1321 0 : const GlobalDesc& global = env->globals[globalIndex];
1322 0 : if (!GlobalIsJSCompatible(d, global.type(), global.isMutable()))
1323 0 : return false;
1324 :
1325 0 : return env->exports.emplaceBack(Move(fieldName), globalIndex, DefinitionKind::Global);
1326 : }
1327 : default:
1328 0 : return d.fail("unexpected export kind");
1329 : }
1330 :
1331 : MOZ_CRASH("unreachable");
1332 : }
1333 :
1334 : static bool
1335 0 : DecodeExportSection(Decoder& d, ModuleEnvironment* env)
1336 : {
1337 : uint32_t sectionStart, sectionSize;
1338 0 : if (!d.startSection(SectionId::Export, env, §ionStart, §ionSize, "export"))
1339 0 : return false;
1340 0 : if (sectionStart == Decoder::NotStarted)
1341 0 : return true;
1342 :
1343 0 : CStringSet dupSet;
1344 0 : if (!dupSet.init())
1345 0 : return false;
1346 :
1347 : uint32_t numExports;
1348 0 : if (!d.readVarU32(&numExports))
1349 0 : return d.fail("failed to read number of exports");
1350 :
1351 0 : if (numExports > MaxExports)
1352 0 : return d.fail("too many exports");
1353 :
1354 0 : for (uint32_t i = 0; i < numExports; i++) {
1355 0 : if (!DecodeExport(d, env, &dupSet))
1356 0 : return false;
1357 : }
1358 :
1359 0 : if (!d.finishSection(sectionStart, sectionSize, "export"))
1360 0 : return false;
1361 :
1362 0 : return true;
1363 : }
1364 :
1365 : static bool
1366 0 : DecodeStartSection(Decoder& d, ModuleEnvironment* env)
1367 : {
1368 : uint32_t sectionStart, sectionSize;
1369 0 : if (!d.startSection(SectionId::Start, env, §ionStart, §ionSize, "start"))
1370 0 : return false;
1371 0 : if (sectionStart == Decoder::NotStarted)
1372 0 : return true;
1373 :
1374 : uint32_t funcIndex;
1375 0 : if (!d.readVarU32(&funcIndex))
1376 0 : return d.fail("failed to read start func index");
1377 :
1378 0 : if (funcIndex >= env->numFuncs())
1379 0 : return d.fail("unknown start function");
1380 :
1381 0 : const Sig& sig = *env->funcSigs[funcIndex];
1382 0 : if (!IsVoid(sig.ret()))
1383 0 : return d.fail("start function must not return anything");
1384 :
1385 0 : if (sig.args().length())
1386 0 : return d.fail("start function must be nullary");
1387 :
1388 0 : env->startFuncIndex = Some(funcIndex);
1389 :
1390 0 : if (!d.finishSection(sectionStart, sectionSize, "start"))
1391 0 : return false;
1392 :
1393 0 : return true;
1394 : }
1395 :
1396 : static bool
1397 0 : DecodeElemSection(Decoder& d, ModuleEnvironment* env)
1398 : {
1399 : uint32_t sectionStart, sectionSize;
1400 0 : if (!d.startSection(SectionId::Elem, env, §ionStart, §ionSize, "elem"))
1401 0 : return false;
1402 0 : if (sectionStart == Decoder::NotStarted)
1403 0 : return true;
1404 :
1405 : uint32_t numSegments;
1406 0 : if (!d.readVarU32(&numSegments))
1407 0 : return d.fail("failed to read number of elem segments");
1408 :
1409 0 : if (numSegments > MaxElemSegments)
1410 0 : return d.fail("too many elem segments");
1411 :
1412 0 : for (uint32_t i = 0; i < numSegments; i++) {
1413 : uint32_t tableIndex;
1414 0 : if (!d.readVarU32(&tableIndex))
1415 0 : return d.fail("expected table index");
1416 :
1417 0 : MOZ_ASSERT(env->tables.length() <= 1);
1418 0 : if (tableIndex >= env->tables.length())
1419 0 : return d.fail("table index out of range");
1420 :
1421 0 : InitExpr offset;
1422 0 : if (!DecodeInitializerExpression(d, env->globals, ValType::I32, &offset))
1423 0 : return false;
1424 :
1425 : uint32_t numElems;
1426 0 : if (!d.readVarU32(&numElems))
1427 0 : return d.fail("expected segment size");
1428 :
1429 0 : if (numElems > MaxTableInitialLength)
1430 0 : return d.fail("too many table elements");
1431 :
1432 0 : Uint32Vector elemFuncIndices;
1433 0 : if (!elemFuncIndices.resize(numElems))
1434 0 : return false;
1435 :
1436 0 : for (uint32_t i = 0; i < numElems; i++) {
1437 0 : if (!d.readVarU32(&elemFuncIndices[i]))
1438 0 : return d.fail("failed to read element function index");
1439 0 : if (elemFuncIndices[i] >= env->numFuncs())
1440 0 : return d.fail("table element out of range");
1441 : }
1442 :
1443 0 : if (!env->elemSegments.emplaceBack(0, offset, Move(elemFuncIndices)))
1444 0 : return false;
1445 :
1446 0 : env->tables[env->elemSegments.back().tableIndex].external = true;
1447 : }
1448 :
1449 0 : if (!d.finishSection(sectionStart, sectionSize, "elem"))
1450 0 : return false;
1451 :
1452 0 : return true;
1453 : }
1454 :
1455 : bool
1456 0 : wasm::DecodeModuleEnvironment(Decoder& d, ModuleEnvironment* env)
1457 : {
1458 0 : if (!DecodePreamble(d))
1459 0 : return false;
1460 :
1461 0 : if (!DecodeTypeSection(d, env))
1462 0 : return false;
1463 :
1464 0 : if (!DecodeImportSection(d, env))
1465 0 : return false;
1466 :
1467 0 : if (!DecodeFunctionSection(d, env))
1468 0 : return false;
1469 :
1470 0 : if (!DecodeTableSection(d, env))
1471 0 : return false;
1472 :
1473 0 : if (!DecodeMemorySection(d, env))
1474 0 : return false;
1475 :
1476 0 : if (!DecodeGlobalSection(d, env))
1477 0 : return false;
1478 :
1479 0 : if (!DecodeExportSection(d, env))
1480 0 : return false;
1481 :
1482 0 : if (!DecodeStartSection(d, env))
1483 0 : return false;
1484 :
1485 0 : if (!DecodeElemSection(d, env))
1486 0 : return false;
1487 :
1488 0 : return true;
1489 : }
1490 :
1491 : static bool
1492 0 : DecodeFunctionBody(Decoder& d, const ModuleEnvironment& env, uint32_t funcIndex)
1493 : {
1494 : uint32_t bodySize;
1495 0 : if (!d.readVarU32(&bodySize))
1496 0 : return d.fail("expected number of function body bytes");
1497 :
1498 0 : if (bodySize > MaxFunctionBytes)
1499 0 : return d.fail("function body too big");
1500 :
1501 0 : if (d.bytesRemain() < bodySize)
1502 0 : return d.fail("function body length too big");
1503 :
1504 0 : if (!ValidateFunctionBody(env, funcIndex, bodySize, d))
1505 0 : return false;
1506 :
1507 0 : return true;
1508 : }
1509 :
1510 : static bool
1511 0 : DecodeCodeSection(Decoder& d, ModuleEnvironment* env)
1512 : {
1513 : uint32_t sectionStart, sectionSize;
1514 0 : if (!d.startSection(SectionId::Code, env, §ionStart, §ionSize, "code"))
1515 0 : return false;
1516 :
1517 0 : if (sectionStart == Decoder::NotStarted) {
1518 0 : if (env->numFuncDefs() != 0)
1519 0 : return d.fail("expected function bodies");
1520 0 : return true;
1521 : }
1522 :
1523 : uint32_t numFuncDefs;
1524 0 : if (!d.readVarU32(&numFuncDefs))
1525 0 : return d.fail("expected function body count");
1526 :
1527 0 : if (numFuncDefs != env->numFuncDefs())
1528 0 : return d.fail("function body count does not match function signature count");
1529 :
1530 0 : for (uint32_t funcDefIndex = 0; funcDefIndex < numFuncDefs; funcDefIndex++) {
1531 0 : if (!DecodeFunctionBody(d, *env, env->numFuncImports() + funcDefIndex))
1532 0 : return false;
1533 : }
1534 :
1535 0 : if (!d.finishSection(sectionStart, sectionSize, "code"))
1536 0 : return false;
1537 :
1538 0 : return true;
1539 : }
1540 :
1541 : static bool
1542 0 : DecodeDataSection(Decoder& d, ModuleEnvironment* env)
1543 : {
1544 : uint32_t sectionStart, sectionSize;
1545 0 : if (!d.startSection(SectionId::Data, env, §ionStart, §ionSize, "data"))
1546 0 : return false;
1547 0 : if (sectionStart == Decoder::NotStarted)
1548 0 : return true;
1549 :
1550 : uint32_t numSegments;
1551 0 : if (!d.readVarU32(&numSegments))
1552 0 : return d.fail("failed to read number of data segments");
1553 :
1554 0 : if (numSegments > MaxDataSegments)
1555 0 : return d.fail("too many data segments");
1556 :
1557 0 : for (uint32_t i = 0; i < numSegments; i++) {
1558 : uint32_t linearMemoryIndex;
1559 0 : if (!d.readVarU32(&linearMemoryIndex))
1560 0 : return d.fail("expected linear memory index");
1561 :
1562 0 : if (linearMemoryIndex != 0)
1563 0 : return d.fail("linear memory index must currently be 0");
1564 :
1565 0 : if (!env->usesMemory())
1566 0 : return d.fail("data segment requires a memory section");
1567 :
1568 0 : DataSegment seg;
1569 0 : if (!DecodeInitializerExpression(d, env->globals, ValType::I32, &seg.offset))
1570 0 : return false;
1571 :
1572 0 : if (!d.readVarU32(&seg.length))
1573 0 : return d.fail("expected segment size");
1574 :
1575 0 : if (seg.length > MaxMemoryInitialPages * PageSize)
1576 0 : return d.fail("segment size too big");
1577 :
1578 0 : seg.bytecodeOffset = d.currentOffset();
1579 :
1580 0 : if (!d.readBytes(seg.length))
1581 0 : return d.fail("data segment shorter than declared");
1582 :
1583 0 : if (!env->dataSegments.append(seg))
1584 0 : return false;
1585 : }
1586 :
1587 0 : if (!d.finishSection(sectionStart, sectionSize, "data"))
1588 0 : return false;
1589 :
1590 0 : return true;
1591 : }
1592 :
1593 : static bool
1594 0 : DecodeModuleNameSubsection(Decoder& d, ModuleEnvironment* env)
1595 : {
1596 : uint32_t endOffset;
1597 0 : if (!d.startNameSubsection(NameType::Module, &endOffset))
1598 0 : return false;
1599 0 : if (endOffset == Decoder::NotStarted)
1600 0 : return true;
1601 :
1602 : // Don't use NameInBytecode for module name; instead store a copy of the
1603 : // string. This way supplying a module name doesn't need to save the whole
1604 : // bytecode. While function names are likely to be stripped in practice,
1605 : // module names aren't necessarily.
1606 :
1607 : uint32_t nameLength;
1608 0 : if (!d.readVarU32(&nameLength))
1609 0 : return false;
1610 :
1611 : const uint8_t* bytes;
1612 0 : if (!d.readBytes(nameLength, &bytes))
1613 0 : return false;
1614 :
1615 : // Do nothing with module name for now; a future patch will incorporate the
1616 : // module name into the callstack format.
1617 :
1618 0 : return d.finishNameSubsection(endOffset);
1619 : }
1620 :
1621 : static bool
1622 0 : DecodeFunctionNameSubsection(Decoder& d, ModuleEnvironment* env)
1623 : {
1624 : uint32_t endOffset;
1625 0 : if (!d.startNameSubsection(NameType::Function, &endOffset))
1626 0 : return false;
1627 0 : if (endOffset == Decoder::NotStarted)
1628 0 : return true;
1629 :
1630 0 : uint32_t nameCount = 0;
1631 0 : if (!d.readVarU32(&nameCount) || nameCount > MaxFuncs)
1632 0 : return false;
1633 :
1634 0 : NameInBytecodeVector funcNames;
1635 :
1636 0 : for (uint32_t i = 0; i < nameCount; ++i) {
1637 0 : uint32_t funcIndex = 0;
1638 0 : if (!d.readVarU32(&funcIndex))
1639 0 : return false;
1640 :
1641 : // Names must refer to real functions and be given in ascending order.
1642 0 : if (funcIndex >= env->numFuncs() || funcIndex < funcNames.length())
1643 0 : return false;
1644 :
1645 0 : if (!funcNames.resize(funcIndex + 1))
1646 0 : return false;
1647 :
1648 0 : uint32_t nameLength = 0;
1649 0 : if (!d.readVarU32(&nameLength) || nameLength > MaxStringLength)
1650 0 : return false;
1651 :
1652 0 : NameInBytecode func;
1653 0 : func.offset = d.currentOffset();
1654 0 : func.length = nameLength;
1655 0 : funcNames[funcIndex] = func;
1656 :
1657 0 : if (!d.readBytes(nameLength))
1658 0 : return false;
1659 : }
1660 :
1661 0 : if (!d.finishNameSubsection(endOffset))
1662 0 : return false;
1663 :
1664 : // To encourage fully valid function names subsections; only save names if
1665 : // the entire subsection decoded correctly.
1666 0 : env->funcNames = Move(funcNames);
1667 0 : return true;
1668 : }
1669 :
1670 : static bool
1671 0 : DecodeNameSection(Decoder& d, ModuleEnvironment* env)
1672 : {
1673 : uint32_t sectionStart, sectionSize;
1674 0 : if (!d.startCustomSection(NameSectionName, env, §ionStart, §ionSize))
1675 0 : return false;
1676 0 : if (sectionStart == Decoder::NotStarted)
1677 0 : return true;
1678 :
1679 : // Once started, custom sections do not report validation errors.
1680 :
1681 0 : if (!DecodeModuleNameSubsection(d, env))
1682 0 : goto finish;
1683 :
1684 0 : if (!DecodeFunctionNameSubsection(d, env))
1685 0 : goto finish;
1686 :
1687 : // The names we care about have already been extracted into 'env' so don't
1688 : // bother decoding the rest of the name section. finishCustomSection() will
1689 : // skip to the end of the name section (as it would for any other error).
1690 :
1691 : finish:
1692 0 : d.finishCustomSection(sectionStart, sectionSize);
1693 0 : return true;
1694 : }
1695 :
1696 : bool
1697 0 : wasm::DecodeModuleTail(Decoder& d, ModuleEnvironment* env)
1698 : {
1699 0 : if (!DecodeDataSection(d, env))
1700 0 : return false;
1701 :
1702 0 : if (!DecodeNameSection(d, env))
1703 0 : return false;
1704 :
1705 0 : while (!d.done()) {
1706 0 : if (!d.skipCustomSection(env)) {
1707 0 : if (d.resilientMode()) {
1708 0 : d.clearError();
1709 0 : return true;
1710 : }
1711 0 : return false;
1712 : }
1713 : }
1714 :
1715 0 : return true;
1716 : }
1717 :
1718 : // Validate algorithm.
1719 :
1720 : bool
1721 0 : wasm::Validate(const ShareableBytes& bytecode, UniqueChars* error)
1722 : {
1723 0 : Decoder d(bytecode.bytes, error);
1724 :
1725 0 : ModuleEnvironment env;
1726 0 : if (!DecodeModuleEnvironment(d, &env))
1727 0 : return false;
1728 :
1729 0 : if (!DecodeCodeSection(d, &env))
1730 0 : return false;
1731 :
1732 0 : if (!DecodeModuleTail(d, &env))
1733 0 : return false;
1734 :
1735 0 : MOZ_ASSERT(!*error, "unreported error in decoding");
1736 0 : return true;
1737 : }
|