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/handles.h"
8#include "src/objects-inl.h"
9#include "src/wasm/module-decoder.h"
10#include "src/wasm/wasm-macro-gen.h"
11#include "src/wasm/wasm-opcodes.h"
12
13namespace v8 {
14namespace internal {
15namespace wasm {
16
17#define EMPTY_FUNCTION(sig_index) 0, SIG_INDEX(sig_index), U16_LE(0)
18#define SIZEOF_EMPTY_FUNCTION ((size_t)5)
19#define EMPTY_BODY 0
20#define SIZEOF_EMPTY_BODY ((size_t)1)
21#define NOP_BODY 2, 0, kExprNop
22#define SIZEOF_NOP_BODY ((size_t)3)
23
24#define SIG_ENTRY_i_i SIG_ENTRY_x_x(kLocalI32, kLocalI32)
25
26#define UNKNOWN_EMPTY_SECTION_NAME 1, '\0'
27#define UNKNOWN_SECTION_NAME 4, 'l', 'u', 'l', 'z'
28
29#define SECTION(NAME, EXTRA_SIZE) WASM_SECTION_##NAME, U32V_1(EXTRA_SIZE)
30
31#define SIGNATURES_SECTION(count, ...) \
32  SECTION(SIGNATURES, 1 + 3 * (count)), U32V_1(count), __VA_ARGS__
33#define FUNCTION_SIGNATURES_SECTION(count, ...) \
34  SECTION(FUNCTION_SIGNATURES, 1 + (count)), U32V_1(count), __VA_ARGS__
35
36#define FOO_STRING 3, 'f', 'o', 'o'
37#define NO_LOCAL_NAMES 0
38
39#define EMPTY_SIGNATURES_SECTION SECTION(SIGNATURES, 1), 0
40#define EMPTY_FUNCTION_SIGNATURES_SECTION SECTION(FUNCTION_SIGNATURES, 1), 0
41#define EMPTY_FUNCTION_BODIES_SECTION SECTION(FUNCTION_BODIES, 1), 0
42#define EMPTY_NAMES_SECTION SECTION(NAMES, 1), 0
43
44#define X1(...) __VA_ARGS__
45#define X2(...) __VA_ARGS__, __VA_ARGS__
46#define X3(...) __VA_ARGS__, __VA_ARGS__, __VA_ARGS__
47#define X4(...) __VA_ARGS__, __VA_ARGS__, __VA_ARGS__, __VA_ARGS__
48
49#define ONE_EMPTY_FUNCTION WASM_SECTION_FUNCTION_SIGNATURES, 1 + 1 * 1, 1, X1(0)
50
51#define TWO_EMPTY_FUNCTIONS \
52  WASM_SECTION_FUNCTION_SIGNATURES, 1 + 2 * 1, 2, X2(0)
53
54#define THREE_EMPTY_FUNCTIONS \
55  WASM_SECTION_FUNCTION_SIGNATURES, 1 + 3 * 1, 3, X3(0)
56
57#define FOUR_EMPTY_FUNCTIONS \
58  WASM_SECTION_FUNCTION_SIGNATURES, 1 + 4 * 1, 4, X4(0)
59
60#define ONE_EMPTY_BODY                                              \
61  WASM_SECTION_FUNCTION_BODIES, 1 + 1 * (1 + SIZEOF_EMPTY_BODY), 1, \
62      X1(SIZEOF_EMPTY_BODY, EMPTY_BODY)
63
64#define TWO_EMPTY_BODIES                                            \
65  WASM_SECTION_FUNCTION_BODIES, 1 + 2 * (1 + SIZEOF_EMPTY_BODY), 2, \
66      X2(SIZEOF_EMPTY_BODY, EMPTY_BODY)
67
68#define THREE_EMPTY_BODIES                                          \
69  WASM_SECTION_FUNCTION_BODIES, 1 + 3 * (1 + SIZEOF_EMPTY_BODY), 3, \
70      X3(SIZEOF_EMPTY_BODY, EMPTY_BODY)
71
72#define FOUR_EMPTY_BODIES                                           \
73  WASM_SECTION_FUNCTION_BODIES, 1 + 4 * (1 + SIZEOF_EMPTY_BODY), 4, \
74      X4(SIZEOF_EMPTY_BODY, EMPTY_BODY)
75
76#define SIGNATURES_SECTION_VOID_VOID \
77  SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v), 1, SIG_ENTRY_v_v
78
79#define EXPECT_VERIFIES(data)                                         \
80  do {                                                                \
81    ModuleResult result = DecodeModule(data, data + arraysize(data)); \
82    EXPECT_TRUE(result.ok());                                         \
83    if (result.val) delete result.val;                                \
84  } while (false)
85
86#define EXPECT_FAILURE_LEN(data, length)                     \
87  do {                                                       \
88    ModuleResult result = DecodeModule(data, data + length); \
89    EXPECT_FALSE(result.ok());                               \
90    if (result.val) delete result.val;                       \
91  } while (false)
92
93#define EXPECT_FAILURE(data) EXPECT_FAILURE_LEN(data, sizeof(data))
94
95#define EXPECT_OFF_END_FAILURE(data, min, max)          \
96  do {                                                  \
97    for (size_t length = min; length < max; length++) { \
98      EXPECT_FAILURE_LEN(data, length);                 \
99    }                                                   \
100  } while (false)
101
102#define EXPECT_OK(result)                \
103  do {                                   \
104    EXPECT_TRUE(result.ok());            \
105    if (!result.ok()) {                  \
106      if (result.val) delete result.val; \
107      return;                            \
108    }                                    \
109  } while (false)
110
111static size_t SizeOfVarInt(size_t value) {
112  size_t size = 0;
113  do {
114    size++;
115    value = value >> 7;
116  } while (value > 0);
117  return size;
118}
119
120struct LocalTypePair {
121  uint8_t code;
122  LocalType type;
123} kLocalTypes[] = {{kLocalI32, kAstI32},
124                   {kLocalI64, kAstI64},
125                   {kLocalF32, kAstF32},
126                   {kLocalF64, kAstF64}};
127
128class WasmModuleVerifyTest : public TestWithIsolateAndZone {
129 public:
130  ModuleResult DecodeModule(const byte* module_start, const byte* module_end) {
131    // Add the WASM magic and version number automatically.
132    size_t size = static_cast<size_t>(module_end - module_start);
133    byte header[] = {WASM_MODULE_HEADER};
134    size_t total = sizeof(header) + size;
135    auto temp = new byte[total];
136    memcpy(temp, header, sizeof(header));
137    memcpy(temp + sizeof(header), module_start, size);
138    ModuleResult result = DecodeWasmModule(isolate(), zone(), temp,
139                                           temp + total, false, kWasmOrigin);
140    delete[] temp;
141    return result;
142  }
143  ModuleResult DecodeModuleNoHeader(const byte* module_start,
144                                    const byte* module_end) {
145    return DecodeWasmModule(isolate(), zone(), module_start, module_end, false,
146                            kWasmOrigin);
147  }
148};
149
150TEST_F(WasmModuleVerifyTest, WrongMagic) {
151  for (uint32_t x = 1; x; x <<= 1) {
152    const byte data[] = {U32_LE(kWasmMagic ^ x), U32_LE(kWasmVersion),
153                         SECTION(END, 0)};
154    ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
155    EXPECT_FALSE(result.ok());
156    if (result.val) delete result.val;
157  }
158}
159
160TEST_F(WasmModuleVerifyTest, WrongVersion) {
161  for (uint32_t x = 1; x; x <<= 1) {
162    const byte data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion ^ x),
163                         SECTION(END, 0)};
164    ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
165    EXPECT_FALSE(result.ok());
166    if (result.val) delete result.val;
167  }
168}
169
170TEST_F(WasmModuleVerifyTest, DecodeEmpty) {
171  static const byte data[] = {SECTION(END, 0)};
172  EXPECT_VERIFIES(data);
173}
174
175TEST_F(WasmModuleVerifyTest, OneGlobal) {
176  static const byte data[] = {
177      SECTION(GLOBALS, 5),  // --
178      1,
179      NAME_LENGTH(1),
180      'g',      // name
181      kMemI32,  // memory type
182      0,        // exported
183  };
184
185  {
186    // Should decode to exactly one global.
187    ModuleResult result = DecodeModule(data, data + arraysize(data));
188    EXPECT_OK(result);
189    EXPECT_EQ(1, result.val->globals.size());
190    EXPECT_EQ(0, result.val->functions.size());
191    EXPECT_EQ(0, result.val->data_segments.size());
192
193    const WasmGlobal* global = &result.val->globals.back();
194
195    EXPECT_EQ(1, global->name_length);
196    EXPECT_EQ(MachineType::Int32(), global->type);
197    EXPECT_EQ(0, global->offset);
198    EXPECT_FALSE(global->exported);
199
200    if (result.val) delete result.val;
201  }
202
203  EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
204}
205
206TEST_F(WasmModuleVerifyTest, Global_invalid_type) {
207  static const byte data[] = {
208      SECTION(GLOBALS, 5),  // --
209      1,
210      NAME_LENGTH(1),
211      'g',  // name
212      64,   // invalid memory type
213      0,    // exported
214  };
215
216  ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
217  EXPECT_FALSE(result.ok());
218  if (result.val) delete result.val;
219}
220
221TEST_F(WasmModuleVerifyTest, ZeroGlobals) {
222  static const byte data[] = {
223      SECTION(GLOBALS, 1),  // --
224      0,                    // declare 0 globals
225  };
226  ModuleResult result = DecodeModule(data, data + arraysize(data));
227  EXPECT_OK(result);
228  if (result.val) delete result.val;
229}
230
231static void AppendUint32v(std::vector<byte>& buffer, uint32_t val) {
232  while (true) {
233    uint32_t next = val >> 7;
234    uint32_t out = val & 0x7f;
235    if (next) {
236      buffer.push_back(static_cast<byte>(0x80 | out));
237      val = next;
238    } else {
239      buffer.push_back(static_cast<byte>(out));
240      break;
241    }
242  }
243}
244
245TEST_F(WasmModuleVerifyTest, NGlobals) {
246  static const byte data[] = {
247      NO_NAME,  // name length
248      kMemI32,  // memory type
249      0,        // exported
250  };
251
252  for (uint32_t i = 0; i < 1000000; i = i * 13 + 1) {
253    std::vector<byte> buffer;
254    size_t size = SizeOfVarInt(i) + i * sizeof(data);
255    const byte globals[] = {WASM_SECTION_GLOBALS, U32V_5(size)};
256    for (size_t g = 0; g != sizeof(globals); ++g) {
257      buffer.push_back(globals[g]);
258    }
259    AppendUint32v(buffer, i);  // Number of globals.
260    for (uint32_t j = 0; j < i; j++) {
261      buffer.insert(buffer.end(), data, data + sizeof(data));
262    }
263
264    ModuleResult result = DecodeModule(&buffer[0], &buffer[0] + buffer.size());
265    EXPECT_OK(result);
266    if (result.val) delete result.val;
267  }
268}
269
270TEST_F(WasmModuleVerifyTest, GlobalWithInvalidNameOffset) {
271  static const byte data[] = {
272      SECTION(GLOBALS, 7),
273      1,        // declare one global
274      NO_NAME,  // name offset
275      33,       // memory type
276      0,        // exported
277  };
278
279  EXPECT_FAILURE(data);
280}
281
282TEST_F(WasmModuleVerifyTest, GlobalWithInvalidMemoryType) {
283  static const byte data[] = {
284      SECTION(GLOBALS, 7),
285      1,        // declare one global
286      NO_NAME,  // name offset
287      33,       // memory type
288      0,        // exported
289  };
290
291  EXPECT_FAILURE(data);
292}
293
294TEST_F(WasmModuleVerifyTest, TwoGlobals) {
295  static const byte data[] = {
296      SECTION(GLOBALS, 7),
297      2,
298      NO_NAME,  // #0: name length
299      kMemF32,  // memory type
300      0,        // exported
301      NO_NAME,  // #1: name length
302      kMemF64,  // memory type
303      1,        // exported
304  };
305
306  {
307    // Should decode to exactly two globals.
308    ModuleResult result = DecodeModule(data, data + arraysize(data));
309    EXPECT_OK(result);
310    EXPECT_EQ(2, result.val->globals.size());
311    EXPECT_EQ(0, result.val->functions.size());
312    EXPECT_EQ(0, result.val->data_segments.size());
313
314    const WasmGlobal* g0 = &result.val->globals[0];
315    const WasmGlobal* g1 = &result.val->globals[1];
316
317    EXPECT_EQ(0, g0->name_length);
318    EXPECT_EQ(MachineType::Float32(), g0->type);
319    EXPECT_EQ(0, g0->offset);
320    EXPECT_FALSE(g0->exported);
321
322    EXPECT_EQ(0, g1->name_length);
323    EXPECT_EQ(MachineType::Float64(), g1->type);
324    EXPECT_EQ(8, g1->offset);
325    EXPECT_TRUE(g1->exported);
326
327    if (result.val) delete result.val;
328  }
329
330  EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
331}
332
333TEST_F(WasmModuleVerifyTest, OneSignature) {
334  {
335    static const byte data[] = {SIGNATURES_SECTION_VOID_VOID};
336    EXPECT_VERIFIES(data);
337  }
338
339  {
340    static const byte data[] = {SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_x_x),
341                                1, SIG_ENTRY_i_i};
342    EXPECT_VERIFIES(data);
343  }
344}
345
346TEST_F(WasmModuleVerifyTest, MultipleSignatures) {
347  static const byte data[] = {
348      SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v + SIZEOF_SIG_ENTRY_x_x +
349                              SIZEOF_SIG_ENTRY_x_xx),   // --
350      3,                                                // --
351      SIG_ENTRY_v_v,                                    // void -> void
352      SIG_ENTRY_x_x(kLocalI32, kLocalF32),              // f32 -> i32
353      SIG_ENTRY_x_xx(kLocalI32, kLocalF64, kLocalF64),  // f64,f64 -> i32
354  };
355
356  ModuleResult result = DecodeModule(data, data + arraysize(data));
357  EXPECT_OK(result);
358  EXPECT_EQ(3, result.val->signatures.size());
359  if (result.val->signatures.size() == 3) {
360    EXPECT_EQ(0, result.val->signatures[0]->return_count());
361    EXPECT_EQ(1, result.val->signatures[1]->return_count());
362    EXPECT_EQ(1, result.val->signatures[2]->return_count());
363
364    EXPECT_EQ(0, result.val->signatures[0]->parameter_count());
365    EXPECT_EQ(1, result.val->signatures[1]->parameter_count());
366    EXPECT_EQ(2, result.val->signatures[2]->parameter_count());
367  }
368  if (result.val) delete result.val;
369
370  EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
371}
372
373TEST_F(WasmModuleVerifyTest, OneDataSegment) {
374  const byte kDataSegmentSourceOffset = 30;
375  const byte data[] = {
376      SECTION(MEMORY, 3),
377      28,
378      28,
379      1,
380      SECTION(DATA_SEGMENTS, 8),
381      1,
382      U32V_3(0x9bbaa),  // dest addr
383      U32V_1(3),        // source size
384      'a',
385      'b',
386      'c'  // data bytes
387  };
388
389  {
390    EXPECT_VERIFIES(data);
391    ModuleResult result = DecodeModule(data, data + arraysize(data));
392    EXPECT_OK(result);
393    EXPECT_EQ(0, result.val->globals.size());
394    EXPECT_EQ(0, result.val->functions.size());
395    EXPECT_EQ(1, result.val->data_segments.size());
396
397    const WasmDataSegment* segment = &result.val->data_segments.back();
398
399    EXPECT_EQ(0x9bbaa, segment->dest_addr);
400    EXPECT_EQ(kDataSegmentSourceOffset, segment->source_offset);
401    EXPECT_EQ(3, segment->source_size);
402    EXPECT_TRUE(segment->init);
403
404    if (result.val) delete result.val;
405  }
406
407  EXPECT_OFF_END_FAILURE(data, 13, sizeof(data));
408}
409
410TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
411  const byte kDataSegment0SourceOffset = 30;
412  const byte kDataSegment1SourceOffset = 30 + 8;
413
414  const byte data[] = {
415      SECTION(MEMORY, 3),
416      28,
417      28,
418      1,
419      SECTION(DATA_SEGMENTS, 23),
420      2,                // segment count
421      U32V_3(0x7ffee),  // #0: dest addr
422      U32V_1(4),        // source size
423      1,
424      2,
425      3,
426      4,                // data bytes
427      U32V_3(0x6ddcc),  // #1: dest addr
428      U32V_1(10),       // source size
429      1,
430      2,
431      3,
432      4,
433      5,
434      6,
435      7,
436      8,
437      9,
438      10  // data bytes
439  };
440
441  {
442    ModuleResult result = DecodeModule(data, data + arraysize(data));
443    EXPECT_OK(result);
444    EXPECT_EQ(0, result.val->globals.size());
445    EXPECT_EQ(0, result.val->functions.size());
446    EXPECT_EQ(2, result.val->data_segments.size());
447
448    const WasmDataSegment* s0 = &result.val->data_segments[0];
449    const WasmDataSegment* s1 = &result.val->data_segments[1];
450
451    EXPECT_EQ(0x7ffee, s0->dest_addr);
452    EXPECT_EQ(kDataSegment0SourceOffset, s0->source_offset);
453    EXPECT_EQ(4, s0->source_size);
454    EXPECT_TRUE(s0->init);
455
456    EXPECT_EQ(0x6ddcc, s1->dest_addr);
457    EXPECT_EQ(kDataSegment1SourceOffset, s1->source_offset);
458    EXPECT_EQ(10, s1->source_size);
459    EXPECT_TRUE(s1->init);
460
461    if (result.val) delete result.val;
462  }
463
464  EXPECT_OFF_END_FAILURE(data, 13, sizeof(data));
465}
466
467TEST_F(WasmModuleVerifyTest, DataSegmentWithInvalidDest) {
468  const int source_size = 3;
469
470  for (byte mem_pages = 1; mem_pages < 16; mem_pages++) {
471    int mem_size = mem_pages * 0x10000;  // 64k pages.
472
473    for (int dest_addr = mem_size - source_size;
474         dest_addr < mem_size + source_size; dest_addr++) {
475      byte data[] = {SECTION(MEMORY, 3),
476                     mem_pages,
477                     mem_pages,
478                     1,
479                     SECTION(DATA_SEGMENTS, 8),
480                     1,
481                     U32V_3(dest_addr),
482                     U32V_1(source_size),
483                     'a',
484                     'b',
485                     'c'};
486
487      if (dest_addr <= (mem_size - source_size)) {
488        EXPECT_VERIFIES(data);
489      } else {
490        EXPECT_FAILURE(data);
491      }
492    }
493  }
494}
495
496TEST_F(WasmModuleVerifyTest, OneIndirectFunction) {
497  static const byte data[] = {
498      // sig#0 -------------------------------------------------------
499      SIGNATURES_SECTION_VOID_VOID,
500      // funcs ------------------------------------------------------
501      ONE_EMPTY_FUNCTION,
502      // indirect table ----------------------------------------------
503      SECTION(FUNCTION_TABLE, 2), 1, U32V_1(0)};
504
505  ModuleResult result = DecodeModule(data, data + arraysize(data));
506  EXPECT_OK(result);
507  if (result.ok()) {
508    EXPECT_EQ(1, result.val->signatures.size());
509    EXPECT_EQ(1, result.val->functions.size());
510    EXPECT_EQ(1, result.val->function_table.size());
511    EXPECT_EQ(0, result.val->function_table[0]);
512  }
513  if (result.val) delete result.val;
514}
515
516TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) {
517  static const byte data[] = {
518      // sig#0 -------------------------------------------------------
519      SECTION(SIGNATURES, 1 + SIZEOF_SIG_ENTRY_v_v + SIZEOF_SIG_ENTRY_v_x),
520      2,                         // --
521      SIG_ENTRY_v_v,             // void -> void
522      SIG_ENTRY_v_x(kLocalI32),  // void -> i32
523      // funcs ------------------------------------------------------
524      FOUR_EMPTY_FUNCTIONS,
525      // indirect table ----------------------------------------------
526      SECTION(FUNCTION_TABLE, 9), 8,
527      U32V_1(0),  // --
528      U32V_1(1),  // --
529      U32V_1(2),  // --
530      U32V_1(3),  // --
531      U32V_1(0),  // --
532      U32V_1(1),  // --
533      U32V_1(2),  // --
534      U32V_1(3),  // --
535      FOUR_EMPTY_BODIES};
536
537  ModuleResult result = DecodeModule(data, data + arraysize(data));
538  EXPECT_OK(result);
539  if (result.ok()) {
540    EXPECT_EQ(2, result.val->signatures.size());
541    EXPECT_EQ(4, result.val->functions.size());
542    EXPECT_EQ(8, result.val->function_table.size());
543    for (int i = 0; i < 8; i++) {
544      EXPECT_EQ(i & 3, result.val->function_table[i]);
545    }
546  }
547  if (result.val) delete result.val;
548}
549
550TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) {
551  static const byte data[] = {
552      // sig#0 -------------------------------------------------------
553      SIGNATURES_SECTION_VOID_VOID,
554      // indirect table ----------------------------------------------
555      SECTION(FUNCTION_TABLE, 3), 1, 0, 0,
556  };
557
558  EXPECT_FAILURE(data);
559}
560
561TEST_F(WasmModuleVerifyTest, IndirectFunctionInvalidIndex) {
562  static const byte data[] = {
563      // sig#0 -------------------------------------------------------
564      SIGNATURES_SECTION_VOID_VOID,
565      // functions ---------------------------------------------------
566      ONE_EMPTY_FUNCTION,
567      // indirect table ----------------------------------------------
568      SECTION(FUNCTION_TABLE, 3), 1, 1, 0,
569  };
570
571  EXPECT_FAILURE(data);
572}
573
574class WasmSignatureDecodeTest : public TestWithZone {};
575
576TEST_F(WasmSignatureDecodeTest, Ok_v_v) {
577  static const byte data[] = {SIG_ENTRY_v_v};
578  base::AccountingAllocator allocator;
579  Zone zone(&allocator);
580  FunctionSig* sig =
581      DecodeWasmSignatureForTesting(&zone, data, data + arraysize(data));
582
583  EXPECT_TRUE(sig != nullptr);
584  EXPECT_EQ(0, sig->parameter_count());
585  EXPECT_EQ(0, sig->return_count());
586}
587
588TEST_F(WasmSignatureDecodeTest, Ok_t_v) {
589  for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
590    LocalTypePair ret_type = kLocalTypes[i];
591    const byte data[] = {SIG_ENTRY_x(ret_type.code)};
592    FunctionSig* sig =
593        DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
594
595    EXPECT_TRUE(sig != nullptr);
596    EXPECT_EQ(0, sig->parameter_count());
597    EXPECT_EQ(1, sig->return_count());
598    EXPECT_EQ(ret_type.type, sig->GetReturn());
599  }
600}
601
602TEST_F(WasmSignatureDecodeTest, Ok_v_t) {
603  for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
604    LocalTypePair param_type = kLocalTypes[i];
605    const byte data[] = {SIG_ENTRY_v_x(param_type.code)};
606    FunctionSig* sig =
607        DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
608
609    EXPECT_TRUE(sig != nullptr);
610    EXPECT_EQ(1, sig->parameter_count());
611    EXPECT_EQ(0, sig->return_count());
612    EXPECT_EQ(param_type.type, sig->GetParam(0));
613  }
614}
615
616TEST_F(WasmSignatureDecodeTest, Ok_t_t) {
617  for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
618    LocalTypePair ret_type = kLocalTypes[i];
619    for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
620      LocalTypePair param_type = kLocalTypes[j];
621      const byte data[] = {SIG_ENTRY_x_x(ret_type.code, param_type.code)};
622      FunctionSig* sig =
623          DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
624
625      EXPECT_TRUE(sig != nullptr);
626      EXPECT_EQ(1, sig->parameter_count());
627      EXPECT_EQ(1, sig->return_count());
628      EXPECT_EQ(param_type.type, sig->GetParam(0));
629      EXPECT_EQ(ret_type.type, sig->GetReturn());
630    }
631  }
632}
633
634TEST_F(WasmSignatureDecodeTest, Ok_i_tt) {
635  for (size_t i = 0; i < arraysize(kLocalTypes); i++) {
636    LocalTypePair p0_type = kLocalTypes[i];
637    for (size_t j = 0; j < arraysize(kLocalTypes); j++) {
638      LocalTypePair p1_type = kLocalTypes[j];
639      const byte data[] = {
640          SIG_ENTRY_x_xx(kLocalI32, p0_type.code, p1_type.code)};
641      FunctionSig* sig =
642          DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
643
644      EXPECT_TRUE(sig != nullptr);
645      EXPECT_EQ(2, sig->parameter_count());
646      EXPECT_EQ(1, sig->return_count());
647      EXPECT_EQ(p0_type.type, sig->GetParam(0));
648      EXPECT_EQ(p1_type.type, sig->GetParam(1));
649    }
650  }
651}
652
653TEST_F(WasmSignatureDecodeTest, Fail_off_end) {
654  byte data[256];
655  for (int p = 0; p <= 255; p = p + 1 + p * 3) {
656    for (int i = 0; i <= p; i++) data[i] = kLocalI32;
657    data[0] = static_cast<byte>(p);
658
659    for (int i = 0; i < p + 1; i++) {
660      // Should fall off the end for all signatures.
661      FunctionSig* sig = DecodeWasmSignatureForTesting(zone(), data, data + i);
662      EXPECT_EQ(nullptr, sig);
663    }
664  }
665}
666
667TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) {
668  byte kInvalidType = 76;
669  for (size_t i = 0; i < SIZEOF_SIG_ENTRY_x_xx; i++) {
670    byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalI32)};
671    data[i] = kInvalidType;
672    FunctionSig* sig =
673        DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
674    EXPECT_EQ(nullptr, sig);
675  }
676}
677
678TEST_F(WasmSignatureDecodeTest, Fail_invalid_ret_type1) {
679  static const byte data[] = {SIG_ENTRY_x_x(kLocalVoid, kLocalI32)};
680  FunctionSig* sig =
681      DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
682  EXPECT_EQ(nullptr, sig);
683}
684
685TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type1) {
686  static const byte data[] = {SIG_ENTRY_x_x(kLocalI32, kLocalVoid)};
687  FunctionSig* sig =
688      DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
689  EXPECT_EQ(nullptr, sig);
690}
691
692TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) {
693  static const byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalVoid)};
694  FunctionSig* sig =
695      DecodeWasmSignatureForTesting(zone(), data, data + arraysize(data));
696  EXPECT_EQ(nullptr, sig);
697}
698
699class WasmFunctionVerifyTest : public TestWithIsolateAndZone {};
700
701TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
702  static const byte data[] = {
703      SIG_ENTRY_v_v,  // signature entry
704      4,              // locals
705      3,
706      kLocalI32,  // --
707      4,
708      kLocalI64,  // --
709      5,
710      kLocalF32,  // --
711      6,
712      kLocalF64,  // --
713      kExprNop    // body
714  };
715
716  FunctionResult result = DecodeWasmFunction(isolate(), zone(), nullptr, data,
717                                             data + arraysize(data));
718  EXPECT_OK(result);
719
720  if (result.val && result.ok()) {
721    WasmFunction* function = result.val;
722    EXPECT_EQ(0, function->sig->parameter_count());
723    EXPECT_EQ(0, function->sig->return_count());
724    EXPECT_EQ(0, function->name_offset);
725    EXPECT_EQ(SIZEOF_SIG_ENTRY_v_v, function->code_start_offset);
726    EXPECT_EQ(arraysize(data), function->code_end_offset);
727    // TODO(titzer): verify encoding of local declarations
728  }
729
730  if (result.val) delete result.val;
731}
732
733TEST_F(WasmModuleVerifyTest, SectionWithoutNameLength) {
734  const byte data[] = {1};
735  EXPECT_FAILURE(data);
736}
737
738TEST_F(WasmModuleVerifyTest, TheLoneliestOfValidModulesTheTrulyEmptyOne) {
739  const byte data[] = {
740      0,  // Empty section name.
741          // No section name, no content, nothing but sadness.
742      0,  // No section content.
743  };
744  EXPECT_VERIFIES(data);
745}
746
747TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionEmpty) {
748  const byte data[] = {
749      UNKNOWN_SECTION_NAME, 0,
750  };
751  EXPECT_VERIFIES(data);
752}
753
754TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionNonEmpty) {
755  const byte data[] = {
756      UNKNOWN_SECTION_NAME,
757      5,  // section size
758      0xff,
759      0xff,
760      0xff,
761      0xff,
762      0xff,  // section data
763  };
764  EXPECT_VERIFIES(data);
765}
766
767TEST_F(WasmModuleVerifyTest, SignatureFollowedByEmptyUnknownSection) {
768  const byte data[] = {
769      // signatures
770      SIGNATURES_SECTION_VOID_VOID,
771      // -----------------------------------------------------------
772      UNKNOWN_SECTION_NAME,
773      0  // empty section
774  };
775  EXPECT_VERIFIES(data);
776}
777
778TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSection) {
779  const byte data[] = {
780      // signatures
781      SIGNATURES_SECTION_VOID_VOID,
782      // -----------------------------------------------------------
783      UNKNOWN_SECTION_NAME,
784      5,  // section size
785      0xff, 0xff, 0xff, 0xff, 0xff,
786  };
787  EXPECT_VERIFIES(data);
788}
789
790TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSectionWithLongLEB) {
791  const byte data[] = {
792      // signatures
793      SIGNATURES_SECTION_VOID_VOID,
794      // -----------------------------------------------------------
795      UNKNOWN_SECTION_NAME, 0x81, 0x80, 0x80, 0x80,
796      0x00,  // section size: 1 but in a 5-byte LEB
797      0,
798  };
799  EXPECT_VERIFIES(data);
800}
801
802TEST_F(WasmModuleVerifyTest, UnknownSectionOverflow) {
803  static const byte data[] = {
804      UNKNOWN_EMPTY_SECTION_NAME,
805      9,  // section size
806      1,
807      2,
808      3,
809      4,
810      5,
811      6,
812      7,
813      8,
814      9,
815      10,  // 10 byte section
816  };
817  EXPECT_FAILURE(data);
818}
819
820TEST_F(WasmModuleVerifyTest, UnknownSectionUnderflow) {
821  static const byte data[] = {
822      UNKNOWN_EMPTY_SECTION_NAME,
823      0xff,
824      0xff,
825      0xff,
826      0xff,
827      0x0f,  // Section size LEB128 0xffffffff
828      1,
829      2,
830      3,
831      4,  // 4 byte section
832  };
833  EXPECT_FAILURE(data);
834}
835
836TEST_F(WasmModuleVerifyTest, UnknownSectionLoop) {
837  // Would infinite loop decoding if wrapping and allowed.
838  static const byte data[] = {
839      UNKNOWN_EMPTY_SECTION_NAME,
840      1,
841      2,
842      3,
843      4,  // 4 byte section
844      0xfa,
845      0xff,
846      0xff,
847      0xff,
848      0x0f,  // Section size LEB128 0xfffffffa
849  };
850  EXPECT_FAILURE(data);
851}
852
853TEST_F(WasmModuleVerifyTest, UnknownSectionSkipped) {
854  static const byte data[] = {
855      UNKNOWN_EMPTY_SECTION_NAME,
856      1,  // section size
857      0,  // one byte section
858      SECTION(GLOBALS, 4),
859      1,
860      0,        // name length
861      kMemI32,  // memory type
862      0,        // exported
863  };
864  ModuleResult result = DecodeModule(data, data + arraysize(data));
865  EXPECT_OK(result);
866
867  EXPECT_EQ(1, result.val->globals.size());
868  EXPECT_EQ(0, result.val->functions.size());
869  EXPECT_EQ(0, result.val->data_segments.size());
870
871  const WasmGlobal* global = &result.val->globals.back();
872
873  EXPECT_EQ(0, global->name_length);
874  EXPECT_EQ(MachineType::Int32(), global->type);
875  EXPECT_EQ(0, global->offset);
876  EXPECT_FALSE(global->exported);
877
878  if (result.val) delete result.val;
879}
880
881TEST_F(WasmModuleVerifyTest, ImportTable_empty) {
882  static const byte data[] = {SECTION(SIGNATURES, 1), 0,
883                              SECTION(IMPORT_TABLE, 1), 0};
884  EXPECT_VERIFIES(data);
885}
886
887TEST_F(WasmModuleVerifyTest, ImportTable_nosigs1) {
888  static const byte data[] = {SECTION(IMPORT_TABLE, 1), 0};
889  EXPECT_VERIFIES(data);
890}
891
892TEST_F(WasmModuleVerifyTest, ImportTable_nosigs2) {
893  static const byte data[] = {
894      SECTION(IMPORT_TABLE, 6), 1,    // sig table
895      IMPORT_SIG_INDEX(0),            // sig index
896      NAME_LENGTH(1),           'm',  // module name
897      NAME_LENGTH(1),           'f',  // function name
898  };
899  EXPECT_FAILURE(data);
900}
901
902TEST_F(WasmModuleVerifyTest, ImportTable_invalid_sig) {
903  static const byte data[] = {
904      SECTION(SIGNATURES, 1),   0,    // --
905      SECTION(IMPORT_TABLE, 6), 1,    // --
906      IMPORT_SIG_INDEX(0),            // sig index
907      NAME_LENGTH(1),           'm',  // module name
908      NAME_LENGTH(1),           'f',  // function name
909  };
910  EXPECT_FAILURE(data);
911}
912
913TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
914  static const byte data[] = {
915      // signatures
916      SIGNATURES_SECTION_VOID_VOID,
917      SECTION(IMPORT_TABLE, 6),
918      1,                    // --
919      IMPORT_SIG_INDEX(0),  // sig index
920      NAME_LENGTH(1),
921      'm',  // module name
922      NAME_LENGTH(1),
923      'f',  // function name
924  };
925  EXPECT_VERIFIES(data);
926}
927
928TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) {
929  static const byte data[] = {
930      // signatures
931      SIGNATURES_SECTION_VOID_VOID,
932      SECTION(IMPORT_TABLE, 6),
933      1,                    // --
934      IMPORT_SIG_INDEX(0),  // sig index
935      NO_NAME,              // module name
936      NAME_LENGTH(1),
937      'f'  // function name
938  };
939  EXPECT_FAILURE(data);
940}
941
942TEST_F(WasmModuleVerifyTest, ImportTable_off_end) {
943  static const byte data[] = {
944      // signatures
945      SIGNATURES_SECTION_VOID_VOID,
946      SECTION(IMPORT_TABLE, 6),
947      1,
948      IMPORT_SIG_INDEX(0),  // sig index
949      NAME_LENGTH(1),
950      'm',  // module name
951      NAME_LENGTH(1),
952      'f',  // function name
953  };
954
955  EXPECT_OFF_END_FAILURE(data, 16, sizeof(data));
956}
957
958TEST_F(WasmModuleVerifyTest, ExportTable_empty1) {
959  static const byte data[] = {// signatures
960                              SIGNATURES_SECTION_VOID_VOID, ONE_EMPTY_FUNCTION,
961                              SECTION(EXPORT_TABLE, 1),
962                              0,  // --
963                              ONE_EMPTY_BODY};
964
965  ModuleResult result = DecodeModule(data, data + arraysize(data));
966  EXPECT_OK(result);
967
968  EXPECT_EQ(1, result.val->functions.size());
969  EXPECT_EQ(0, result.val->export_table.size());
970
971  if (result.val) delete result.val;
972}
973
974TEST_F(WasmModuleVerifyTest, ExportTable_empty2) {
975  static const byte data[] = {
976      SECTION(SIGNATURES, 1), 0, SECTION(EXPORT_TABLE, 1), 0  // --
977  };
978  // TODO(titzer): current behavior treats empty functions section as missing.
979  EXPECT_FAILURE(data);
980}
981
982TEST_F(WasmModuleVerifyTest, ExportTable_NoFunctions1) {
983  static const byte data[] = {
984      SECTION(SIGNATURES, 1), 0, SECTION(EXPORT_TABLE, 1), 0  // --
985  };
986  EXPECT_FAILURE(data);
987}
988
989TEST_F(WasmModuleVerifyTest, ExportTable_NoFunctions2) {
990  static const byte data[] = {SECTION(EXPORT_TABLE, 1), 0};
991  EXPECT_FAILURE(data);
992}
993
994TEST_F(WasmModuleVerifyTest, ExportTableOne) {
995  static const byte data[] = {// signatures
996                              SIGNATURES_SECTION_VOID_VOID,
997                              ONE_EMPTY_FUNCTION,
998                              SECTION(EXPORT_TABLE, 3),
999                              1,              // exports
1000                              FUNC_INDEX(0),  // --
1001                              NO_NAME,        // --
1002                              ONE_EMPTY_BODY};
1003  ModuleResult result = DecodeModule(data, data + arraysize(data));
1004  EXPECT_OK(result);
1005
1006  EXPECT_EQ(1, result.val->functions.size());
1007  EXPECT_EQ(1, result.val->export_table.size());
1008
1009  if (result.val) delete result.val;
1010}
1011
1012TEST_F(WasmModuleVerifyTest, ExportTableTwo) {
1013  static const byte data[] = {// signatures
1014                              SIGNATURES_SECTION_VOID_VOID,
1015                              ONE_EMPTY_FUNCTION,
1016                              SECTION(EXPORT_TABLE, 12),
1017                              2,              // exports
1018                              FUNC_INDEX(0),  // --
1019                              NAME_LENGTH(4),
1020                              'n',
1021                              'a',
1022                              'm',
1023                              'e',            // --
1024                              FUNC_INDEX(0),  // --
1025                              NAME_LENGTH(3),
1026                              'n',
1027                              'o',
1028                              'm',  // --
1029                              ONE_EMPTY_BODY};
1030
1031  ModuleResult result = DecodeModule(data, data + arraysize(data));
1032  EXPECT_OK(result);
1033
1034  EXPECT_EQ(1, result.val->functions.size());
1035  EXPECT_EQ(2, result.val->export_table.size());
1036
1037  if (result.val) delete result.val;
1038}
1039
1040TEST_F(WasmModuleVerifyTest, ExportTableThree) {
1041  static const byte data[] = {// signatures
1042                              SIGNATURES_SECTION_VOID_VOID,
1043                              THREE_EMPTY_FUNCTIONS,
1044                              SECTION(EXPORT_TABLE, 10),
1045                              3,              // exports
1046                              FUNC_INDEX(0),  // --
1047                              NAME_LENGTH(1),
1048                              'a',            // --
1049                              FUNC_INDEX(1),  // --
1050                              NAME_LENGTH(1),
1051                              'b',            // --
1052                              FUNC_INDEX(2),  // --
1053                              NAME_LENGTH(1),
1054                              'c',  // --
1055                              THREE_EMPTY_BODIES};
1056  ModuleResult result = DecodeModule(data, data + arraysize(data));
1057  EXPECT_OK(result);
1058
1059  EXPECT_EQ(3, result.val->functions.size());
1060  EXPECT_EQ(3, result.val->export_table.size());
1061
1062  if (result.val) delete result.val;
1063}
1064
1065TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) {
1066  for (int i = 0; i < 6; i++) {
1067    const byte data[] = {// signatures
1068                         SIGNATURES_SECTION_VOID_VOID,
1069                         THREE_EMPTY_FUNCTIONS,
1070                         SECTION(EXPORT_TABLE, 5),
1071                         1,              // exports
1072                         FUNC_INDEX(i),  // --
1073                         NAME_LENGTH(2),
1074                         'e',
1075                         'x',  // --
1076                         THREE_EMPTY_BODIES};
1077
1078    if (i < 3) {
1079      EXPECT_VERIFIES(data);
1080    } else {
1081      EXPECT_FAILURE(data);
1082    }
1083  }
1084}
1085
1086TEST_F(WasmModuleVerifyTest, ExportTableOne_off_end) {
1087  static const byte data[] = {
1088      // signatures
1089      SIGNATURES_SECTION_VOID_VOID,
1090      ONE_EMPTY_FUNCTION,
1091      SECTION(EXPORT_TABLE, 1 + 6),
1092      1,              // exports
1093      FUNC_INDEX(0),  // --
1094      NO_NAME         // --
1095  };
1096
1097  for (int length = 33; length < sizeof(data); length++) {
1098    ModuleResult result = DecodeModule(data, data + length);
1099    EXPECT_FALSE(result.ok());
1100    if (result.val) delete result.val;
1101  }
1102}
1103
1104TEST_F(WasmModuleVerifyTest, FunctionSignatures_empty) {
1105  static const byte data[] = {
1106      SECTION(SIGNATURES, 1), 0,          // --
1107      SECTION(FUNCTION_SIGNATURES, 1), 0  // --
1108  };                                      // --
1109  EXPECT_VERIFIES(data);
1110}
1111
1112TEST_F(WasmModuleVerifyTest, FunctionSignatures_one) {
1113  static const byte data[] = {
1114      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),  // --
1115      FUNCTION_SIGNATURES_SECTION(1, 0)      // --
1116  };
1117  EXPECT_VERIFIES(data);
1118}
1119
1120TEST_F(WasmModuleVerifyTest, FunctionBodies_empty) {
1121  static const byte data[] = {
1122      EMPTY_SIGNATURES_SECTION,           // --
1123      EMPTY_FUNCTION_SIGNATURES_SECTION,  // --
1124      EMPTY_FUNCTION_BODIES_SECTION       // --
1125  };
1126  EXPECT_VERIFIES(data);
1127}
1128
1129TEST_F(WasmModuleVerifyTest, FunctionBodies_one_empty) {
1130  static const byte data[] = {
1131      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),                           // --
1132      FUNCTION_SIGNATURES_SECTION(1, 0),                              // --
1133      SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY), 1, EMPTY_BODY  // --
1134  };
1135  EXPECT_VERIFIES(data);
1136}
1137
1138TEST_F(WasmModuleVerifyTest, FunctionBodies_one_nop) {
1139  static const byte data[] = {
1140      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),                       // --
1141      FUNCTION_SIGNATURES_SECTION(1, 0),                          // --
1142      SECTION(FUNCTION_BODIES, 1 + SIZEOF_NOP_BODY), 1, NOP_BODY  // --
1143  };
1144  EXPECT_VERIFIES(data);
1145}
1146
1147TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch1) {
1148  static const byte data[] = {
1149      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),                // --
1150      FUNCTION_SIGNATURES_SECTION(2, 0, 0),                // --
1151      SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY), 1,  // --
1152      EMPTY_BODY                                           // --
1153  };
1154  EXPECT_FAILURE(data);
1155}
1156
1157TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch2) {
1158  static const byte data[] = {
1159      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),               // --
1160      FUNCTION_SIGNATURES_SECTION(1, 0),                  // --
1161      SECTION(FUNCTION_BODIES, 1 + 2 * SIZEOF_NOP_BODY),  // --
1162      2,                                                  // --
1163      NOP_BODY,                                           // --
1164      NOP_BODY                                            // --
1165  };
1166  EXPECT_FAILURE(data);
1167}
1168
1169TEST_F(WasmModuleVerifyTest, Names_empty) {
1170  static const byte data[] = {
1171      EMPTY_SIGNATURES_SECTION, EMPTY_FUNCTION_SIGNATURES_SECTION,
1172      EMPTY_FUNCTION_BODIES_SECTION, EMPTY_NAMES_SECTION};
1173  EXPECT_VERIFIES(data);
1174}
1175
1176TEST_F(WasmModuleVerifyTest, Names_one_empty) {
1177  static const byte data[] = {
1178      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),  // --
1179      FUNCTION_SIGNATURES_SECTION(1, 0),     // --
1180      SECTION(FUNCTION_BODIES, 1 + SIZEOF_EMPTY_BODY),
1181      1,
1182      EMPTY_BODY,  // --
1183      SECTION(NAMES, 1 + 5),
1184      1,
1185      FOO_STRING,
1186      NO_LOCAL_NAMES  // --
1187  };
1188  EXPECT_VERIFIES(data);
1189}
1190
1191TEST_F(WasmModuleVerifyTest, Names_two_empty) {
1192  static const byte data[] = {
1193      SIGNATURES_SECTION(1, SIG_ENTRY_v_v),                 // --
1194      FUNCTION_SIGNATURES_SECTION(2, 0, 0),                 // --
1195      SECTION(FUNCTION_BODIES, 1 + 2 * SIZEOF_EMPTY_BODY),  // --
1196      2,
1197      EMPTY_BODY,
1198      EMPTY_BODY,  // --
1199      SECTION(NAMES, 1 + 10),
1200      2,  // --
1201      FOO_STRING,
1202      NO_LOCAL_NAMES,  // --
1203      FOO_STRING,
1204      NO_LOCAL_NAMES,  // --
1205  };
1206  EXPECT_VERIFIES(data);
1207}
1208
1209}  // namespace wasm
1210}  // namespace internal
1211}  // namespace v8
1212