blob: 0738b5909ba21eefab237669041ee20d016ed195 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "test/unittests/test-utils.h"
6
7#include "src/wasm/module-decoder.h"
8#include "src/wasm/wasm-opcodes.h"
9
10namespace v8 {
11namespace internal {
12namespace wasm {
13
14class WasmModuleVerifyTest : public TestWithZone {
15 public:
16 ModuleResult DecodeModule(const byte* module_start, const byte* module_end) {
17 return DecodeWasmModule(nullptr, zone(), module_start, module_end, false,
18 false);
19 }
20};
21
22
23#define EXPECT_VERIFIES(data) \
24 do { \
25 ModuleResult result = DecodeModule(data, data + arraysize(data)); \
26 EXPECT_TRUE(result.ok()); \
27 if (result.val) delete result.val; \
28 } while (false)
29
30
31#define EXPECT_FAILURE(data) \
32 do { \
33 ModuleResult result = DecodeModule(data, data + arraysize(data)); \
34 EXPECT_FALSE(result.ok()); \
35 if (result.val) delete result.val; \
36 } while (false)
37
38
39struct LocalTypePair {
40 uint8_t code;
41 LocalType type;
42} kLocalTypes[] = {{kLocalI32, kAstI32},
43 {kLocalI64, kAstI64},
44 {kLocalF32, kAstF32},
45 {kLocalF64, kAstF64}};
46
47
48TEST_F(WasmModuleVerifyTest, DecodeEmpty) {
49 static const byte data[1]{kDeclEnd};
50 {
51 ModuleResult result = DecodeModule(data, data);
52 EXPECT_TRUE(result.ok());
53 if (result.val) delete result.val;
54 }
55 {
56 ModuleResult result = DecodeModule(data, data + 1);
57 EXPECT_TRUE(result.ok());
58 if (result.val) delete result.val;
59 }
60}
61
62
63TEST_F(WasmModuleVerifyTest, OneGlobal) {
64 const byte data[] = {
65 kDeclGlobals,
66 1,
67 0,
68 0,
69 0,
70 0, // name offset
71 kMemI32, // memory type
72 0, // exported
73 };
74
75 {
76 // Should decode to exactly one global.
77 ModuleResult result = DecodeModule(data, data + arraysize(data));
78 EXPECT_TRUE(result.ok());
79 EXPECT_EQ(1, result.val->globals->size());
80 EXPECT_EQ(0, result.val->functions->size());
81 EXPECT_EQ(0, result.val->data_segments->size());
82
83 WasmGlobal* global = &result.val->globals->back();
84
85 EXPECT_EQ(0, global->name_offset);
86 EXPECT_EQ(MachineType::Int32(), global->type);
87 EXPECT_EQ(0, global->offset);
88 EXPECT_FALSE(global->exported);
89
90 if (result.val) delete result.val;
91 }
92
93 for (size_t size = 1; size < arraysize(data); size++) {
94 // Should fall off end of module bytes.
95 ModuleResult result = DecodeModule(data, data + size);
96 EXPECT_FALSE(result.ok());
97 if (result.val) delete result.val;
98 }
99}
100
101
102TEST_F(WasmModuleVerifyTest, ZeroGlobals) {
103 const byte data[] = {
104 kDeclGlobals, 0, // declare 0 globals
105 };
106 ModuleResult result = DecodeModule(data, data + arraysize(data));
107 EXPECT_TRUE(result.ok());
108 if (result.val) delete result.val;
109}
110
111
112static void AppendUint32v(std::vector<byte>& buffer, uint32_t val) {
113 while (true) {
114 uint32_t next = val >> 7;
115 uint32_t out = val & 0x7f;
116 if (next) {
117 buffer.push_back(static_cast<byte>(0x80 | out));
118 val = next;
119 } else {
120 buffer.push_back(static_cast<byte>(out));
121 break;
122 }
123 }
124}
125
126
127TEST_F(WasmModuleVerifyTest, NGlobals) {
128 const byte data[] = {
129 0, 0, 0, 0, // name offset
130 kMemI32, // memory type
131 0, // exported
132 };
133 for (uint32_t i = 0; i < 1000000; i = i * 7 + 1) {
134 std::vector<byte> buffer;
135 buffer.push_back(kDeclGlobals);
136 AppendUint32v(buffer, i);
137 for (uint32_t j = 0; j < i; j++) {
138 buffer.insert(buffer.end(), data, data + arraysize(data));
139 }
140
141 ModuleResult result = DecodeModule(&buffer[0], &buffer[0] + buffer.size());
142 EXPECT_TRUE(result.ok());
143 if (result.val) delete result.val;
144 }
145}
146
147
148TEST_F(WasmModuleVerifyTest, GlobalWithInvalidNameOffset) {
149 const byte data[] = {
150 kDeclGlobals,
151 1, // declare one global
152 0,
153 3,
154 0,
155 0, // name offset
156 kMemI32, // memory type
157 0, // exported
158 };
159
160 EXPECT_FAILURE(data);
161}
162
163
164TEST_F(WasmModuleVerifyTest, GlobalWithInvalidMemoryType) {
165 const byte data[] = {
166 kDeclGlobals,
167 1, // declare one global
168 0,
169 0,
170 0,
171 0, // name offset
172 33, // memory type
173 0, // exported
174 };
175
176 EXPECT_FAILURE(data);
177}
178
179
180TEST_F(WasmModuleVerifyTest, TwoGlobals) {
181 const byte data[] = {
182 kDeclGlobals,
183 2,
184 0,
185 0,
186 0,
187 0, // #0: name offset
188 kMemF32, // memory type
189 0, // exported
190 0,
191 0,
192 0,
193 0, // #1: name offset
194 kMemF64, // memory type
195 1, // exported
196 };
197
198 {
199 // Should decode to exactly two globals.
200 ModuleResult result = DecodeModule(data, data + arraysize(data));
201 EXPECT_TRUE(result.ok());
202 EXPECT_EQ(2, result.val->globals->size());
203 EXPECT_EQ(0, result.val->functions->size());
204 EXPECT_EQ(0, result.val->data_segments->size());
205
206 WasmGlobal* g0 = &result.val->globals->at(0);
207 WasmGlobal* g1 = &result.val->globals->at(1);
208
209 EXPECT_EQ(0, g0->name_offset);
210 EXPECT_EQ(MachineType::Float32(), g0->type);
211 EXPECT_EQ(0, g0->offset);
212 EXPECT_FALSE(g0->exported);
213
214 EXPECT_EQ(0, g1->name_offset);
215 EXPECT_EQ(MachineType::Float64(), g1->type);
216 EXPECT_EQ(0, g1->offset);
217 EXPECT_TRUE(g1->exported);
218
219 if (result.val) delete result.val;
220 }
221
222 for (size_t size = 1; size < arraysize(data); size++) {
223 // Should fall off end of module bytes.
224 ModuleResult result = DecodeModule(data, data + size);
225 EXPECT_FALSE(result.ok());
226 if (result.val) delete result.val;
227 }
228}
229
230
231TEST_F(WasmModuleVerifyTest, OneSignature) {
232 static const byte data[] = {
233 kDeclSignatures, 1, 0, kLocalVoid // void -> void
234 };
235 EXPECT_VERIFIES(data);
236}
237
238
239TEST_F(WasmModuleVerifyTest, MultipleSignatures) {
240 static const byte data[] = {
241 kDeclSignatures,
242 3,
243 0,
244 kLocalVoid, // void -> void
245 1,
246 kLocalI32,
247 kLocalF32, // f32 -> i32
248 2,
249 kLocalI32,
250 kLocalF64,
251 kLocalF64, // (f64,f64) -> i32
252 };
253
254 ModuleResult result = DecodeModule(data, data + arraysize(data));
255 EXPECT_TRUE(result.ok());
256 EXPECT_EQ(3, result.val->signatures->size());
257 if (result.val->signatures->size() == 3) {
258 EXPECT_EQ(0, result.val->signatures->at(0)->return_count());
259 EXPECT_EQ(1, result.val->signatures->at(1)->return_count());
260 EXPECT_EQ(1, result.val->signatures->at(2)->return_count());
261
262 EXPECT_EQ(0, result.val->signatures->at(0)->parameter_count());
263 EXPECT_EQ(1, result.val->signatures->at(1)->parameter_count());
264 EXPECT_EQ(2, result.val->signatures->at(2)->parameter_count());
265 }
266 if (result.val) delete result.val;
267
268 for (size_t size = 1; size < arraysize(data); size++) {
269 ModuleResult result = DecodeModule(data, data + size);
270 // Should fall off the end of module bytes.
271 EXPECT_FALSE(result.ok());
272 if (result.val) delete result.val;
273 }
274}
275
276
277TEST_F(WasmModuleVerifyTest, FunctionWithoutSig) {
278 static const byte data[] = {
279 kDeclFunctions, 1,
280 // func#0 ------------------------------------------------------
281 0, 0, // signature index
282 0, 0, 0, 0, // name offset
283 0, 0, 0, 0, // code start offset
284 0, 0, 0, 0, // code end offset
285 1, 2, // local int32 count
286 3, 4, // local int64 count
287 5, 6, // local float32 count
288 7, 8, // local float64 count
289 0, // exported
290 1 // external
291 };
292
293 ModuleResult result = DecodeModule(data, data + arraysize(data));
294 EXPECT_FALSE(result.ok());
295 if (result.val) delete result.val;
296}
297
298
299TEST_F(WasmModuleVerifyTest, OneEmptyVoidVoidFunction) {
300 const int kCodeStartOffset = 23;
301 const int kCodeEndOffset = kCodeStartOffset + 1;
302
303 static const byte data[] = {
304 kDeclSignatures, 1,
305 // sig#0 -------------------------------------------------------
306 0, 0, // void -> void
307 // func#0 ------------------------------------------------------
308 kDeclFunctions, 1,
309 kDeclFunctionLocals | kDeclFunctionExport | kDeclFunctionName, 0,
310 0, // signature index
311 9, 0, 0, 0, // name offset
312 11, 2, // local int32 count
313 13, 4, // local int64 count
314 15, 6, // local float32 count
315 17, 8, // local float64 count
316 1, 0, // size
317 kExprNop,
318 };
319
320 {
321 // Should decode to exactly one function.
322 ModuleResult result = DecodeModule(data, data + arraysize(data));
323 EXPECT_TRUE(result.ok());
324 EXPECT_EQ(0, result.val->globals->size());
325 EXPECT_EQ(1, result.val->signatures->size());
326 EXPECT_EQ(1, result.val->functions->size());
327 EXPECT_EQ(0, result.val->data_segments->size());
328 EXPECT_EQ(0, result.val->function_table->size());
329
330 WasmFunction* function = &result.val->functions->back();
331
332 EXPECT_EQ(9, function->name_offset);
333 EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
334 EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
335
336 EXPECT_EQ(523, function->local_int32_count);
337 EXPECT_EQ(1037, function->local_int64_count);
338 EXPECT_EQ(1551, function->local_float32_count);
339 EXPECT_EQ(2065, function->local_float64_count);
340
341 EXPECT_TRUE(function->exported);
342 EXPECT_FALSE(function->external);
343
344 if (result.val) delete result.val;
345 }
346
347 for (size_t size = 5; size < arraysize(data); size++) {
348 // Should fall off end of module bytes.
349 ModuleResult result = DecodeModule(data, data + size);
350 EXPECT_FALSE(result.ok());
351 if (result.val) delete result.val;
352 }
353}
354
355
356TEST_F(WasmModuleVerifyTest, OneFunctionImported) {
357 static const byte data[] = {
358 kDeclSignatures, 1,
359 // sig#0 -------------------------------------------------------
360 0, 0, // void -> void
361 kDeclFunctions, 1,
362 // func#0 ------------------------------------------------------
363 kDeclFunctionImport, // no name, no locals, imported
364 0, 0, // signature index
365 };
366
367 ModuleResult result = DecodeModule(data, data + arraysize(data));
368 EXPECT_TRUE(result.ok());
369 EXPECT_EQ(1, result.val->functions->size());
370 WasmFunction* function = &result.val->functions->back();
371
372 EXPECT_EQ(0, function->name_offset);
373 EXPECT_EQ(0, function->code_start_offset);
374 EXPECT_EQ(0, function->code_end_offset);
375
376 EXPECT_EQ(0, function->local_int32_count);
377 EXPECT_EQ(0, function->local_int64_count);
378 EXPECT_EQ(0, function->local_float32_count);
379 EXPECT_EQ(0, function->local_float64_count);
380
381 EXPECT_FALSE(function->exported);
382 EXPECT_TRUE(function->external);
383
384 if (result.val) delete result.val;
385}
386
387
388TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody) {
389 static const byte kCodeStartOffset = 11;
390 static const byte kCodeEndOffset = kCodeStartOffset + 1;
391
392 static const byte data[] = {
393 kDeclSignatures, 1,
394 // sig#0 -------------------------------------------------------
395 0, 0, // void -> void
396 kDeclFunctions, 1,
397 // func#0 ------------------------------------------------------
398 0, // no name, no locals
399 0, 0, // signature index
400 1, 0, // body size
401 kExprNop // body
402 };
403
404 ModuleResult result = DecodeModule(data, data + arraysize(data));
405 EXPECT_TRUE(result.ok());
406 EXPECT_EQ(1, result.val->functions->size());
407 WasmFunction* function = &result.val->functions->back();
408
409 EXPECT_EQ(0, function->name_offset);
410 EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
411 EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
412
413 EXPECT_EQ(0, function->local_int32_count);
414 EXPECT_EQ(0, function->local_int64_count);
415 EXPECT_EQ(0, function->local_float32_count);
416 EXPECT_EQ(0, function->local_float64_count);
417
418 EXPECT_FALSE(function->exported);
419 EXPECT_FALSE(function->external);
420
421 if (result.val) delete result.val;
422}
423
424
425TEST_F(WasmModuleVerifyTest, OneFunctionWithNopBody_WithLocals) {
426 static const byte kCodeStartOffset = 19;
427 static const byte kCodeEndOffset = kCodeStartOffset + 1;
428
429 static const byte data[] = {
430 kDeclSignatures, 1,
431 // sig#0 -------------------------------------------------------
432 0, 0, // void -> void
433 kDeclFunctions, 1,
434 // func#0 ------------------------------------------------------
435 kDeclFunctionLocals, 0, 0, // signature index
436 1, 2, // local int32 count
437 3, 4, // local int64 count
438 5, 6, // local float32 count
439 7, 8, // local float64 count
440 1, 0, // body size
441 kExprNop // body
442 };
443
444 ModuleResult result = DecodeModule(data, data + arraysize(data));
445 EXPECT_TRUE(result.ok());
446 EXPECT_EQ(1, result.val->functions->size());
447 WasmFunction* function = &result.val->functions->back();
448
449 EXPECT_EQ(0, function->name_offset);
450 EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
451 EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
452
453 EXPECT_EQ(513, function->local_int32_count);
454 EXPECT_EQ(1027, function->local_int64_count);
455 EXPECT_EQ(1541, function->local_float32_count);
456 EXPECT_EQ(2055, function->local_float64_count);
457
458 EXPECT_FALSE(function->exported);
459 EXPECT_FALSE(function->external);
460
461 if (result.val) delete result.val;
462}
463
464
465TEST_F(WasmModuleVerifyTest, OneGlobalOneFunctionWithNopBodyOneDataSegment) {
466 static const byte kCodeStartOffset = 2 + kDeclGlobalSize + 4 + 2 + 17;
467 static const byte kCodeEndOffset = kCodeStartOffset + 3;
468
469 static const byte data[] = {
470 // global#0 --------------------------------------------------
471 kDeclGlobals, 1, 0, 0, 0, 0, // name offset
472 kMemU8, // memory type
473 0, // exported
474 // sig#0 -----------------------------------------------------
475 kDeclSignatures, 1, 0, 0, // void -> void
476 // func#0 ----------------------------------------------------
477 kDeclFunctions, 1, kDeclFunctionLocals | kDeclFunctionName, 0,
478 0, // signature index
479 9, 0, 0, 0, // name offset
480 1, 2, // local int32 count
481 3, 4, // local int64 count
482 5, 6, // local float32 count
483 7, 8, // local float64 count
484 3, 0, // body size
485 kExprNop, // func#0 body
486 kExprNop, // func#0 body
487 kExprNop, // func#0 body
488 // segment#0 -------------------------------------------------
489 kDeclDataSegments, 1, 0xae, 0xb3, 0x08, 0, // dest addr
490 15, 0, 0, 0, // source offset
491 5, 0, 0, 0, // source size
492 1, // init
493 // rest ------------------------------------------------------
494 kDeclEnd,
495 };
496
497 {
498 ModuleResult result = DecodeModule(data, data + arraysize(data));
499 EXPECT_TRUE(result.ok());
500 EXPECT_EQ(1, result.val->globals->size());
501 EXPECT_EQ(1, result.val->functions->size());
502 EXPECT_EQ(1, result.val->data_segments->size());
503
504 WasmGlobal* global = &result.val->globals->back();
505
506 EXPECT_EQ(0, global->name_offset);
507 EXPECT_EQ(MachineType::Uint8(), global->type);
508 EXPECT_EQ(0, global->offset);
509 EXPECT_FALSE(global->exported);
510
511 WasmFunction* function = &result.val->functions->back();
512
513 EXPECT_EQ(9, function->name_offset);
514 EXPECT_EQ(kCodeStartOffset, function->code_start_offset);
515 EXPECT_EQ(kCodeEndOffset, function->code_end_offset);
516
517 EXPECT_FALSE(function->exported);
518 EXPECT_FALSE(function->external);
519
520 WasmDataSegment* segment = &result.val->data_segments->back();
521
522 EXPECT_EQ(0x8b3ae, segment->dest_addr);
523 EXPECT_EQ(15, segment->source_offset);
524 EXPECT_EQ(5, segment->source_size);
525 EXPECT_TRUE(segment->init);
526
527 if (result.val) delete result.val;
528 }
529}
530
531
532TEST_F(WasmModuleVerifyTest, OneDataSegment) {
533 const byte data[] = {
534 kDeclDataSegments,
535 1,
536 0xaa,
537 0xbb,
538 0x09,
539 0, // dest addr
540 11,
541 0,
542 0,
543 0, // source offset
544 3,
545 0,
546 0,
547 0, // source size
548 1, // init
549 };
550
551 {
552 ModuleResult result = DecodeModule(data, data + arraysize(data));
553 EXPECT_TRUE(result.ok());
554 EXPECT_EQ(0, result.val->globals->size());
555 EXPECT_EQ(0, result.val->functions->size());
556 EXPECT_EQ(1, result.val->data_segments->size());
557
558 WasmDataSegment* segment = &result.val->data_segments->back();
559
560 EXPECT_EQ(0x9bbaa, segment->dest_addr);
561 EXPECT_EQ(11, segment->source_offset);
562 EXPECT_EQ(3, segment->source_size);
563 EXPECT_TRUE(segment->init);
564
565 if (result.val) delete result.val;
566 }
567
568 for (size_t size = 1; size < arraysize(data); size++) {
569 // Should fall off end of module bytes.
570 ModuleResult result = DecodeModule(data, data + size);
571 EXPECT_FALSE(result.ok());
572 if (result.val) delete result.val;
573 }
574}
575
576
577TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
578 const byte data[] = {
579 kDeclDataSegments,
580 2,
581 0xee,
582 0xff,
583 0x07,
584 0, // dest addr
585 9,
586 0,
587 0,
588 0, // #0: source offset
589 4,
590 0,
591 0,
592 0, // source size
593 0, // init
594 0xcc,
595 0xdd,
596 0x06,
597 0, // #1: dest addr
598 6,
599 0,
600 0,
601 0, // source offset
602 10,
603 0,
604 0,
605 0, // source size
606 1, // init
607 };
608
609 {
610 ModuleResult result = DecodeModule(data, data + arraysize(data));
611 EXPECT_TRUE(result.ok());
612 EXPECT_EQ(0, result.val->globals->size());
613 EXPECT_EQ(0, result.val->functions->size());
614 EXPECT_EQ(2, result.val->data_segments->size());
615
616 WasmDataSegment* s0 = &result.val->data_segments->at(0);
617 WasmDataSegment* s1 = &result.val->data_segments->at(1);
618
619 EXPECT_EQ(0x7ffee, s0->dest_addr);
620 EXPECT_EQ(9, s0->source_offset);
621 EXPECT_EQ(4, s0->source_size);
622 EXPECT_FALSE(s0->init);
623
624 EXPECT_EQ(0x6ddcc, s1->dest_addr);
625 EXPECT_EQ(6, s1->source_offset);
626 EXPECT_EQ(10, s1->source_size);
627 EXPECT_TRUE(s1->init);
628
629 if (result.val) delete result.val;
630 }
631
632 for (size_t size = 1; size < arraysize(data); size++) {
633 // Should fall off end of module bytes.
634 ModuleResult result = DecodeModule(data, data + size);
635 EXPECT_FALSE(result.ok());
636 if (result.val) delete result.val;
637 }
638}
639
640
641// To make below tests for indirect calls much shorter.
642#define FUNCTION(sig_index, external) \
643 kDeclFunctionImport, static_cast<byte>(sig_index), \
644 static_cast<byte>(sig_index >> 8)
645
646
647TEST_F(WasmModuleVerifyTest, OneIndirectFunction) {
648 static const byte data[] = {
649 // sig#0 -------------------------------------------------------
650 kDeclSignatures, 1, 0, 0, // void -> void
651 // func#0 ------------------------------------------------------
652 kDeclFunctions, 1, FUNCTION(0, 0),
653 // indirect table ----------------------------------------------
654 kDeclFunctionTable, 1, 0, 0};
655
656 ModuleResult result = DecodeModule(data, data + arraysize(data));
657 EXPECT_TRUE(result.ok());
658 if (result.ok()) {
659 EXPECT_EQ(1, result.val->signatures->size());
660 EXPECT_EQ(1, result.val->functions->size());
661 EXPECT_EQ(1, result.val->function_table->size());
662 EXPECT_EQ(0, result.val->function_table->at(0));
663 }
664 if (result.val) delete result.val;
665}
666
667
668TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) {
669 static const byte data[] = {
670 // sig#0 -------------------------------------------------------
671 kDeclSignatures, 2, 0, 0, // void -> void
672 0, kLocalI32, // void -> i32
673 // func#0 ------------------------------------------------------
674 kDeclFunctions, 4, FUNCTION(0, 1), FUNCTION(1, 1), FUNCTION(0, 1),
675 FUNCTION(1, 1),
676 // indirect table ----------------------------------------------
677 kDeclFunctionTable, 8, 0, 0, 1, 0, 2, 0, 3, 0, 0, 0, 1, 0, 2, 0, 3, 0,
678 };
679
680 ModuleResult result = DecodeModule(data, data + arraysize(data));
681 EXPECT_TRUE(result.ok());
682 if (result.ok()) {
683 EXPECT_EQ(2, result.val->signatures->size());
684 EXPECT_EQ(4, result.val->functions->size());
685 EXPECT_EQ(8, result.val->function_table->size());
686 for (int i = 0; i < 8; i++) {
687 EXPECT_EQ(i & 3, result.val->function_table->at(i));
688 }
689 }
690 if (result.val) delete result.val;
691}
692
693
694TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) {
695 static const byte data[] = {
696 // sig#0 -------------------------------------------------------
697 kDeclSignatures, 1, 0, 0, // void -> void
698 // indirect table ----------------------------------------------
699 kDeclFunctionTable, 1, 0, 0,
700 };
701
702 EXPECT_FAILURE(data);
703}
704
705
706TEST_F(WasmModuleVerifyTest, IndirectFunctionInvalidIndex) {
707 static const byte data[] = {
708 // sig#0 -------------------------------------------------------
709 kDeclSignatures, 1, 0, 0, // void -> void
710 // functions ---------------------------------------------------
711 kDeclFunctions, 1, FUNCTION(0, 1),
712 // indirect table ----------------------------------------------
713 kDeclFunctionTable, 1, 1, 0,
714 };
715
716 EXPECT_FAILURE(data);
717}
718
719
720class WasmSignatureDecodeTest : public TestWithZone {};
721
722
723TEST_F(WasmSignatureDecodeTest, Ok_v_v) {
724 static const byte data[] = {0, 0};
725 Zone zone;
726 FunctionSig* sig =
727 DecodeWasmSignatureForTesting(&zone, data, data + arraysize(data));
728
729 EXPECT_TRUE(sig != nullptr);
730 EXPECT_EQ(0, sig->parameter_count());
731 EXPECT_EQ(0, sig->return_count());
732}
733
734
735TEST_F(WasmSignatureDecodeTest, Ok_t_v) {
736 for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
737 LocalTypePair ret_type = kLocalTypes[i];
738 const byte data[] = {0, ret_type.code};
739 FunctionSig* sig =
740 DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
741
742 EXPECT_TRUE(sig != nullptr);
743 EXPECT_EQ(0, sig->parameter_count());
744 EXPECT_EQ(1, sig->return_count());
745 EXPECT_EQ(ret_type.type, sig->GetReturn());
746 }
747}
748
749
750TEST_F(WasmSignatureDecodeTest, Ok_v_t) {
751 for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
752 LocalTypePair param_type = kLocalTypes[i];
753 const byte data[] = {1, 0, param_type.code};
754 FunctionSig* sig =
755 DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
756
757 EXPECT_TRUE(sig != nullptr);
758 EXPECT_EQ(1, sig->parameter_count());
759 EXPECT_EQ(0, sig->return_count());
760 EXPECT_EQ(param_type.type, sig->GetParam(0));
761 }
762}
763
764
765TEST_F(WasmSignatureDecodeTest, Ok_t_t) {
766 for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
767 LocalTypePair ret_type = kLocalTypes[i];
768 for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
769 LocalTypePair param_type = kLocalTypes[j];
770 const byte data[] = {1, // param count
771 ret_type.code, // ret
772 param_type.code}; // param
773 FunctionSig* sig =
774 DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
775
776 EXPECT_TRUE(sig != nullptr);
777 EXPECT_EQ(1, sig->parameter_count());
778 EXPECT_EQ(1, sig->return_count());
779 EXPECT_EQ(param_type.type, sig->GetParam(0));
780 EXPECT_EQ(ret_type.type, sig->GetReturn());
781 }
782 }
783}
784
785
786TEST_F(WasmSignatureDecodeTest, Ok_i_tt) {
787 for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
788 LocalTypePair p0_type = kLocalTypes[i];
789 for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
790 LocalTypePair p1_type = kLocalTypes[j];
791 const byte data[] = {2, // param count
792 kLocalI32, // ret
793 p0_type.code, // p0
794 p1_type.code}; // p1
795 FunctionSig* sig =
796 DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
797
798 EXPECT_TRUE(sig != nullptr);
799 EXPECT_EQ(2, sig->parameter_count());
800 EXPECT_EQ(1, sig->return_count());
801 EXPECT_EQ(p0_type.type, sig->GetParam(0));
802 EXPECT_EQ(p1_type.type, sig->GetParam(1));
803 }
804 }
805}
806
807
808TEST_F(WasmSignatureDecodeTest, Fail_off_end) {
809 byte data[256];
810 for (int p = 0; p <= 255; p = p + 1 + p * 3) {
811 for (int i = 0; i <= p; i++) data[i] = kLocalI32;
812 data[0] = static_cast<byte>(p);
813
814 for (int i = 0; i < p + 1; i++) {
815 // Should fall off the end for all signatures.
816 FunctionSig* sig = DecodeWasmSignatureForTesting(zone(), data, data + i);
817 EXPECT_EQ(nullptr, sig);
818 }
819 }
820}
821
822
823TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) {
824 byte kInvalidType = 76;
825 for (int i = 1; i < 3; i++) {
826 byte data[] = {2, kLocalI32, kLocalI32, kLocalI32};
827 data[i] = kInvalidType;
828 FunctionSig* sig =
829 DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
830 EXPECT_EQ(nullptr, sig);
831 }
832}
833
834
835TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type) {
836 static const int kParamCount = 3;
837 for (int i = 0; i < kParamCount; i++) {
838 byte data[] = {kParamCount, kLocalI32, kLocalI32, kLocalI32, kLocalI32};
839 data[i + 2] = kLocalVoid;
840 FunctionSig* sig =
841 DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
842 EXPECT_EQ(nullptr, sig);
843 }
844}
845
846
847class WasmFunctionVerifyTest : public TestWithZone {};
848
849
850TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
851 byte data[] = {
852 0, kLocalVoid, // signature
853 3, 0, // local int32 count
854 4, 0, // local int64 count
855 5, 0, // local float32 count
856 6, 0, // local float64 count
857 kExprNop // body
858 };
859
860 FunctionResult result = DecodeWasmFunction(nullptr, zone(), nullptr, data,
861 data + arraysize(data));
862 EXPECT_TRUE(result.ok());
863
864 if (result.val && result.ok()) {
865 WasmFunction* function = result.val;
866 EXPECT_EQ(0, function->sig->parameter_count());
867 EXPECT_EQ(0, function->sig->return_count());
868 EXPECT_EQ(0, function->name_offset);
869 EXPECT_EQ(arraysize(data) - 1, function->code_start_offset);
870 EXPECT_EQ(arraysize(data), function->code_end_offset);
871 EXPECT_EQ(3, function->local_int32_count);
872 EXPECT_EQ(4, function->local_int64_count);
873 EXPECT_EQ(5, function->local_float32_count);
874 EXPECT_EQ(6, function->local_float64_count);
875 EXPECT_FALSE(function->external);
876 EXPECT_FALSE(function->exported);
877 }
878
879 if (result.val) delete result.val;
880}
881
882
883TEST_F(WasmModuleVerifyTest, WLLSectionNoLen) {
884 const byte data[] = {
885 kDeclWLL, // section without length.
886 };
887 EXPECT_FAILURE(data);
888}
889
890
891TEST_F(WasmModuleVerifyTest, WLLSectionEmpty) {
892 const byte data[] = {
893 kDeclWLL, 0, // empty section
894 };
895 ModuleResult result = DecodeModule(data, data + arraysize(data));
896 EXPECT_TRUE(result.ok());
897 if (result.val) delete result.val;
898}
899
900
901TEST_F(WasmModuleVerifyTest, WLLSectionOne) {
902 const byte data[] = {
903 kDeclWLL,
904 1, // LEB128 1
905 0, // one byte section
906 };
907 ModuleResult result = DecodeModule(data, data + arraysize(data));
908 EXPECT_TRUE(result.ok());
909 if (result.val) delete result.val;
910}
911
912
913TEST_F(WasmModuleVerifyTest, WLLSectionTen) {
914 const byte data[] = {
915 kDeclWLL,
916 10, // LEB128 10
917 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 10 byte section
918 };
919 ModuleResult result = DecodeModule(data, data + arraysize(data));
920 EXPECT_TRUE(result.ok());
921 if (result.val) delete result.val;
922}
923
924
925TEST_F(WasmModuleVerifyTest, WLLSectionOverflow) {
926 const byte data[] = {
927 kDeclWLL,
928 11, // LEB128 11
929 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 10 byte section
930 };
931 EXPECT_FAILURE(data);
932}
933
934
935TEST_F(WasmModuleVerifyTest, WLLSectionUnderflow) {
936 const byte data[] = {
937 kDeclWLL,
938 0xff, 0xff, 0xff, 0xff, 0x0f, // LEB128 0xffffffff
939 1, 2, 3, 4, // 4 byte section
940 };
941 EXPECT_FAILURE(data);
942}
943
944
945TEST_F(WasmModuleVerifyTest, WLLSectionLoop) {
946 // Would infinite loop decoding if wrapping and allowed.
947 const byte data[] = {
948 kDeclWLL,
949 0xfa, 0xff, 0xff, 0xff, 0x0f, // LEB128 0xfffffffa
950 1, 2, 3, 4, // 4 byte section
951 };
952 EXPECT_FAILURE(data);
953}
954
955} // namespace wasm
956} // namespace internal
957} // namespace v8