• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
10 namespace v8 {
11 namespace internal {
12 namespace wasm {
13 
14 class WasmModuleVerifyTest : public TestWithZone {
15  public:
DecodeModule(const byte * module_start,const byte * module_end)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 
39 struct LocalTypePair {
40   uint8_t code;
41   LocalType type;
42 } kLocalTypes[] = {{kLocalI32, kAstI32},
43                    {kLocalI64, kAstI64},
44                    {kLocalF32, kAstF32},
45                    {kLocalF64, kAstF64}};
46 
47 
TEST_F(WasmModuleVerifyTest,DecodeEmpty)48 TEST_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 
TEST_F(WasmModuleVerifyTest,OneGlobal)63 TEST_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 
TEST_F(WasmModuleVerifyTest,ZeroGlobals)102 TEST_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 
AppendUint32v(std::vector<byte> & buffer,uint32_t val)112 static 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 
TEST_F(WasmModuleVerifyTest,NGlobals)127 TEST_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 
TEST_F(WasmModuleVerifyTest,GlobalWithInvalidNameOffset)148 TEST_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 
TEST_F(WasmModuleVerifyTest,GlobalWithInvalidMemoryType)164 TEST_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 
TEST_F(WasmModuleVerifyTest,TwoGlobals)180 TEST_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 
TEST_F(WasmModuleVerifyTest,OneSignature)231 TEST_F(WasmModuleVerifyTest, OneSignature) {
232   static const byte data[] = {
233       kDeclSignatures, 1, 0, kLocalVoid  // void -> void
234   };
235   EXPECT_VERIFIES(data);
236 }
237 
238 
TEST_F(WasmModuleVerifyTest,MultipleSignatures)239 TEST_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 
TEST_F(WasmModuleVerifyTest,FunctionWithoutSig)277 TEST_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 
TEST_F(WasmModuleVerifyTest,OneEmptyVoidVoidFunction)299 TEST_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 
TEST_F(WasmModuleVerifyTest,OneFunctionImported)356 TEST_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 
TEST_F(WasmModuleVerifyTest,OneFunctionWithNopBody)388 TEST_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 
TEST_F(WasmModuleVerifyTest,OneFunctionWithNopBody_WithLocals)425 TEST_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 
TEST_F(WasmModuleVerifyTest,OneGlobalOneFunctionWithNopBodyOneDataSegment)465 TEST_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 
TEST_F(WasmModuleVerifyTest,OneDataSegment)532 TEST_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 
TEST_F(WasmModuleVerifyTest,TwoDataSegments)577 TEST_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 
TEST_F(WasmModuleVerifyTest,OneIndirectFunction)647 TEST_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 
TEST_F(WasmModuleVerifyTest,MultipleIndirectFunctions)668 TEST_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 
TEST_F(WasmModuleVerifyTest,IndirectFunctionNoFunctions)694 TEST_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 
TEST_F(WasmModuleVerifyTest,IndirectFunctionInvalidIndex)706 TEST_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 
720 class WasmSignatureDecodeTest : public TestWithZone {};
721 
722 
TEST_F(WasmSignatureDecodeTest,Ok_v_v)723 TEST_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 
TEST_F(WasmSignatureDecodeTest,Ok_t_v)735 TEST_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 
TEST_F(WasmSignatureDecodeTest,Ok_v_t)750 TEST_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 
TEST_F(WasmSignatureDecodeTest,Ok_t_t)765 TEST_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 
TEST_F(WasmSignatureDecodeTest,Ok_i_tt)786 TEST_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 
TEST_F(WasmSignatureDecodeTest,Fail_off_end)808 TEST_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 
TEST_F(WasmSignatureDecodeTest,Fail_invalid_type)823 TEST_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 
TEST_F(WasmSignatureDecodeTest,Fail_invalid_param_type)835 TEST_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 
847 class WasmFunctionVerifyTest : public TestWithZone {};
848 
849 
TEST_F(WasmFunctionVerifyTest,Ok_v_v_empty)850 TEST_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 
TEST_F(WasmModuleVerifyTest,WLLSectionNoLen)883 TEST_F(WasmModuleVerifyTest, WLLSectionNoLen) {
884   const byte data[] = {
885       kDeclWLL,  // section without length.
886   };
887   EXPECT_FAILURE(data);
888 }
889 
890 
TEST_F(WasmModuleVerifyTest,WLLSectionEmpty)891 TEST_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 
TEST_F(WasmModuleVerifyTest,WLLSectionOne)901 TEST_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 
TEST_F(WasmModuleVerifyTest,WLLSectionTen)913 TEST_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 
TEST_F(WasmModuleVerifyTest,WLLSectionOverflow)925 TEST_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 
TEST_F(WasmModuleVerifyTest,WLLSectionUnderflow)935 TEST_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 
TEST_F(WasmModuleVerifyTest,WLLSectionLoop)945 TEST_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
958