module-decoder-unittest.cc 146 KB
Newer Older
1 2 3 4
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "src/wasm/module-decoder.h"
6

7
#include "src/handles/handles.h"
8
#include "src/objects/objects-inl.h"
9
#include "src/wasm/branch-hint-map.h"
10
#include "src/wasm/wasm-engine.h"
11
#include "src/wasm/wasm-features.h"
12
#include "src/wasm/wasm-limits.h"
13
#include "src/wasm/wasm-opcodes.h"
14
#include "test/common/wasm/flag-utils.h"
15
#include "test/common/wasm/wasm-macro-gen.h"
16
#include "test/unittests/test-utils.h"
17 18 19
#include "testing/gmock-support.h"

using testing::HasSubstr;
20 21 22 23

namespace v8 {
namespace internal {
namespace wasm {
24
namespace module_decoder_unittest {
25

26 27 28 29 30 31 32 33
#define WASM_INIT_EXPR_I32V_1(val) WASM_I32V_1(val), kExprEnd
#define WASM_INIT_EXPR_I32V_2(val) WASM_I32V_2(val), kExprEnd
#define WASM_INIT_EXPR_I32V_3(val) WASM_I32V_3(val), kExprEnd
#define WASM_INIT_EXPR_I32V_4(val) WASM_I32V_4(val), kExprEnd
#define WASM_INIT_EXPR_I32V_5(val) WASM_I32V_5(val), kExprEnd
#define WASM_INIT_EXPR_F32(val) WASM_F32(val), kExprEnd
#define WASM_INIT_EXPR_I64(val) WASM_I64(val), kExprEnd
#define WASM_INIT_EXPR_F64(val) WASM_F64(val), kExprEnd
34 35
#define WASM_INIT_EXPR_EXTERN_REF_NULL WASM_REF_NULL(kExternRefCode), kExprEnd
#define WASM_INIT_EXPR_FUNC_REF_NULL WASM_REF_NULL(kFuncRefCode), kExprEnd
36
#define WASM_INIT_EXPR_REF_FUNC(val) WASM_REF_FUNC(val), kExprEnd
37
#define WASM_INIT_EXPR_GLOBAL(index) WASM_GLOBAL_GET(index), kExprEnd
38 39
#define WASM_INIT_EXPR_STRUCT_NEW(index, ...) \
  WASM_STRUCT_NEW_WITH_RTT(index, __VA_ARGS__), kExprEnd
40 41
#define WASM_INIT_EXPR_ARRAY_INIT(index, length, ...) \
  WASM_ARRAY_INIT(index, length, __VA_ARGS__), kExprEnd
42
#define WASM_INIT_EXPR_RTT_CANON(index) WASM_RTT_CANON(index), kExprEnd
43

44
#define REF_NULL_ELEMENT kExprRefNull, kFuncRefCode, kExprEnd
45 46
#define REF_FUNC_ELEMENT(v) kExprRefFunc, U32V_1(v), kExprEnd

47 48
#define EMPTY_BODY 0
#define NOP_BODY 2, 0, kExprNop
49

50
#define SIG_ENTRY_i_i SIG_ENTRY_x_x(kI32Code, kI32Code)
51

52
#define UNKNOWN_SECTION(size) 0, U32V_1(size + 5), ADD_COUNT('l', 'u', 'l', 'z')
53 54
#define TYPE_SECTION(count, ...) SECTION(Type, U32V_1(count), __VA_ARGS__)
#define FUNCTION_SECTION(count, ...) \
55
  SECTION(Function, U32V_1(count), __VA_ARGS__)
56

57
#define FOO_STRING ADD_COUNT('f', 'o', 'o')
58 59
#define NO_LOCAL_NAMES 0

60 61
#define EMPTY_TYPE_SECTION SECTION(Type, ENTRY_COUNT(0))
#define EMPTY_FUNCTION_SECTION SECTION(Function, ENTRY_COUNT(0))
62 63
#define EMPTY_FUNCTION_BODIES_SECTION SECTION(Code, ENTRY_COUNT(0))
#define SECTION_NAMES(...) \
64
  SECTION(Unknown, ADD_COUNT('n', 'a', 'm', 'e'), ##__VA_ARGS__)
65
#define EMPTY_NAMES_SECTION SECTION_NAMES()
66 67 68 69 70
#define SECTION_SRC_MAP(...)                                               \
  SECTION(Unknown,                                                         \
          ADD_COUNT('s', 'o', 'u', 'r', 'c', 'e', 'M', 'a', 'p', 'p', 'i', \
                    'n', 'g', 'U', 'R', 'L'),                              \
          ADD_COUNT(__VA_ARGS__))
71 72 73 74 75
#define SECTION_COMPILATION_HINTS(...)                                     \
  SECTION(Unknown,                                                         \
          ADD_COUNT('c', 'o', 'm', 'p', 'i', 'l', 'a', 't', 'i', 'o', 'n', \
                    'H', 'i', 'n', 't', 's'),                              \
          ADD_COUNT(__VA_ARGS__))
76

77 78 79 80 81
#define SECTION_BRANCH_HINTS(...)                                           \
  SECTION(Unknown,                                                          \
          ADD_COUNT('b', 'r', 'a', 'n', 'c', 'h', 'H', 'i', 'n', 't', 's'), \
          __VA_ARGS__)

82 83 84 85
#define FAIL_IF_NO_EXPERIMENTAL_EH(data)                                 \
  do {                                                                   \
    ModuleResult result = DecodeModule((data), (data) + sizeof((data))); \
    EXPECT_FALSE(result.ok());                                           \
86
  } while (false)
87

88 89 90 91 92
#define X1(...) __VA_ARGS__
#define X2(...) __VA_ARGS__, __VA_ARGS__
#define X3(...) __VA_ARGS__, __VA_ARGS__, __VA_ARGS__
#define X4(...) __VA_ARGS__, __VA_ARGS__, __VA_ARGS__, __VA_ARGS__

93
#define ONE_EMPTY_FUNCTION(sig_index) \
94
  SECTION(Function, ENTRY_COUNT(1), X1(sig_index))
95

96
#define TWO_EMPTY_FUNCTIONS(sig_index) \
97
  SECTION(Function, ENTRY_COUNT(2), X2(sig_index))
98

99
#define THREE_EMPTY_FUNCTIONS(sig_index) \
100
  SECTION(Function, ENTRY_COUNT(3), X3(sig_index))
101

102
#define FOUR_EMPTY_FUNCTIONS(sig_index) \
103
  SECTION(Function, ENTRY_COUNT(4), X4(sig_index))
104

105 106 107 108
#define ONE_EMPTY_BODY SECTION(Code, ENTRY_COUNT(1), X1(EMPTY_BODY))
#define TWO_EMPTY_BODIES SECTION(Code, ENTRY_COUNT(2), X2(EMPTY_BODY))
#define THREE_EMPTY_BODIES SECTION(Code, ENTRY_COUNT(3), X3(EMPTY_BODY))
#define FOUR_EMPTY_BODIES SECTION(Code, ENTRY_COUNT(4), X4(EMPTY_BODY))
109

110
#define TYPE_SECTION_ONE_SIG_VOID_VOID \
111
  SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_v_v)
112 113

#define LINEAR_MEMORY_INDEX_0 0
titzer's avatar
titzer committed
114

115 116
#define EXCEPTION_ENTRY(sig_index) U32V_1(kExceptionAttribute), sig_index

117 118
#define FIELD_COUNT(count) U32V_1(count)
#define STRUCT_FIELD(type, mutability) type, (mutability ? 1 : 0)
119 120
#define WASM_REF(index) kRefCode, index
#define WASM_OPT_REF(index) kOptRefCode, index
121 122 123 124 125
#define WASM_STRUCT_DEF(...) kWasmStructTypeCode, __VA_ARGS__
#define WASM_ARRAY_DEF(type, mutability) \
  kWasmArrayTypeCode, type, (mutability ? 1 : 0)
#define WASM_FUNCTION_DEF(...) kWasmFunctionTypeCode, __VA_ARGS__

126 127 128
#define EXPECT_VERIFIES(data)                                      \
  do {                                                             \
    ModuleResult result = DecodeModule(data, data + sizeof(data)); \
129
    EXPECT_OK(result);                                             \
130 131
  } while (false)

132 133 134 135
#define EXPECT_FAILURE_LEN(data, length)                     \
  do {                                                       \
    ModuleResult result = DecodeModule(data, data + length); \
    EXPECT_FALSE(result.ok());                               \
136 137
  } while (false)

138 139
#define EXPECT_FAILURE(data) EXPECT_FAILURE_LEN(data, sizeof(data))

140 141 142 143
#define EXPECT_FAILURE_WITH_MSG(data, msg)                         \
  do {                                                             \
    ModuleResult result = DecodeModule(data, data + sizeof(data)); \
    EXPECT_FALSE(result.ok());                                     \
144 145 146
    if (!result.ok()) {                                            \
      EXPECT_THAT(result.error().message(), HasSubstr(msg));       \
    }                                                              \
147 148
  } while (false)

149 150 151 152 153 154
#define EXPECT_OFF_END_FAILURE(data, min)                           \
  do {                                                              \
    STATIC_ASSERT(min < arraysize(data));                           \
    for (size_t length = min; length < arraysize(data); length++) { \
      EXPECT_FAILURE_LEN(data, length);                             \
    }                                                               \
155
  } while (false)
156

157 158 159 160 161 162
#define EXPECT_OK(result)                                        \
  do {                                                           \
    if (!result.ok()) {                                          \
      GTEST_NONFATAL_FAILURE_(result.error().message().c_str()); \
      return;                                                    \
    }                                                            \
163 164
  } while (false)

165 166 167 168
#define EXPECT_NOT_OK(result, msg)                         \
  do {                                                     \
    EXPECT_FALSE(result.ok());                             \
    EXPECT_THAT(result.error().message(), HasSubstr(msg)); \
169 170
  } while (false)

171 172 173 174 175 176 177 178 179
static size_t SizeOfVarInt(size_t value) {
  size_t size = 0;
  do {
    size++;
    value = value >> 7;
  } while (value > 0);
  return size;
}

180
struct ValueTypePair {
181
  uint8_t code;
182
  ValueType type;
183
} kValueTypes[] = {
184 185 186 187 188 189
    {kI32Code, kWasmI32},              // --
    {kI64Code, kWasmI64},              // --
    {kF32Code, kWasmF32},              // --
    {kF64Code, kWasmF64},              // --
    {kFuncRefCode, kWasmFuncRef},      // --
    {kExternRefCode, kWasmExternRef},  // --
190
};
191

192
class WasmModuleVerifyTest : public TestWithIsolateAndZone {
193
 public:
194
  WasmFeatures enabled_features_ = WasmFeatures::None();
195

196
  ModuleResult DecodeModule(const byte* module_start, const byte* module_end) {
197
    // Add the wasm magic and version number automatically.
198 199 200 201 202
    size_t size = static_cast<size_t>(module_end - module_start);
    byte header[] = {WASM_MODULE_HEADER};
    size_t total = sizeof(header) + size;
    auto temp = new byte[total];
    memcpy(temp, header, sizeof(header));
203 204 205
    if (size > 0) {
      memcpy(temp + sizeof(header), module_start, size);
    }
206 207
    ModuleResult result = DecodeWasmModule(
        enabled_features_, temp, temp + total, false, kWasmOrigin,
208 209 210
        isolate()->counters(), isolate()->metrics_recorder(),
        v8::metrics::Recorder::ContextId::Empty(), DecodingMethod::kSync,
        isolate()->wasm_engine()->allocator());
211 212 213 214 215
    delete[] temp;
    return result;
  }
  ModuleResult DecodeModuleNoHeader(const byte* module_start,
                                    const byte* module_end) {
216 217 218 219 220
    return DecodeWasmModule(
        enabled_features_, module_start, module_end, false, kWasmOrigin,
        isolate()->counters(), isolate()->metrics_recorder(),
        v8::metrics::Recorder::ContextId::Empty(), DecodingMethod::kSync,
        isolate()->wasm_engine()->allocator());
221 222 223
  }
};

224 225
TEST_F(WasmModuleVerifyTest, WrongMagic) {
  for (uint32_t x = 1; x; x <<= 1) {
226
    const byte data[] = {U32_LE(kWasmMagic ^ x), U32_LE(kWasmVersion)};
227 228
    ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
    EXPECT_FALSE(result.ok());
229
  }
230 231 232 233
}

TEST_F(WasmModuleVerifyTest, WrongVersion) {
  for (uint32_t x = 1; x; x <<= 1) {
234
    const byte data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion ^ x)};
235 236
    ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
    EXPECT_FALSE(result.ok());
237 238 239
  }
}

240 241 242 243 244 245 246
TEST_F(WasmModuleVerifyTest, WrongSection) {
  constexpr byte kInvalidSection = 0x1c;
  const byte data[] = {kInvalidSection, 0};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_FALSE(result.ok());
}

247
TEST_F(WasmModuleVerifyTest, DecodeEmpty) {
248
  ModuleResult result = DecodeModule(nullptr, nullptr);
249
  EXPECT_TRUE(result.ok());
250
}
251 252

TEST_F(WasmModuleVerifyTest, OneGlobal) {
253
  static const byte data[] = {
254 255
      SECTION(Global,                     // --
              ENTRY_COUNT(1),             // --
256
              kI32Code,                   // local type
257 258
              0,                          // immutable
              WASM_INIT_EXPR_I32V_1(13))  // init
259 260 261 262
  };

  {
    // Should decode to exactly one global.
263
    ModuleResult result = DecodeModule(data, data + sizeof(data));
264
    EXPECT_OK(result);
265 266 267
    EXPECT_EQ(1u, result.value()->globals.size());
    EXPECT_EQ(0u, result.value()->functions.size());
    EXPECT_EQ(0u, result.value()->data_segments.size());
268

269
    const WasmGlobal* global = &result.value()->globals.back();
270

271
    EXPECT_EQ(kWasmI32, global->type);
272
    EXPECT_EQ(0u, global->offset);
273
    EXPECT_FALSE(global->mutability);
274 275
    EXPECT_EQ(WasmInitExpr::kI32Const, global->init.kind());
    EXPECT_EQ(13, global->init.immediate().i32_const);
276 277
  }

278
  EXPECT_OFF_END_FAILURE(data, 1);
279 280
}

281 282
TEST_F(WasmModuleVerifyTest, S128Global) {
  WASM_FEATURE_SCOPE(simd);
283 284
  std::array<uint8_t, kSimd128Size> v = {1, 2,  3,  4,  5,  6,  7, 8,
                                         9, 10, 11, 12, 13, 14, 15};
285 286
  static const byte data[] = {SECTION(Global,          // --
                                      ENTRY_COUNT(1),  // --
287
                                      kS128Code,       // memory type
288
                                      0,               // immutable
289
                                      WASM_SIMD_CONSTANT(v.data()), kExprEnd)};
290 291 292 293 294 295 296
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
  const WasmGlobal* global = &result.value()->globals.back();
  EXPECT_EQ(kWasmS128, global->type);
  EXPECT_EQ(0u, global->offset);
  EXPECT_FALSE(global->mutability);
  EXPECT_EQ(WasmInitExpr::kS128Const, global->init.kind());
297
  EXPECT_EQ(global->init.immediate().s128_const, v);
298 299
}

300 301
TEST_F(WasmModuleVerifyTest, ExternRefGlobal) {
  WASM_FEATURE_SCOPE(reftypes);
302
  static const byte data[] = {
303
      // sig#0 ---------------------------------------------------------------
304
      TYPE_SECTION_ONE_SIG_VOID_VOID,
305 306
      // funcs ---------------------------------------------------------------
      TWO_EMPTY_FUNCTIONS(SIG_INDEX(0)),
307 308
      SECTION(Global,                          // --
              ENTRY_COUNT(2),                  // --
309
              kExternRefCode,                  // local type
310 311
              0,                               // immutable
              WASM_INIT_EXPR_EXTERN_REF_NULL,  // init
312
              kFuncRefCode,                    // local type
313 314 315 316 317 318 319 320 321
              0,                               // immutable
              WASM_INIT_EXPR_REF_FUNC(1)),     // init
      SECTION(Element,                         // section name
              ENTRY_COUNT(2),                  // entry count
              DECLARATIVE,                     // flags 0
              kExternalFunction,               // type
              ENTRY_COUNT(1),                  // func entry count
              FUNC_INDEX(0),                   // func index
              DECLARATIVE_WITH_ELEMENTS,       // flags 1
322
              kFuncRefCode,                    // local type
323 324
              ENTRY_COUNT(1),                  // func ref count
              REF_FUNC_ELEMENT(1)),            // func ref
325
      TWO_EMPTY_BODIES};
326 327

  {
328
    // Should decode to two globals.
329 330
    ModuleResult result = DecodeModule(data, data + sizeof(data));
    EXPECT_OK(result);
331 332
    EXPECT_EQ(2u, result.value()->globals.size());
    EXPECT_EQ(2u, result.value()->functions.size());
333
    EXPECT_EQ(0u, result.value()->data_segments.size());
334

335
    const WasmGlobal* global = &result.value()->globals[0];
336
    EXPECT_EQ(kWasmExternRef, global->type);
337
    EXPECT_FALSE(global->mutability);
338
    EXPECT_EQ(WasmInitExpr::kRefNullConst, global->init.kind());
339

340
    global = &result.value()->globals[1];
341
    EXPECT_EQ(kWasmFuncRef, global->type);
342
    EXPECT_FALSE(global->mutability);
343 344
    EXPECT_EQ(WasmInitExpr::kRefFuncConst, global->init.kind());
    EXPECT_EQ(uint32_t{1}, global->init.immediate().index);
345 346 347
  }
}

348
TEST_F(WasmModuleVerifyTest, FuncRefGlobal) {
349
  WASM_FEATURE_SCOPE(reftypes);
350 351
  static const byte data[] = {
      // sig#0 ---------------------------------------------------------------
352
      TYPE_SECTION_ONE_SIG_VOID_VOID,
353 354
      // funcs ---------------------------------------------------------------
      TWO_EMPTY_FUNCTIONS(SIG_INDEX(0)),
355 356
      SECTION(Global,                        // --
              ENTRY_COUNT(2),                // --
357
              kFuncRefCode,                  // local type
358 359
              0,                             // immutable
              WASM_INIT_EXPR_FUNC_REF_NULL,  // init
360
              kFuncRefCode,                  // local type
361 362 363 364 365 366 367 368 369
              0,                             // immutable
              WASM_INIT_EXPR_REF_FUNC(1)),   // init
      SECTION(Element,                       // section name
              ENTRY_COUNT(2),                // entry count
              DECLARATIVE,                   // flags 0
              kExternalFunction,             // type
              ENTRY_COUNT(1),                // func entry count
              FUNC_INDEX(0),                 // func index
              DECLARATIVE_WITH_ELEMENTS,     // flags 1
370
              kFuncRefCode,                  // local type
371 372
              ENTRY_COUNT(1),                // func ref count
              REF_FUNC_ELEMENT(1)),          // func ref
373 374 375 376 377 378 379 380 381 382
      TWO_EMPTY_BODIES};
  {
    // Should decode to two globals.
    ModuleResult result = DecodeModule(data, data + sizeof(data));
    EXPECT_OK(result);
    EXPECT_EQ(2u, result.value()->globals.size());
    EXPECT_EQ(2u, result.value()->functions.size());
    EXPECT_EQ(0u, result.value()->data_segments.size());

    const WasmGlobal* global = &result.value()->globals[0];
383
    EXPECT_EQ(kWasmFuncRef, global->type);
384
    EXPECT_FALSE(global->mutability);
385
    EXPECT_EQ(WasmInitExpr::kRefNullConst, global->init.kind());
386 387

    global = &result.value()->globals[1];
388
    EXPECT_EQ(kWasmFuncRef, global->type);
389
    EXPECT_FALSE(global->mutability);
390 391
    EXPECT_EQ(WasmInitExpr::kRefFuncConst, global->init.kind());
    EXPECT_EQ(uint32_t{1}, global->init.immediate().index);
392 393 394
  }
}

395
TEST_F(WasmModuleVerifyTest, InvalidFuncRefGlobal) {
396
  WASM_FEATURE_SCOPE(reftypes);
397 398
  static const byte data[] = {
      // sig#0 ---------------------------------------------------------------
399
      TYPE_SECTION_ONE_SIG_VOID_VOID,
400 401 402 403
      // funcs ---------------------------------------------------------------
      TWO_EMPTY_FUNCTIONS(SIG_INDEX(0)),
      SECTION(Global,                       // --
              ENTRY_COUNT(1),               // --
404
              kFuncRefCode,                 // local type
405 406 407 408 409 410
              0,                            // immutable
              WASM_INIT_EXPR_REF_FUNC(7)),  // invalid function index
      TWO_EMPTY_BODIES};
  EXPECT_FAILURE(data);
}

411 412
TEST_F(WasmModuleVerifyTest, ExternRefGlobalWithGlobalInit) {
  WASM_FEATURE_SCOPE(reftypes);
413
  static const byte data[] = {
414 415
      SECTION(Import,           // --
              ENTRY_COUNT(1),   // number of imports
416 417
              ADD_COUNT('m'),   // module name
              ADD_COUNT('f'),   // global name
418
              kExternalGlobal,  // import kind
419
              kExternRefCode,   // type
420 421 422
              0),               // mutability
      SECTION(Global,           // --
              ENTRY_COUNT(1),
423 424
              kExternRefCode,  // local type
              0,               // immutable
425
              WASM_INIT_EXPR_GLOBAL(0)),
426 427 428 429 430 431
  };

  {
    // Should decode to exactly one global.
    ModuleResult result = DecodeModule(data, data + sizeof(data));
    EXPECT_OK(result);
432 433 434
    EXPECT_EQ(2u, result.value()->globals.size());
    EXPECT_EQ(0u, result.value()->functions.size());
    EXPECT_EQ(0u, result.value()->data_segments.size());
435

436
    const WasmGlobal* global = &result.value()->globals.back();
437

438
    EXPECT_EQ(kWasmExternRef, global->type);
439
    EXPECT_FALSE(global->mutability);
440
    EXPECT_EQ(WasmInitExpr::kGlobalGet, global->init.kind());
441 442 443
  }
}

444
TEST_F(WasmModuleVerifyTest, NullGlobalWithGlobalInit) {
445
  WASM_FEATURE_SCOPE(reftypes);
446 447 448 449 450 451
  static const byte data[] = {
      SECTION(Import,           // --
              ENTRY_COUNT(1),   // number of imports
              ADD_COUNT('m'),   // module name
              ADD_COUNT('n'),   // global name
              kExternalGlobal,  // import kind
452
              kExternRefCode,   // type
453 454 455
              0),               // mutability
      SECTION(Global,           // --
              ENTRY_COUNT(1),
456 457
              kExternRefCode,  // local type
              0,               // immutable
458 459 460 461 462 463 464 465 466 467 468 469 470 471
              WASM_INIT_EXPR_GLOBAL(0)),
  };

  {
    // Should decode to exactly one global.
    ModuleResult result = DecodeModule(data, data + sizeof(data));
    std::cout << result.error().message() << std::endl;
    EXPECT_OK(result);
    EXPECT_EQ(2u, result.value()->globals.size());
    EXPECT_EQ(0u, result.value()->functions.size());
    EXPECT_EQ(0u, result.value()->data_segments.size());

    const WasmGlobal* global = &result.value()->globals.back();

472
    EXPECT_EQ(kWasmExternRef, global->type);
473
    EXPECT_FALSE(global->mutability);
474
    EXPECT_EQ(WasmInitExpr::kGlobalGet, global->init.kind());
475 476 477
  }
}

478
TEST_F(WasmModuleVerifyTest, GlobalInvalidType) {
479
  static const byte data[] = {
480 481
      SECTION(Global,                      // --
              ENTRY_COUNT(1),              // --
482
              64,                          // invalid value type
483 484
              1,                           // mutable
              WASM_INIT_EXPR_I32V_1(33)),  // init
485 486
  };

487
  EXPECT_FAILURE(data);
488 489
}

490
TEST_F(WasmModuleVerifyTest, GlobalInvalidType2) {
491
  static const byte data[] = {
492 493
      SECTION(Global,                      // --
              ENTRY_COUNT(1),              // --
494
              kVoidCode,                   // invalid value type
495 496
              1,                           // mutable
              WASM_INIT_EXPR_I32V_1(33)),  // init
497 498
  };

499
  EXPECT_FAILURE(data);
500 501
}

502
TEST_F(WasmModuleVerifyTest, GlobalInitializer) {
503 504 505
  static const byte no_initializer_no_end[] = {
      SECTION(Global,          //--
              ENTRY_COUNT(1),  //--
506
              kI32Code,        // type
507 508 509
              1)               // mutable
  };
  EXPECT_FAILURE_WITH_MSG(no_initializer_no_end,
510
                          "Initializer expression is missing 'end'");
511 512 513 514

  static const byte no_initializer[] = {
      SECTION(Global,          //--
              ENTRY_COUNT(1),  //--
515
              kI32Code,        // type
516 517 518 519
              1,               // mutable
              kExprEnd)        // --
  };
  EXPECT_FAILURE_WITH_MSG(no_initializer,
520
                          "Found 'end' in initializer expression, but no "
521 522 523 524 525
                          "expressions were found on the stack");

  static const byte too_many_initializers_no_end[] = {
      SECTION(Global,           // --
              ENTRY_COUNT(1),   // --
526
              kI32Code,         // type
527 528 529 530 531
              1,                // mutable
              WASM_I32V_1(42),  // one value is good
              WASM_I32V_1(43))  // another value is too much
  };
  EXPECT_FAILURE_WITH_MSG(too_many_initializers_no_end,
532
                          "Initializer expression is missing 'end'");
533 534 535 536

  static const byte too_many_initializers[] = {
      SECTION(Global,           // --
              ENTRY_COUNT(1),   // --
537
              kI32Code,         // type
538 539 540 541 542
              1,                // mutable
              WASM_I32V_1(42),  // one value is good
              WASM_I32V_1(43),  // another value is too much
              kExprEnd)};
  EXPECT_FAILURE_WITH_MSG(too_many_initializers,
543 544
                          "Found 'end' in initializer expression, but more than"
                          " one expressions were found on the stack");
545 546 547 548

  static const byte missing_end_opcode[] = {
      SECTION(Global,           // --
              ENTRY_COUNT(1),   // --
549
              kI32Code,         // type
550 551 552 553
              1,                // mutable
              WASM_I32V_1(42))  // init value
  };
  EXPECT_FAILURE_WITH_MSG(missing_end_opcode,
554
                          "Initializer expression is missing 'end'");
555 556 557

  static const byte referencing_out_of_bounds_global[] = {
      SECTION(Global, ENTRY_COUNT(1),         // --
558
              kI32Code,                       // type
559
              1,                              // mutable
560
              WASM_GLOBAL_GET(42), kExprEnd)  // init value
561 562 563 564 565 566
  };
  EXPECT_FAILURE_WITH_MSG(referencing_out_of_bounds_global,
                          "global index is out of bounds");

  static const byte referencing_undefined_global[] = {
      SECTION(Global, ENTRY_COUNT(2),        // --
567
              kI32Code,                      // type
568
              0,                             // mutable
569
              WASM_GLOBAL_GET(1), kExprEnd,  // init value
570
              kI32Code,                      // type
571 572 573 574 575 576 577 578 579 580 581
              0,                             // mutable
              WASM_I32V(0), kExprEnd)        // init value
  };
  EXPECT_FAILURE_WITH_MSG(referencing_undefined_global,
                          "global #1 is not defined yet");

  {
    WASM_FEATURE_SCOPE(reftypes);
    WASM_FEATURE_SCOPE(typed_funcref);
    WASM_FEATURE_SCOPE(gc);
    static const byte referencing_undefined_global_nested[] = {
582 583
        SECTION(Type, ENTRY_COUNT(1), WASM_ARRAY_DEF(kI32Code, true)),
        SECTION(Global, ENTRY_COUNT(2),            // --
584
                WASM_RTT_WITH_DEPTH(1, 0),         // type
585 586 587 588
                0,                                 // mutable
                WASM_RTT_SUB(0,                    // init value
                             WASM_GLOBAL_GET(1)),  // --
                kExprEnd,                          // --
589
                WASM_RTT_WITH_DEPTH(0, 0),         // type
590 591
                0,                                 // mutable
                WASM_RTT_CANON(0), kExprEnd)       // init value
592 593 594 595 596 597 598
    };
    EXPECT_FAILURE_WITH_MSG(referencing_undefined_global_nested,
                            "global #1 is not defined yet");
  }

  static const byte referencing_mutable_global[] = {
      SECTION(Global, ENTRY_COUNT(2),        // --
599
              kI32Code,                      // type
600 601
              1,                             // mutable
              WASM_I32V(1), kExprEnd,        // init value
602
              kI32Code,                      // type
603
              0,                             // mutable
604
              WASM_GLOBAL_GET(0), kExprEnd)  // init value
605 606 607 608 609 610 611 612 613
  };
  EXPECT_FAILURE_WITH_MSG(
      referencing_mutable_global,
      "mutable globals cannot be used in initializer expressions");

  static const byte referencing_mutable_imported_global[] = {
      SECTION(Import, ENTRY_COUNT(1),          // --
              ADD_COUNT('m'), ADD_COUNT('n'),  // module, name
              kExternalGlobal,                 // --
614
              kI32Code,                        // type
615 616
              1),                              // mutable
      SECTION(Global, ENTRY_COUNT(1),          // --
617
              kI32Code,                        // type
618
              0,                               // mutable
619
              WASM_GLOBAL_GET(0), kExprEnd)    // init value
620 621 622 623 624 625 626 627 628
  };
  EXPECT_FAILURE_WITH_MSG(
      referencing_mutable_imported_global,
      "mutable globals cannot be used in initializer expressions");

  static const byte referencing_immutable_imported_global[] = {
      SECTION(Import, ENTRY_COUNT(1),          // --
              ADD_COUNT('m'), ADD_COUNT('n'),  // module, name
              kExternalGlobal,                 // --
629
              kI32Code,                        // type
630 631
              0),                              // mutable
      SECTION(Global, ENTRY_COUNT(1),          // --
632
              kI32Code,                        // type
633
              0,                               // mutable
634
              WASM_GLOBAL_GET(0), kExprEnd)    // init value
635 636 637 638 639
  };
  EXPECT_VERIFIES(referencing_immutable_imported_global);

  static const byte referencing_local_global[] = {
      SECTION(Global, ENTRY_COUNT(2),        // --
640
              kI32Code,                      // type
641 642
              0,                             // mutable
              WASM_I32V(1), kExprEnd,        // init value
643
              kI32Code,                      // type
644
              0,                             // mutable
645
              WASM_GLOBAL_GET(0), kExprEnd)  // init value
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
  };
  EXPECT_FAILURE_WITH_MSG(
      referencing_local_global,
      "non-imported globals cannot be used in initializer expressions");

  {
    // But: experimental-wasm-gc should enable referencing immutable local
    // globals.
    WASM_FEATURE_SCOPE(gc);
    EXPECT_VERIFIES(referencing_local_global);
    // Referencing mutable glocals still invalid.
    EXPECT_FAILURE_WITH_MSG(
        referencing_mutable_global,
        "mutable globals cannot be used in initializer expressions");
  }
661 662
}

663
TEST_F(WasmModuleVerifyTest, ZeroGlobals) {
664
  static const byte data[] = {SECTION(Global, ENTRY_COUNT(0))};
665
  ModuleResult result = DecodeModule(data, data + sizeof(data));
666
  EXPECT_OK(result);
667 668
}

669 670 671
TEST_F(WasmModuleVerifyTest, ExportMutableGlobal) {
  {
    static const byte data[] = {
672 673
        SECTION(Global,                         // --
                ENTRY_COUNT(1),                 // --
674
                kI32Code,                       // local type
675 676 677 678 679 680 681
                0,                              // immutable
                WASM_INIT_EXPR_I32V_1(13)),     // init
        SECTION(Export,                         // --
                ENTRY_COUNT(1),                 // export count
                ADD_COUNT('n', 'a', 'm', 'e'),  // name
                kExternalGlobal,                // global
                0),                             // global index
682 683 684 685 686
    };
    EXPECT_VERIFIES(data);
  }
  {
    static const byte data[] = {
687 688
        SECTION(Global,                         // --
                ENTRY_COUNT(1),                 // --
689
                kI32Code,                       // local type
690 691 692 693 694 695 696
                1,                              // mutable
                WASM_INIT_EXPR_I32V_1(13)),     // init
        SECTION(Export,                         // --
                ENTRY_COUNT(1),                 // export count
                ADD_COUNT('n', 'a', 'm', 'e'),  // name
                kExternalGlobal,                // global
                0),                             // global index
697
    };
698
    EXPECT_VERIFIES(data);
699 700 701
  }
}

702
static void AppendUint32v(std::vector<byte>* buffer, uint32_t val) {
703 704
  while (true) {
    uint32_t next = val >> 7;
705
    uint32_t out = val & 0x7F;
706
    if (next) {
707
      buffer->push_back(static_cast<byte>(0x80 | out));
708 709
      val = next;
    } else {
710
      buffer->push_back(static_cast<byte>(out));
711 712 713 714 715 716
      break;
    }
  }
}

TEST_F(WasmModuleVerifyTest, NGlobals) {
717
  static const byte data[] = {
718
      kF32Code,                 // memory type
719 720
      0,                        // immutable
      WASM_INIT_EXPR_F32(7.7),  // init
721
  };
722

723
  for (uint32_t i = 0; i < kV8MaxWasmGlobals; i = i * 13 + 1) {
724
    std::vector<byte> buffer;
725
    size_t size = SizeOfVarInt(i) + i * sizeof(data);
726
    const byte globals[] = {kGlobalSectionCode, U32V_5(size)};
727 728 729
    for (size_t g = 0; g != sizeof(globals); ++g) {
      buffer.push_back(globals[g]);
    }
730
    AppendUint32v(&buffer, i);  // Number of globals.
731
    for (uint32_t j = 0; j < i; j++) {
732
      buffer.insert(buffer.end(), data, data + sizeof(data));
733 734 735
    }

    ModuleResult result = DecodeModule(&buffer[0], &buffer[0] + buffer.size());
736
    EXPECT_OK(result);
737 738 739 740
  }
}

TEST_F(WasmModuleVerifyTest, TwoGlobals) {
741 742
  static const byte data[] = {SECTION(Global,                      // --
                                      ENTRY_COUNT(2),              // --
743
                                      kF32Code,                    // type
744 745
                                      0,                           // immutable
                                      WASM_INIT_EXPR_F32(22.0),    // --
746
                                      kF64Code,                    // type
747 748
                                      1,                           // mutable
                                      WASM_INIT_EXPR_F64(23.0))};  // --
749 750 751

  {
    // Should decode to exactly two globals.
752
    ModuleResult result = DecodeModule(data, data + sizeof(data));
753
    EXPECT_OK(result);
754 755 756
    EXPECT_EQ(2u, result.value()->globals.size());
    EXPECT_EQ(0u, result.value()->functions.size());
    EXPECT_EQ(0u, result.value()->data_segments.size());
757

758
    const WasmGlobal* g0 = &result.value()->globals[0];
759

760
    EXPECT_EQ(kWasmF32, g0->type);
761
    EXPECT_EQ(0u, g0->offset);
762
    EXPECT_FALSE(g0->mutability);
763
    EXPECT_EQ(WasmInitExpr::kF32Const, g0->init.kind());
764

765
    const WasmGlobal* g1 = &result.value()->globals[1];
766

767
    EXPECT_EQ(kWasmF64, g1->type);
768
    EXPECT_EQ(8u, g1->offset);
769
    EXPECT_TRUE(g1->mutability);
770
    EXPECT_EQ(WasmInitExpr::kF64Const, g1->init.kind());
771 772
  }

773
  EXPECT_OFF_END_FAILURE(data, 1);
774 775
}

776 777
TEST_F(WasmModuleVerifyTest, RefNullGlobal) {
  WASM_FEATURE_SCOPE(reftypes);
778 779
  static const byte data[] = {SECTION(Global, ENTRY_COUNT(1), kFuncRefCode, 1,
                                      WASM_REF_NULL(kFuncRefCode), kExprEnd)};
780 781 782 783 784 785 786
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
}

TEST_F(WasmModuleVerifyTest, RefNullGlobalInvalid1) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
787 788
  static const byte data[] = {SECTION(Global, ENTRY_COUNT(1), kOptRefCode, 0, 1,
                                      WASM_REF_NULL(0), kExprEnd)};
789
  ModuleResult result = DecodeModule(data, data + sizeof(data));
790
  EXPECT_NOT_OK(result, "Type index 0 is out of bounds");
791 792 793 794 795
}

TEST_F(WasmModuleVerifyTest, RefNullGlobalInvalid2) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
796
  static const byte data[] = {SECTION(Global, ENTRY_COUNT(1), kFuncRefCode, 1,
797 798 799 800 801 802 803
                                      kExprRefNull, U32V_5(1000001), kExprEnd)};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result,
                "Type index 1000001 is greater than the maximum number 1000000 "
                "of type definitions supported by V8");
}

804 805 806 807 808 809
TEST_F(WasmModuleVerifyTest, RttCanonGlobalStruct) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1),
810
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true))),
811 812
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(0, 0), 0,
              WASM_RTT_CANON(0), kExprEnd)};
813 814 815 816 817 818 819 820
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
}

TEST_F(WasmModuleVerifyTest, RttCanonGlobalTypeError) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
821 822 823
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true))),
824 825
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(1, 0), 1,
              WASM_RTT_CANON(0), kExprEnd)};
826 827
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result,
828 829
                "type error in init expression, expected (rtt 1 0), got "
                "(rtt 0 0)");
830 831 832 833 834 835
}

TEST_F(WasmModuleVerifyTest, GlobalRttSubOfCanon) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
836
  static const byte data[] = {
837 838 839 840
      SECTION(Type, ENTRY_COUNT(2),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(2), STRUCT_FIELD(kI32Code, true),
                              STRUCT_FIELD(kI32Code, true))),
841
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(1, 1), 1,
842
              WASM_RTT_SUB(1, WASM_RTT_CANON(0)), kExprEnd)};
843
  ModuleResult result = DecodeModule(data, data + sizeof(data));
844
  WasmInitExpr expected = WasmInitExpr::RttSub(1, WasmInitExpr::RttCanon(0));
845 846 847 848
  EXPECT_OK(result);
  EXPECT_EQ(result.value()->globals.front().init, expected);
}

849 850 851 852
TEST_F(WasmModuleVerifyTest, GlobalRttFreshSubOfCanon) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
853 854
  WASM_FEATURE_SCOPE(gc_experiments);

855 856 857 858 859 860 861 862 863 864 865 866 867 868
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(2),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(2), STRUCT_FIELD(kI32Code, true),
                              STRUCT_FIELD(kI32Code, true))),
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(1, 1), 1,
              WASM_RTT_FRESH_SUB(1, WASM_RTT_CANON(0)), kExprEnd)};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  WasmInitExpr expected =
      WasmInitExpr::RttFreshSub(1, WasmInitExpr::RttCanon(0));
  EXPECT_OK(result);
  EXPECT_EQ(result.value()->globals.front().init, expected);
}

869 870 871 872
TEST_F(WasmModuleVerifyTest, GlobalRttSubOfSubOfCanon) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
873 874 875 876 877
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(2),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(2), STRUCT_FIELD(kI32Code, true),
                              STRUCT_FIELD(kI32Code, true))),
878
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(2, 1), 1,
879
              WASM_RTT_SUB(1, WASM_RTT_SUB(1, WASM_RTT_CANON(0))), kExprEnd)};
880 881
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  WasmInitExpr expected = WasmInitExpr::RttSub(
882
      1, WasmInitExpr::RttSub(1, WasmInitExpr::RttCanon(0)));
883 884 885 886
  EXPECT_OK(result);
  EXPECT_EQ(result.value()->globals.front().init, expected);
}

887 888 889 890
TEST_F(WasmModuleVerifyTest, GlobalRttFreshSubOfSubOfCanon) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
891 892
  WASM_FEATURE_SCOPE(gc_experiments);

893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(2),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(2), STRUCT_FIELD(kI32Code, true),
                              STRUCT_FIELD(kI32Code, true))),
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(2, 1), 1,
              WASM_RTT_FRESH_SUB(1, WASM_RTT_SUB(1, WASM_RTT_CANON(0))),
              kExprEnd)};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  WasmInitExpr expected = WasmInitExpr::RttFreshSub(
      1, WasmInitExpr::RttSub(1, WasmInitExpr::RttCanon(0)));
  EXPECT_OK(result);
  EXPECT_EQ(result.value()->globals.front().init, expected);
}

TEST_F(WasmModuleVerifyTest, GlobalRttFreshSubOfFreshSubOfCanon) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
912 913
  WASM_FEATURE_SCOPE(gc_experiments);

914 915 916 917 918 919 920 921 922 923 924 925 926 927 928
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(2),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(2), STRUCT_FIELD(kI32Code, true),
                              STRUCT_FIELD(kI32Code, true))),
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(2, 1), 1,
              WASM_RTT_FRESH_SUB(1, WASM_RTT_FRESH_SUB(1, WASM_RTT_CANON(0))),
              kExprEnd)};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  WasmInitExpr expected = WasmInitExpr::RttFreshSub(
      1, WasmInitExpr::RttFreshSub(1, WasmInitExpr::RttCanon(0)));
  EXPECT_OK(result);
  EXPECT_EQ(result.value()->globals.front().init, expected);
}

929 930 931 932 933
TEST_F(WasmModuleVerifyTest, GlobalRttSubOfGlobal) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
  static const byte data[] = {
934 935 936 937
      SECTION(Type, ENTRY_COUNT(2),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(2), STRUCT_FIELD(kI32Code, true),
                              STRUCT_FIELD(kI32Code, true))),
938 939 940 941 942 943 944 945
      SECTION(Import,                     // section header
              ENTRY_COUNT(1),             // number of imports
              ADD_COUNT('m'),             // module name
              ADD_COUNT('f'),             // global name
              kExternalGlobal,            // import kind
              WASM_RTT_WITH_DEPTH(0, 0),  // type
              0),                         // mutability
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(1, 1), 1,
946
              WASM_RTT_SUB(1, WASM_GLOBAL_GET(0)), kExprEnd)};
947
  ModuleResult result = DecodeModule(data, data + sizeof(data));
948
  WasmInitExpr expected = WasmInitExpr::RttSub(1, WasmInitExpr::GlobalGet(0));
949 950 951 952
  EXPECT_OK(result);
  EXPECT_EQ(result.value()->globals[1].init, expected);
}

953 954 955 956
TEST_F(WasmModuleVerifyTest, GlobalRttFreshSubOfGlobal) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
957 958
  WASM_FEATURE_SCOPE(gc_experiments);

959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(2),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(2), STRUCT_FIELD(kI32Code, true),
                              STRUCT_FIELD(kI32Code, true))),
      SECTION(Import,                     // section header
              ENTRY_COUNT(1),             // number of imports
              ADD_COUNT('m'),             // module name
              ADD_COUNT('f'),             // global name
              kExternalGlobal,            // import kind
              WASM_RTT_WITH_DEPTH(0, 0),  // type
              0),                         // mutability
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(1, 1), 1,
              WASM_RTT_FRESH_SUB(1, WASM_GLOBAL_GET(0)), kExprEnd)};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  WasmInitExpr expected =
      WasmInitExpr::RttFreshSub(1, WasmInitExpr::GlobalGet(0));
  EXPECT_OK(result);
  EXPECT_EQ(result.value()->globals[1].init, expected);
}

980 981 982 983 984
TEST_F(WasmModuleVerifyTest, GlobalRttSubOfGlobalTypeError) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
  static const byte data[] = {
985 986
      SECTION(Type, ENTRY_COUNT(1),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true))),
987 988 989 990 991
      SECTION(Import,           // section header
              ENTRY_COUNT(1),   // number of imports
              ADD_COUNT('m'),   // module name
              ADD_COUNT('f'),   // global name
              kExternalGlobal,  // import kind
992
              kI32Code,         // type
993
              0),               // mutability
994
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(1, 0), 1,
995
              WASM_RTT_SUB(0, WASM_GLOBAL_GET(0)), kExprEnd)};
996 997 998 999
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "rtt.sub requires a supertype rtt on stack");
}

1000 1001 1002 1003
TEST_F(WasmModuleVerifyTest, GlobalRttFreshSubOfGlobalTypeError) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
1004 1005
  WASM_FEATURE_SCOPE(gc_experiments);

1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true))),
      SECTION(Import,           // section header
              ENTRY_COUNT(1),   // number of imports
              ADD_COUNT('m'),   // module name
              ADD_COUNT('f'),   // global name
              kExternalGlobal,  // import kind
              kI32Code,         // type
              0),               // mutability
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(1, 0), 1,
              WASM_RTT_FRESH_SUB(0, WASM_GLOBAL_GET(0)), kExprEnd)};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "rtt.fresh_sub requires a supertype rtt on stack");
}

1022
#if !V8_OS_FUCHSIA
1023 1024 1025 1026
TEST_F(WasmModuleVerifyTest, GlobalRttSubIllegalParent) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
1027 1028 1029 1030
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(2),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kF32Code, true))),
1031
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(1, 1), 1,
1032
              WASM_RTT_SUB(1, WASM_RTT_CANON(0)), kExprEnd)};
1033 1034 1035
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "rtt.sub requires a supertype rtt on stack");
}
1036 1037 1038 1039 1040

TEST_F(WasmModuleVerifyTest, GlobalRttFreshSubIllegalParent) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
1041 1042
  WASM_FEATURE_SCOPE(gc_experiments);

1043 1044 1045 1046 1047 1048 1049 1050 1051
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(2),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kF32Code, true))),
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(1, 1), 1,
              WASM_RTT_FRESH_SUB(1, WASM_RTT_CANON(0)), kExprEnd)};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "rtt.fresh_sub requires a supertype rtt on stack");
}
1052
#endif  // !V8_OS_FUCHSIA
1053 1054 1055 1056 1057

TEST_F(WasmModuleVerifyTest, RttSubGlobalTypeError) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
1058 1059 1060
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true))),
1061
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(0, 0), 1,
1062
              WASM_RTT_SUB(0, WASM_RTT_CANON(0)), kExprEnd)};
1063 1064
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result,
1065 1066
                "type error in init expression, expected (rtt 0 0), got "
                "(rtt 1 0)");
1067 1068
}

1069 1070 1071 1072
TEST_F(WasmModuleVerifyTest, RttFreshSubGlobalTypeError) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
1073 1074
  WASM_FEATURE_SCOPE(gc_experiments);

1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true))),
      SECTION(Global, ENTRY_COUNT(1), WASM_RTT_WITH_DEPTH(0, 0), 1,
              WASM_RTT_FRESH_SUB(0, WASM_RTT_CANON(0)), kExprEnd)};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result,
                "type error in init expression, expected (rtt 0 0), got "
                "(rtt 1 0)");
}

1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
TEST_F(WasmModuleVerifyTest, StructNewInitExpr) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
  WASM_FEATURE_SCOPE(gc_experiments);

  static const byte basic[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true))),
      SECTION(Global, ENTRY_COUNT(1),  // --
              kRefCode, 0, 0,          // type, mutability
              WASM_INIT_EXPR_STRUCT_NEW(0, WASM_I32V(42), WASM_RTT_CANON(0)))};
  EXPECT_VERIFIES(basic);

  static const byte global_args[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true))),
      SECTION(Global, ENTRY_COUNT(3),                        // --
              kI32Code, 0,                                   // type, mutability
              WASM_INIT_EXPR_I32V_1(10),                     // --
              kRttCode, 0, 0,                                // type, mutability
              WASM_RTT_SUB(0, WASM_RTT_CANON(0)), kExprEnd,  // --
              kRefCode, 0, 0,                                // type, mutability
              WASM_INIT_EXPR_STRUCT_NEW(0, WASM_GLOBAL_GET(0),
                                        WASM_GLOBAL_GET(1)))};
  EXPECT_VERIFIES(global_args);

  static const byte type_error[] = {
      SECTION(Type, ENTRY_COUNT(2),  // --
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI64Code, true))),
      SECTION(Global, ENTRY_COUNT(1),  // --
              kRefCode, 1, 0,          // type, mutability
              WASM_INIT_EXPR_STRUCT_NEW(0, WASM_I32V(42), WASM_RTT_CANON(0)))};
  EXPECT_FAILURE_WITH_MSG(
      type_error,
      "type error in init expression, expected (ref 1), got (ref 0)");

  static const byte subexpr_type_error[] = {
      SECTION(Type, ENTRY_COUNT(2),  // --
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI64Code, true))),
      SECTION(Global, ENTRY_COUNT(1),  // --
              kRefCode, 0, 0,          // type, mutability
              WASM_INIT_EXPR_STRUCT_NEW(0, WASM_I32V(42), WASM_RTT_CANON(1)))};
  EXPECT_FAILURE_WITH_MSG(
      subexpr_type_error,
      "struct.new[1]: expected (rtt 0), found (rtt 0 1) instead");
}

1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181
TEST_F(WasmModuleVerifyTest, ArrayInitInitExpr) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
  WASM_FEATURE_SCOPE(gc_experiments);

  static const byte basic[] = {
      SECTION(Type, ENTRY_COUNT(1), WASM_ARRAY_DEF(kI16Code, true)),
      SECTION(Global, ENTRY_COUNT(1),  // --
              kRefCode, 0, 0,          // type, mutability
              WASM_INIT_EXPR_ARRAY_INIT(0, 3, WASM_I32V(10), WASM_I32V(20),
                                        WASM_I32V(30), WASM_RTT_CANON(0)))};
  EXPECT_VERIFIES(basic);

  static const byte type_error[] = {
      SECTION(Type, ENTRY_COUNT(2),  // --
              WASM_ARRAY_DEF(kI32Code, true),
              WASM_ARRAY_DEF(WASM_SEQ(kRefCode, 0), true)),
      SECTION(
          Global, ENTRY_COUNT(1),  // --
          kRefCode, 1, 0,          // type, mutability
          WASM_INIT_EXPR_ARRAY_INIT(0, 1, WASM_I32V(42), WASM_RTT_CANON(0)))};
  EXPECT_FAILURE_WITH_MSG(
      type_error,
      "type error in init expression, expected (ref 1), got (ref 0)");

  static const byte subexpr_type_error[] = {
      SECTION(Type, ENTRY_COUNT(1), WASM_ARRAY_DEF(kI64Code, true)),
      SECTION(Global, ENTRY_COUNT(1),  // --
              kRefCode, 0, 0,          // type, mutability
              WASM_INIT_EXPR_ARRAY_INIT(0, 2, WASM_I64V(42), WASM_I32V(142),
                                        WASM_RTT_CANON(0)))};
  EXPECT_FAILURE_WITH_MSG(subexpr_type_error,
                          "array.init[1]: expected i64, found i32 instead");

  static const byte length_error[] = {
      SECTION(Type, ENTRY_COUNT(1), WASM_ARRAY_DEF(kI16Code, true)),
      SECTION(Global, ENTRY_COUNT(1),  // --
              kRefCode, 0, 0,          // type, mutability
              WASM_INIT_EXPR_ARRAY_INIT(0, 10, WASM_I32V(10), WASM_I32V(20),
                                        WASM_I32V(30), WASM_RTT_CANON(0)))};
  EXPECT_FAILURE_WITH_MSG(
      length_error,
      "not enough arguments on the stack for array.init: expected 11, found 4");
}

1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
TEST_F(WasmModuleVerifyTest, EmptyStruct) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
  static const byte empty_struct[] = {SECTION(Type, ENTRY_COUNT(1),  // --
                                              kWasmStructTypeCode,   // --
                                              U32V_1(0))};  // field count

  EXPECT_VERIFIES(empty_struct);
}

1193 1194 1195 1196 1197 1198 1199 1200
TEST_F(WasmModuleVerifyTest, InvalidStructTypeDef) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
  static const byte all_good[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmStructTypeCode,   // --
              U32V_1(1),             // field count
1201
              kI32Code,              // perfectly valid field type
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
              1)};                   // mutability
  EXPECT_VERIFIES(all_good);

  static const byte invalid_field_type[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmStructTypeCode,   // --
              U32V_1(1),             // field count
              kWasmArrayTypeCode,    // bogus field type
              1)};                   // mutability
  EXPECT_FAILURE_WITH_MSG(invalid_field_type, "invalid value type");

  static const byte field_type_oob_ref[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmStructTypeCode,   // --
              U32V_1(1),             // field count
1217
              kOptRefCode,           // field type: reference...
1218 1219 1220 1221 1222 1223 1224 1225
              3,                     // ...to nonexistent type
              1)};                   // mutability
  EXPECT_FAILURE_WITH_MSG(field_type_oob_ref, "Type index 3 is out of bounds");

  static const byte field_type_invalid_ref[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmStructTypeCode,   // --
              U32V_1(1),             // field count
1226
              kOptRefCode,           // field type: reference...
1227 1228 1229 1230 1231 1232 1233 1234
              U32V_4(1234567),       // ...to a type > kV8MaxWasmTypes
              1)};                   // mutability
  EXPECT_FAILURE_WITH_MSG(field_type_invalid_ref, "greater than the maximum");

  static const byte field_type_invalid_ref2[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmStructTypeCode,   // --
              U32V_1(1),             // field count
1235 1236
              kOptRefCode,           // field type: reference...
              kI32Code,              // ...to a non-referenceable type
1237 1238 1239 1240 1241 1242 1243
              1)};                   // mutability
  EXPECT_FAILURE_WITH_MSG(field_type_invalid_ref2, "Unknown heap type");

  static const byte not_enough_field_types[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmStructTypeCode,   // --
              U32V_1(2),             // field count
1244
              kI32Code,              // field type 1
1245 1246 1247 1248 1249 1250 1251
              1)};                   // mutability 1
  EXPECT_FAILURE_WITH_MSG(not_enough_field_types, "expected 1 byte");

  static const byte not_enough_field_types2[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmStructTypeCode,   // --
              U32V_1(2),             // field count
1252
              kI32Code,              // field type 1
1253
              1,                     // mutability 1
1254
              kI32Code)};            // field type 2
1255 1256 1257 1258 1259 1260
  EXPECT_FAILURE_WITH_MSG(not_enough_field_types2, "expected 1 byte");

  static const byte invalid_mutability[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmStructTypeCode,   // --
              U32V_1(1),             // field count
1261
              kI32Code,              // field type
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
              2)};                   // invalid mutability value
  EXPECT_FAILURE_WITH_MSG(invalid_mutability, "invalid mutability");
}

TEST_F(WasmModuleVerifyTest, InvalidArrayTypeDef) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
  static const byte all_good[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmArrayTypeCode,    // --
1273
              kI32Code,              // perfectly valid field type
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
              1)};                   // mutability
  EXPECT_VERIFIES(all_good);

  static const byte invalid_field_type[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmArrayTypeCode,    // --
              kWasmArrayTypeCode,    // bogus field type
              1)};                   // mutability
  EXPECT_FAILURE_WITH_MSG(invalid_field_type, "invalid value type");

  static const byte field_type_oob_ref[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmArrayTypeCode,    // --
1287
              kOptRefCode,           // field type: reference...
1288 1289 1290 1291 1292 1293 1294
              3,                     // ...to nonexistent type
              1)};                   // mutability
  EXPECT_FAILURE_WITH_MSG(field_type_oob_ref, "Type index 3 is out of bounds");

  static const byte field_type_invalid_ref[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmArrayTypeCode,    // --
1295
              kOptRefCode,           // field type: reference...
1296 1297 1298 1299 1300 1301 1302
              U32V_3(1234567),       // ...to a type > kV8MaxWasmTypes
              1)};                   // mutability
  EXPECT_FAILURE_WITH_MSG(field_type_invalid_ref, "Unknown heap type");

  static const byte field_type_invalid_ref2[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmArrayTypeCode,    // --
1303 1304
              kOptRefCode,           // field type: reference...
              kI32Code,              // ...to a non-referenceable type
1305 1306 1307 1308 1309 1310
              1)};                   // mutability
  EXPECT_FAILURE_WITH_MSG(field_type_invalid_ref2, "Unknown heap type");

  static const byte invalid_mutability[] = {
      SECTION(Type, ENTRY_COUNT(1),  // --
              kWasmArrayTypeCode,    // --
1311
              kI32Code,              // field type
1312 1313 1314 1315 1316 1317 1318
              2)};                   // invalid mutability value
  EXPECT_FAILURE_WITH_MSG(invalid_mutability, "invalid mutability");

  static const byte invalid_mutability2[] = {
      SECTION(Type,
              ENTRY_COUNT(1),      // --
              kWasmArrayTypeCode,  // --
1319
              kI32Code,            // field type
1320 1321 1322 1323 1324
              0)};                 // immmutability (disallowed in MVP)
  EXPECT_FAILURE_WITH_MSG(invalid_mutability2,
                          "immutable arrays are not supported");
}

1325
TEST_F(WasmModuleVerifyTest, ZeroExceptions) {
1326
  static const byte data[] = {SECTION(Exception, ENTRY_COUNT(0))};
1327
  FAIL_IF_NO_EXPERIMENTAL_EH(data);
1328

1329
  WASM_FEATURE_SCOPE(eh);
1330 1331
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
1332
  EXPECT_EQ(0u, result.value()->exceptions.size());
1333 1334 1335
}

TEST_F(WasmModuleVerifyTest, OneI32Exception) {
1336
  static const byte data[] = {
1337
      SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_v_x(kI32Code)),  // sig#0 (i32)
1338 1339
      SECTION(Exception, ENTRY_COUNT(1),
              EXCEPTION_ENTRY(SIG_INDEX(0)))};  // except[0] (sig#0)
1340
  FAIL_IF_NO_EXPERIMENTAL_EH(data);
1341

1342
  WASM_FEATURE_SCOPE(eh);
1343 1344
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
1345
  EXPECT_EQ(1u, result.value()->exceptions.size());
1346

1347
  const WasmException& e0 = result.value()->exceptions.front();
1348
  EXPECT_EQ(1u, e0.sig->parameter_count());
1349
  EXPECT_EQ(kWasmI32, e0.sig->GetParam(0));
1350 1351 1352
}

TEST_F(WasmModuleVerifyTest, TwoExceptions) {
1353 1354
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(2),
1355 1356
              SIG_ENTRY_v_x(kI32Code),              // sig#0 (i32)
              SIG_ENTRY_v_xx(kF32Code, kI64Code)),  // sig#1 (f32, i64)
1357
      SECTION(Exception, ENTRY_COUNT(2),
1358 1359
              EXCEPTION_ENTRY(SIG_INDEX(1)),    // except[0] (sig#1)
              EXCEPTION_ENTRY(SIG_INDEX(0)))};  // except[1] (sig#0)
1360 1361
  FAIL_IF_NO_EXPERIMENTAL_EH(data);

1362
  WASM_FEATURE_SCOPE(eh);
1363 1364
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
1365 1366
  EXPECT_EQ(2u, result.value()->exceptions.size());
  const WasmException& e0 = result.value()->exceptions.front();
1367
  EXPECT_EQ(2u, e0.sig->parameter_count());
1368 1369
  EXPECT_EQ(kWasmF32, e0.sig->GetParam(0));
  EXPECT_EQ(kWasmI64, e0.sig->GetParam(1));
1370
  const WasmException& e1 = result.value()->exceptions.back();
1371
  EXPECT_EQ(kWasmI32, e1.sig->GetParam(0));
1372 1373
}

1374
TEST_F(WasmModuleVerifyTest, Exception_invalid_sig_index) {
1375
  static const byte data[] = {
1376
      TYPE_SECTION_ONE_SIG_VOID_VOID,
1377
      SECTION(Exception, ENTRY_COUNT(1),
1378 1379
              EXCEPTION_ENTRY(
                  SIG_INDEX(23)))};  // except[0] (sig#23 [out-of-bounds])
1380 1381 1382 1383
  FAIL_IF_NO_EXPERIMENTAL_EH(data);

  // Should fail decoding exception section.
  WASM_FEATURE_SCOPE(eh);
1384 1385
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "signature index 23 out of bounds");
1386 1387 1388
}

TEST_F(WasmModuleVerifyTest, Exception_invalid_sig_return) {
1389 1390 1391
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_i_i),
      SECTION(Exception, ENTRY_COUNT(1),
1392 1393
              EXCEPTION_ENTRY(
                  SIG_INDEX(0)))};  // except[0] (sig#0 [invalid-return-type])
1394
  FAIL_IF_NO_EXPERIMENTAL_EH(data);
1395

1396
  // Should fail decoding exception section.
1397
  WASM_FEATURE_SCOPE(eh);
1398 1399
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "exception signature 0 has non-void return");
1400 1401
}

1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414
TEST_F(WasmModuleVerifyTest, Exception_invalid_attribute) {
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_i_i),
      SECTION(Exception, ENTRY_COUNT(1), 23,
              SIG_INDEX(0))};  // except[0] (sig#0) [invalid-attribute]
  FAIL_IF_NO_EXPERIMENTAL_EH(data);

  // Should fail decoding exception section.
  WASM_FEATURE_SCOPE(eh);
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "exception attribute 23 not supported");
}

1415
TEST_F(WasmModuleVerifyTest, ExceptionSectionCorrectPlacement) {
1416
  static const byte data[] = {SECTION(Memory, ENTRY_COUNT(0)),
1417
                              SECTION(Exception, ENTRY_COUNT(0)),
1418
                              SECTION(Global, ENTRY_COUNT(0))};
1419 1420 1421 1422 1423 1424 1425
  FAIL_IF_NO_EXPERIMENTAL_EH(data);

  WASM_FEATURE_SCOPE(eh);
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
}

1426 1427
TEST_F(WasmModuleVerifyTest, ExceptionSectionAfterGlobal) {
  static const byte data[] = {SECTION(Global, ENTRY_COUNT(0)),
1428
                              SECTION(Exception, ENTRY_COUNT(0))};
1429 1430 1431
  FAIL_IF_NO_EXPERIMENTAL_EH(data);

  WASM_FEATURE_SCOPE(eh);
1432
  ModuleResult result = DecodeModule(data, data + sizeof(data));
1433
  EXPECT_NOT_OK(result,
1434
                "The Exception section must appear before the Global section");
1435 1436
}

1437
TEST_F(WasmModuleVerifyTest, ExceptionSectionBeforeMemory) {
1438
  static const byte data[] = {SECTION(Exception, ENTRY_COUNT(0)),
1439
                              SECTION(Memory, ENTRY_COUNT(0))};
1440 1441 1442
  FAIL_IF_NO_EXPERIMENTAL_EH(data);

  WASM_FEATURE_SCOPE(eh);
1443
  ModuleResult result = DecodeModule(data, data + sizeof(data));
1444
  EXPECT_NOT_OK(result, "unexpected section <Memory>");
1445 1446
}

1447
TEST_F(WasmModuleVerifyTest, ExceptionSectionAfterTableBeforeMemory) {
1448
  STATIC_ASSERT(kMemorySectionCode + 1 == kGlobalSectionCode);
1449
  static const byte data[] = {SECTION(Table, ENTRY_COUNT(0)),
1450
                              SECTION(Exception, ENTRY_COUNT(0)),
1451
                              SECTION(Memory, ENTRY_COUNT(0))};
1452 1453 1454 1455
  FAIL_IF_NO_EXPERIMENTAL_EH(data);

  WASM_FEATURE_SCOPE(eh);
  ModuleResult result = DecodeModule(data, data + sizeof(data));
1456
  EXPECT_NOT_OK(result, "unexpected section <Memory>");
1457 1458
}

1459
TEST_F(WasmModuleVerifyTest, ExceptionImport) {
1460
  static const byte data[] = {
1461
      TYPE_SECTION_ONE_SIG_VOID_VOID,
1462 1463 1464 1465 1466 1467
      SECTION(Import,                           // section header
              ENTRY_COUNT(1),                   // number of imports
              ADD_COUNT('m'),                   // module name
              ADD_COUNT('e', 'x'),              // exception name
              kExternalException,               // import kind
              EXCEPTION_ENTRY(SIG_INDEX(0)))};  // except[0] (sig#0)
1468 1469 1470 1471 1472
  FAIL_IF_NO_EXPERIMENTAL_EH(data);

  WASM_FEATURE_SCOPE(eh);
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
1473 1474
  EXPECT_EQ(1u, result.value()->exceptions.size());
  EXPECT_EQ(1u, result.value()->import_table.size());
1475 1476
}

1477
TEST_F(WasmModuleVerifyTest, ExceptionExport) {
1478
  static const byte data[] = {
1479
      TYPE_SECTION_ONE_SIG_VOID_VOID,
1480 1481 1482 1483 1484 1485
      SECTION(Exception, ENTRY_COUNT(1),
              EXCEPTION_ENTRY(SIG_INDEX(0))),  // except[0] (sig#0)
      SECTION(Export, ENTRY_COUNT(1),          // --
              NO_NAME,                         // --
              kExternalException,              // --
              EXCEPTION_INDEX(0))};
1486 1487 1488 1489 1490
  FAIL_IF_NO_EXPERIMENTAL_EH(data);

  WASM_FEATURE_SCOPE(eh);
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
1491 1492
  EXPECT_EQ(1u, result.value()->exceptions.size());
  EXPECT_EQ(1u, result.value()->export_table.size());
1493 1494
}

1495
TEST_F(WasmModuleVerifyTest, OneSignature) {
titzer's avatar
titzer committed
1496
  {
1497
    static const byte data[] = {TYPE_SECTION_ONE_SIG_VOID_VOID};
titzer's avatar
titzer committed
1498 1499 1500 1501
    EXPECT_VERIFIES(data);
  }

  {
1502
    static const byte data[] = {SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_i_i)};
titzer's avatar
titzer committed
1503 1504
    EXPECT_VERIFIES(data);
  }
1505 1506 1507 1508
}

TEST_F(WasmModuleVerifyTest, MultipleSignatures) {
  static const byte data[] = {
1509 1510 1511 1512 1513
      SECTION(Type,                                           // --
              ENTRY_COUNT(3),                                 // --
              SIG_ENTRY_v_v,                                  // void -> void
              SIG_ENTRY_x_x(kI32Code, kF32Code),              // f32 -> i32
              SIG_ENTRY_x_xx(kI32Code, kF64Code, kF64Code)),  // f64,f64 -> i32
1514 1515
  };

1516
  ModuleResult result = DecodeModule(data, data + sizeof(data));
1517
  EXPECT_OK(result);
1518 1519 1520 1521 1522 1523 1524 1525 1526
  EXPECT_EQ(3u, result.value()->types.size());
  if (result.value()->types.size() == 3) {
    EXPECT_EQ(0u, result.value()->signature(0)->return_count());
    EXPECT_EQ(1u, result.value()->signature(1)->return_count());
    EXPECT_EQ(1u, result.value()->signature(2)->return_count());

    EXPECT_EQ(0u, result.value()->signature(0)->parameter_count());
    EXPECT_EQ(1u, result.value()->signature(1)->parameter_count());
    EXPECT_EQ(2u, result.value()->signature(2)->parameter_count());
1527 1528
  }

1529
  EXPECT_OFF_END_FAILURE(data, 1);
1530 1531
}

1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566
TEST_F(WasmModuleVerifyTest, CanonicalTypeIds) {
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
  WASM_FEATURE_SCOPE(reftypes);

  static const byte data[] = {
      SECTION(Type,                               // --
              ENTRY_COUNT(5),                     // --
              WASM_STRUCT_DEF(                    // Struct definition
                  FIELD_COUNT(1),                 // --
                  STRUCT_FIELD(kI32Code, true)),  // --
              SIG_ENTRY_x_x(kI32Code, kF32Code),  // f32 -> i32
              SIG_ENTRY_x_x(kI32Code, kF64Code),  // f64 -> i32
              SIG_ENTRY_x_x(kI32Code, kF32Code),  // f32 -> i32 (again)
              WASM_ARRAY_DEF(kI32Code, true))     // Array definition
  };

  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
  const WasmModule* module = result.value().get();

  EXPECT_EQ(5u, module->types.size());
  EXPECT_EQ(5u, module->type_kinds.size());
  EXPECT_EQ(5u, module->canonicalized_type_ids.size());
  EXPECT_EQ(2u, module->signature_map.size());

  // No canonicalization for structs.
  EXPECT_EQ(0u, module->canonicalized_type_ids[0]);
  EXPECT_EQ(0u, module->canonicalized_type_ids[1]);
  EXPECT_EQ(1u, module->canonicalized_type_ids[2]);
  EXPECT_EQ(0u, module->canonicalized_type_ids[3]);
  // No canonicalization for arrays.
  EXPECT_EQ(0u, module->canonicalized_type_ids[4]);
}

1567 1568 1569
TEST_F(WasmModuleVerifyTest, DataSegmentWithImmutableImportedGlobal) {
  // Import 2 globals so that we can initialize data with a global index != 0.
  const byte data[] = {
1570 1571
      SECTION(Import,           // section header
              ENTRY_COUNT(2),   // number of imports
1572 1573
              ADD_COUNT('m'),   // module name
              ADD_COUNT('f'),   // global name
1574
              kExternalGlobal,  // import kind
1575
              kI32Code,         // type
1576
              0,                // mutability
1577 1578
              ADD_COUNT('n'),   // module name
              ADD_COUNT('g'),   // global name
1579
              kExternalGlobal,  // import kind
1580
              kI32Code,         // type
1581
              0),               // mutability
1582
      SECTION(Memory, ENTRY_COUNT(1), kWithMaximum, 28, 28),
1583 1584 1585 1586
      SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
              WASM_INIT_EXPR_GLOBAL(1),  // dest addr
              U32V_1(3),                 // source size
              'a', 'b', 'c')             // data bytes
1587 1588 1589
  };
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
1590 1591 1592
  WasmInitExpr expr = std::move(result.value()->data_segments.back()).dest_addr;
  EXPECT_EQ(WasmInitExpr::kGlobalGet, expr.kind());
  EXPECT_EQ(1u, expr.immediate().index);
1593 1594 1595 1596 1597
}

TEST_F(WasmModuleVerifyTest, DataSegmentWithMutableImportedGlobal) {
  // Only an immutable imported global can be used as an init_expr.
  const byte data[] = {
1598 1599
      SECTION(Import,           // section header
              ENTRY_COUNT(1),   // number of imports
1600 1601
              ADD_COUNT('m'),   // module name
              ADD_COUNT('f'),   // global name
1602
              kExternalGlobal,  // import kind
1603
              kI32Code,         // type
1604
              1),               // mutability
1605
      SECTION(Memory, ENTRY_COUNT(1), kWithMaximum, 28, 28),
1606 1607 1608 1609
      SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
              WASM_INIT_EXPR_GLOBAL(0),  // dest addr
              U32V_1(3),                 // source size
              'a', 'b', 'c')             // data bytes
1610 1611 1612 1613 1614 1615
  };
  EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, DataSegmentWithImmutableGlobal) {
  // Only an immutable imported global can be used as an init_expr.
  const byte data[] = {
1616
      SECTION(Memory, ENTRY_COUNT(1), kWithMaximum, 28, 28),
1617
      SECTION(Global, ENTRY_COUNT(1),
1618
              kI32Code,                         // local type
1619 1620 1621 1622 1623 1624
              0,                                // immutable
              WASM_INIT_EXPR_I32V_3(0x9BBAA)),  // init
      SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
              WASM_INIT_EXPR_GLOBAL(0),  // dest addr
              U32V_1(3),                 // source size
              'a', 'b', 'c')             // data bytes
1625 1626 1627 1628
  };
  EXPECT_FAILURE(data);
}

1629
TEST_F(WasmModuleVerifyTest, OneDataSegment) {
1630
  const byte kDataSegmentSourceOffset = 24;
1631
  const byte data[] = {
1632
      SECTION(Memory, ENTRY_COUNT(1), kWithMaximum, 28, 28),
1633 1634 1635 1636
      SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
              WASM_INIT_EXPR_I32V_3(0x9BBAA),  // dest addr
              U32V_1(3),                       // source size
              'a', 'b', 'c')                   // data bytes
1637 1638 1639
  };

  {
1640
    EXPECT_VERIFIES(data);
1641
    ModuleResult result = DecodeModule(data, data + sizeof(data));
1642
    EXPECT_OK(result);
1643 1644 1645
    EXPECT_EQ(0u, result.value()->globals.size());
    EXPECT_EQ(0u, result.value()->functions.size());
    EXPECT_EQ(1u, result.value()->data_segments.size());
1646

1647
    const WasmDataSegment* segment = &result.value()->data_segments.back();
1648

1649 1650
    EXPECT_EQ(WasmInitExpr::kI32Const, segment->dest_addr.kind());
    EXPECT_EQ(0x9BBAA, segment->dest_addr.immediate().i32_const);
1651 1652
    EXPECT_EQ(kDataSegmentSourceOffset, segment->source.offset());
    EXPECT_EQ(3u, segment->source.length());
1653 1654
  }

1655
  EXPECT_OFF_END_FAILURE(data, 14);
1656 1657 1658
}

TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
1659 1660
  const byte kDataSegment0SourceOffset = 24;
  const byte kDataSegment1SourceOffset = kDataSegment0SourceOffset + 11;
1661

1662
  const byte data[] = {
1663
      SECTION(Memory, ENTRY_COUNT(1), kWithMaximum, 28, 28),
1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
      SECTION(Data,
              ENTRY_COUNT(2),  // segment count
              LINEAR_MEMORY_INDEX_0,
              WASM_INIT_EXPR_I32V_3(0x7FFEE),  // #0: dest addr
              U32V_1(4),                       // source size
              1, 2, 3, 4,                      // data bytes
              LINEAR_MEMORY_INDEX_0,
              WASM_INIT_EXPR_I32V_3(0x6DDCC),  // #1: dest addr
              U32V_1(10),                      // source size
              1, 2, 3, 4, 5, 6, 7, 8, 9, 10)   // data bytes
1674 1675 1676
  };

  {
1677
    ModuleResult result = DecodeModule(data, data + sizeof(data));
1678
    EXPECT_OK(result);
1679 1680 1681
    EXPECT_EQ(0u, result.value()->globals.size());
    EXPECT_EQ(0u, result.value()->functions.size());
    EXPECT_EQ(2u, result.value()->data_segments.size());
1682

1683 1684
    const WasmDataSegment* s0 = &result.value()->data_segments[0];
    const WasmDataSegment* s1 = &result.value()->data_segments[1];
1685

1686 1687
    EXPECT_EQ(WasmInitExpr::kI32Const, s0->dest_addr.kind());
    EXPECT_EQ(0x7FFEE, s0->dest_addr.immediate().i32_const);
1688 1689
    EXPECT_EQ(kDataSegment0SourceOffset, s0->source.offset());
    EXPECT_EQ(4u, s0->source.length());
1690

1691 1692
    EXPECT_EQ(WasmInitExpr::kI32Const, s1->dest_addr.kind());
    EXPECT_EQ(0x6DDCC, s1->dest_addr.immediate().i32_const);
1693 1694
    EXPECT_EQ(kDataSegment1SourceOffset, s1->source.offset());
    EXPECT_EQ(10u, s1->source.length());
1695 1696
  }

1697
  EXPECT_OFF_END_FAILURE(data, 14);
1698 1699
}

1700 1701
TEST_F(WasmModuleVerifyTest, DataWithoutMemory) {
  const byte data[] = {
1702 1703 1704 1705
      SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
              WASM_INIT_EXPR_I32V_3(0x9BBAA),  // dest addr
              U32V_1(3),                       // source size
              'a', 'b', 'c')                   // data bytes
1706 1707 1708 1709
  };
  EXPECT_FAILURE(data);
}

1710 1711 1712
TEST_F(WasmModuleVerifyTest, MaxMaximumMemorySize) {
  {
    const byte data[] = {
1713
        SECTION(Memory, ENTRY_COUNT(1), kWithMaximum, 0, U32V_3(65536))};
1714 1715 1716 1717
    EXPECT_VERIFIES(data);
  }
  {
    const byte data[] = {
1718
        SECTION(Memory, ENTRY_COUNT(1), kWithMaximum, 0, U32V_3(65537))};
1719 1720 1721 1722
    EXPECT_FAILURE(data);
  }
}

1723 1724 1725 1726 1727 1728 1729 1730 1731
TEST_F(WasmModuleVerifyTest, InvalidMemoryLimits) {
  {
    const byte kInvalidLimits = 0x15;
    const byte data[] = {
        SECTION(Memory, ENTRY_COUNT(1), kInvalidLimits, 0, 10)};
    EXPECT_FAILURE_WITH_MSG(data, "invalid memory limits flags 0x15");
  }
}

1732 1733
TEST_F(WasmModuleVerifyTest, DataSegment_wrong_init_type) {
  const byte data[] = {
1734
      SECTION(Memory, ENTRY_COUNT(1), kWithMaximum, 28, 28),
1735 1736 1737 1738
      SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
              WASM_INIT_EXPR_F64(9.9),  // dest addr
              U32V_1(3),                // source size
              'a', 'b', 'c')            // data bytes
1739 1740 1741
  };

  EXPECT_FAILURE(data);
1742 1743
}

1744 1745
TEST_F(WasmModuleVerifyTest, DataSegmentEndOverflow) {
  const byte data[] = {
1746
      SECTION(Memory,  // memory section
1747
              ENTRY_COUNT(1), kWithMaximum, 28, 28),
1748 1749 1750 1751 1752
      SECTION(Data,                      // data section
              ENTRY_COUNT(1),            // one entry
              LINEAR_MEMORY_INDEX_0,     // mem index
              WASM_INIT_EXPR_I32V_1(0),  // offset
              U32V_5(0xFFFFFFFF))        // size
1753 1754 1755 1756 1757
  };

  EXPECT_FAILURE(data);
}

1758
TEST_F(WasmModuleVerifyTest, OneIndirectFunction) {
1759
  static const byte data[] = {
1760
      // sig#0 ---------------------------------------------------------------
1761
      TYPE_SECTION_ONE_SIG_VOID_VOID,
1762
      // funcs ---------------------------------------------------------------
1763
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
1764
      // table declaration ---------------------------------------------------
1765
      SECTION(Table, ENTRY_COUNT(1), kFuncRefCode, 0, 1),
1766 1767
      // code ----------------------------------------------------------------
      ONE_EMPTY_BODY};
1768

1769 1770 1771
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
  if (result.ok()) {
1772
    EXPECT_EQ(1u, result.value()->types.size());
1773 1774 1775
    EXPECT_EQ(1u, result.value()->functions.size());
    EXPECT_EQ(1u, result.value()->tables.size());
    EXPECT_EQ(1u, result.value()->tables[0].initial_size);
1776 1777 1778
  }
}

1779 1780 1781
TEST_F(WasmModuleVerifyTest, ElementSectionWithInternalTable) {
  static const byte data[] = {
      // table ---------------------------------------------------------------
1782
      SECTION(Table, ENTRY_COUNT(1), kFuncRefCode, 0, 1),
1783
      // elements ------------------------------------------------------------
1784
      SECTION(Element, ENTRY_COUNT(0))};
1785 1786 1787 1788 1789 1790 1791

  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, ElementSectionWithImportedTable) {
  static const byte data[] = {
      // imports -------------------------------------------------------------
1792
      SECTION(Import, ENTRY_COUNT(1),
1793 1794
              ADD_COUNT('m'),  // module name
              ADD_COUNT('t'),  // table name
1795
              kExternalTable,  // import kind
1796
              kFuncRefCode,    // elem_type
1797 1798
              0,               // no maximum field
              1),              // initial size
1799
      // elements ------------------------------------------------------------
1800
      SECTION(Element, ENTRY_COUNT(0))};
1801 1802 1803 1804 1805 1806 1807 1808

  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, ElementSectionWithoutTable) {
  // Test that an element section without a table causes a validation error.
  static const byte data[] = {
      // elements ------------------------------------------------------------
1809 1810 1811 1812 1813
      SECTION(Element,
              ENTRY_COUNT(1),  // entry count
              0,               // table index
              0,               // offset
              0)               // number of elements
1814 1815 1816 1817 1818
  };

  EXPECT_FAILURE(data);
}

1819 1820 1821 1822
TEST_F(WasmModuleVerifyTest, Regression_735887) {
  // Test with an invalid function index in the element section.
  static const byte data[] = {
      // sig#0 ---------------------------------------------------------------
1823
      TYPE_SECTION_ONE_SIG_VOID_VOID,
1824
      // funcs ---------------------------------------------------------------
1825
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
1826
      // table declaration ---------------------------------------------------
1827
      SECTION(Table, ENTRY_COUNT(1), kFuncRefCode, 0, 1),
1828
      // elements ------------------------------------------------------------
1829 1830
      SECTION(Element,
              ENTRY_COUNT(1),  // entry count
1831
              TABLE_INDEX0, WASM_INIT_EXPR_I32V_1(0),
1832 1833
              1,     // elements count
              0x9A)  // invalid I32V as function index
1834 1835 1836 1837 1838
  };

  EXPECT_FAILURE(data);
}

1839 1840 1841
TEST_F(WasmModuleVerifyTest, OneIndirectFunction_one_entry) {
  static const byte data[] = {
      // sig#0 ---------------------------------------------------------------
1842
      TYPE_SECTION_ONE_SIG_VOID_VOID,
1843
      // funcs ---------------------------------------------------------------
1844
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
1845
      // table declaration ---------------------------------------------------
1846
      SECTION(Table, ENTRY_COUNT(1), kFuncRefCode, 0, 1),
1847
      // elements ------------------------------------------------------------
1848 1849
      SECTION(Element,
              ENTRY_COUNT(1),  // entry count
1850
              TABLE_INDEX0, WASM_INIT_EXPR_I32V_1(0),
1851
              1,  // elements count
1852 1853 1854
              FUNC_INDEX(0)),
      // code ----------------------------------------------------------------
      ONE_EMPTY_BODY};
1855 1856

  ModuleResult result = DecodeModule(data, data + sizeof(data));
1857
  EXPECT_OK(result);
1858
  EXPECT_EQ(1u, result.value()->types.size());
1859 1860 1861
  EXPECT_EQ(1u, result.value()->functions.size());
  EXPECT_EQ(1u, result.value()->tables.size());
  EXPECT_EQ(1u, result.value()->tables[0].initial_size);
1862 1863 1864 1865 1866
}

TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) {
  static const byte data[] = {
      // sig#0 -------------------------------------------------------
1867
      SECTION(Type,
1868 1869 1870
              ENTRY_COUNT(2),            // --
              SIG_ENTRY_v_v,             // void -> void
              SIG_ENTRY_v_x(kI32Code)),  // void -> i32
1871
      // funcs ------------------------------------------------------
1872
      FOUR_EMPTY_FUNCTIONS(SIG_INDEX(0)),
1873
      // table declaration -------------------------------------------
1874
      SECTION(Table, ENTRY_COUNT(1), kFuncRefCode, 0, 8),
1875
      // table elements ----------------------------------------------
1876 1877
      SECTION(Element,
              ENTRY_COUNT(1),  // entry count
1878
              TABLE_INDEX0, WASM_INIT_EXPR_I32V_1(0),
1879 1880 1881
              ADD_COUNT(FUNC_INDEX(0), FUNC_INDEX(1), FUNC_INDEX(2),
                        FUNC_INDEX(3), FUNC_INDEX(0), FUNC_INDEX(1),
                        FUNC_INDEX(2), FUNC_INDEX(3))),
1882
      FOUR_EMPTY_BODIES};
1883

1884
  ModuleResult result = DecodeModule(data, data + sizeof(data));
1885
  EXPECT_OK(result);
1886
  EXPECT_EQ(2u, result.value()->types.size());
1887 1888 1889
  EXPECT_EQ(4u, result.value()->functions.size());
  EXPECT_EQ(1u, result.value()->tables.size());
  EXPECT_EQ(8u, result.value()->tables[0].initial_size);
1890 1891
}

1892 1893 1894
TEST_F(WasmModuleVerifyTest, ElementSectionMultipleTables) {
  // Test that if we have multiple tables, in the element section we can target
  // and initialize all tables.
1895
  WASM_FEATURE_SCOPE(reftypes);
1896 1897
  static const byte data[] = {
      // sig#0 ---------------------------------------------------------------
1898
      TYPE_SECTION_ONE_SIG_VOID_VOID,
1899
      // funcs ---------------------------------------------------------------
1900
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
1901
      // table declaration ---------------------------------------------------
1902
      SECTION(Table, ENTRY_COUNT(2),  // section header
1903 1904
              kFuncRefCode, 0, 5,     // table 0
              kFuncRefCode, 0, 9),    // table 1
1905
      // elements ------------------------------------------------------------
1906 1907
      SECTION(Element,
              ENTRY_COUNT(2),            // entry count
1908
              TABLE_INDEX0,              // element for table 0
1909 1910 1911 1912 1913
              WASM_INIT_EXPR_I32V_1(0),  // index
              1,                         // elements count
              FUNC_INDEX(0),             // function
              TABLE_INDEX(1),            // element for table 1
              WASM_INIT_EXPR_I32V_1(7),  // index
1914
              kExternalFunction,         // type
1915 1916 1917
              2,                         // elements count
              FUNC_INDEX(0),             // entry 0
              FUNC_INDEX(0)),            // entry 1
1918 1919
      // code ----------------------------------------------------------------
      ONE_EMPTY_BODY};
1920 1921 1922 1923 1924 1925 1926

  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, ElementSectionMixedTables) {
  // Test that if we have multiple tables, both imported and module-defined, in
  // the element section we can target and initialize all tables.
1927
  WASM_FEATURE_SCOPE(reftypes);
1928 1929
  static const byte data[] = {
      // sig#0 ---------------------------------------------------------------
1930
      TYPE_SECTION_ONE_SIG_VOID_VOID,
1931
      // imports -------------------------------------------------------------
1932
      SECTION(Import, ENTRY_COUNT(2),
1933 1934
              ADD_COUNT('m'),  // module name
              ADD_COUNT('t'),  // table name
1935
              kExternalTable,  // import kind
1936
              kFuncRefCode,    // elem_type
1937 1938
              0,               // no maximum field
              5,               // initial size
1939 1940
              ADD_COUNT('m'),  // module name
              ADD_COUNT('s'),  // table name
1941
              kExternalTable,  // import kind
1942
              kFuncRefCode,    // elem_type
1943 1944
              0,               // no maximum field
              10),             // initial size
1945
      // funcs ---------------------------------------------------------------
1946
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
1947
      // table declaration ---------------------------------------------------
1948
      SECTION(Table, ENTRY_COUNT(2),  // section header
1949 1950
              kFuncRefCode, 0, 15,    // table 0
              kFuncRefCode, 0, 19),   // table 1
1951
      // elements ------------------------------------------------------------
1952 1953
      SECTION(Element,
              4,                          // entry count
1954
              TABLE_INDEX0,               // element for table 0
1955 1956 1957 1958 1959
              WASM_INIT_EXPR_I32V_1(0),   // index
              1,                          // elements count
              FUNC_INDEX(0),              // function
              TABLE_INDEX(1),             // element for table 1
              WASM_INIT_EXPR_I32V_1(7),   // index
1960
              kExternalFunction,          // type
1961 1962 1963 1964 1965
              2,                          // elements count
              FUNC_INDEX(0),              // entry 0
              FUNC_INDEX(0),              // entry 1
              TABLE_INDEX(2),             // element for table 2
              WASM_INIT_EXPR_I32V_1(12),  // index
1966
              kExternalFunction,          // type
1967 1968 1969 1970
              1,                          // elements count
              FUNC_INDEX(0),              // function
              TABLE_INDEX(3),             // element for table 1
              WASM_INIT_EXPR_I32V_1(17),  // index
1971
              kExternalFunction,          // type
1972 1973 1974
              2,                          // elements count
              FUNC_INDEX(0),              // entry 0
              FUNC_INDEX(0)),             // entry 1
1975 1976
      // code ----------------------------------------------------------------
      ONE_EMPTY_BODY};
1977 1978 1979 1980 1981 1982 1983

  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, ElementSectionMultipleTablesArbitraryOrder) {
  // Test that the order in which tables are targeted in the element secion
  // can be arbitrary.
1984
  WASM_FEATURE_SCOPE(reftypes);
1985 1986
  static const byte data[] = {
      // sig#0 ---------------------------------------------------------------
1987
      TYPE_SECTION_ONE_SIG_VOID_VOID,
1988
      // funcs ---------------------------------------------------------------
1989
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
1990
      // table declaration ---------------------------------------------------
1991
      SECTION(Table, ENTRY_COUNT(2),  // section header
1992 1993
              kFuncRefCode, 0, 5,     // table 0
              kFuncRefCode, 0, 9),    // table 1
1994
      // elements ------------------------------------------------------------
1995 1996
      SECTION(Element,
              ENTRY_COUNT(3),            // entry count
1997
              TABLE_INDEX0,              // element for table 1
1998 1999 2000 2001 2002
              WASM_INIT_EXPR_I32V_1(0),  // index
              1,                         // elements count
              FUNC_INDEX(0),             // function
              TABLE_INDEX(1),            // element for table 0
              WASM_INIT_EXPR_I32V_1(7),  // index
2003
              kExternalFunction,         // type
2004 2005 2006
              2,                         // elements count
              FUNC_INDEX(0),             // entry 0
              FUNC_INDEX(0),             // entry 1
2007
              TABLE_INDEX0,              // element for table 1
2008 2009 2010
              WASM_INIT_EXPR_I32V_1(3),  // index
              1,                         // elements count
              FUNC_INDEX(0)),            // function
2011 2012
      // code ----------------------------------------------------------------
      ONE_EMPTY_BODY};
2013 2014 2015 2016 2017 2018 2019

  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, ElementSectionMixedTablesArbitraryOrder) {
  // Test that the order in which tables are targeted in the element secion can
  // be arbitrary. In this test, tables can be both imported and module-defined.
2020
  WASM_FEATURE_SCOPE(reftypes);
2021 2022
  static const byte data[] = {
      // sig#0 ---------------------------------------------------------------
2023
      TYPE_SECTION_ONE_SIG_VOID_VOID,
2024
      // imports -------------------------------------------------------------
2025
      SECTION(Import, ENTRY_COUNT(2),
2026 2027
              ADD_COUNT('m'),  // module name
              ADD_COUNT('t'),  // table name
2028
              kExternalTable,  // import kind
2029
              kFuncRefCode,    // elem_type
2030 2031
              0,               // no maximum field
              5,               // initial size
2032 2033
              ADD_COUNT('m'),  // module name
              ADD_COUNT('s'),  // table name
2034
              kExternalTable,  // import kind
2035
              kFuncRefCode,    // elem_type
2036 2037
              0,               // no maximum field
              10),             // initial size
2038
      // funcs ---------------------------------------------------------------
2039
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
2040
      // table declaration ---------------------------------------------------
2041
      SECTION(Table, ENTRY_COUNT(2),  // section header
2042 2043
              kFuncRefCode, 0, 15,    // table 0
              kFuncRefCode, 0, 19),   // table 1
2044
      // elements ------------------------------------------------------------
2045 2046 2047 2048
      SECTION(Element,
              4,                          // entry count
              TABLE_INDEX(2),             // element for table 0
              WASM_INIT_EXPR_I32V_1(10),  // index
2049
              kExternalFunction,          // type
2050 2051 2052 2053
              1,                          // elements count
              FUNC_INDEX(0),              // function
              TABLE_INDEX(3),             // element for table 1
              WASM_INIT_EXPR_I32V_1(17),  // index
2054
              kExternalFunction,          // type
2055 2056 2057
              2,                          // elements count
              FUNC_INDEX(0),              // entry 0
              FUNC_INDEX(0),              // entry 1
2058
              TABLE_INDEX0,               // element for table 2
2059 2060 2061 2062 2063
              WASM_INIT_EXPR_I32V_1(2),   // index
              1,                          // elements count
              FUNC_INDEX(0),              // function
              TABLE_INDEX(1),             // element for table 1
              WASM_INIT_EXPR_I32V_1(7),   // index
2064
              kExternalFunction,          // type
2065 2066 2067
              2,                          // elements count
              FUNC_INDEX(0),              // entry 0
              FUNC_INDEX(0)),             // entry 1
2068 2069
      // code ----------------------------------------------------------------
      ONE_EMPTY_BODY};
2070 2071 2072 2073

  EXPECT_VERIFIES(data);
}

2074 2075
TEST_F(WasmModuleVerifyTest, ElementSectionInitExternRefTableWithFuncRef) {
  WASM_FEATURE_SCOPE(reftypes);
2076 2077
  static const byte data[] = {
      // sig#0 ---------------------------------------------------------------
2078
      TYPE_SECTION_ONE_SIG_VOID_VOID,
2079
      // funcs ---------------------------------------------------------------
2080
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
2081
      // table declaration ---------------------------------------------------
2082
      SECTION(Table, ENTRY_COUNT(2),  // section header
2083 2084
              kExternRefCode, 0, 5,   // table 0
              kFuncRefCode, 0, 9),    // table 1
2085
      // elements ------------------------------------------------------------
2086 2087
      SECTION(Element,
              ENTRY_COUNT(2),            // entry count
2088
              TABLE_INDEX0,              // element for table 0
2089 2090 2091 2092 2093
              WASM_INIT_EXPR_I32V_1(0),  // index
              1,                         // elements count
              FUNC_INDEX(0),             // function
              TABLE_INDEX(1),            // element for table 1
              WASM_INIT_EXPR_I32V_1(7),  // index
2094
              kExternalFunction,         // type
2095 2096 2097
              2,                         // elements count
              FUNC_INDEX(0),             // entry 0
              FUNC_INDEX(0)),            // entry 1
2098 2099
      // code ----------------------------------------------------------------
      ONE_EMPTY_BODY,
2100 2101
  };

2102 2103 2104 2105
  EXPECT_FAILURE_WITH_MSG(data,
                          "An active element segment with function indices as "
                          "elements must reference a table of type funcref. "
                          "Instead, table 0 of type externref is referenced.");
2106 2107
}

2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148
TEST_F(WasmModuleVerifyTest, ElementSectionInitFuncRefTableWithFuncRefNull) {
  WASM_FEATURE_SCOPE(reftypes);
  static const byte data[] = {
      // table declaration ---------------------------------------------------
      SECTION(Table, ENTRY_COUNT(1),  // section header
              kFuncRefCode, 0, 9),    // table 0
      // elements ------------------------------------------------------------
      SECTION(Element,
              ENTRY_COUNT(1),                      // entry count
              ACTIVE_WITH_ELEMENTS, TABLE_INDEX0,  // element for table 0
              WASM_INIT_EXPR_I32V_1(0),            // index
              kFuncRefCode,                        // .
              1,                                   // elements count
              WASM_INIT_EXPR_FUNC_REF_NULL)        // function
  };

  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, ElementSectionInitFuncRefTableWithExternRefNull) {
  WASM_FEATURE_SCOPE(reftypes);
  static const byte data[] = {
      // table declaration ---------------------------------------------------
      SECTION(Table, ENTRY_COUNT(1),  // section header
              kFuncRefCode, 0, 9),    // table 0
      // elements ------------------------------------------------------------
      SECTION(Element,
              ENTRY_COUNT(1),                      // entry count
              ACTIVE_WITH_ELEMENTS, TABLE_INDEX0,  // element for table 0
              WASM_INIT_EXPR_I32V_1(0),            // index
              kFuncRefCode,                        // .
              1,                                   // elements count
              WASM_INIT_EXPR_EXTERN_REF_NULL)      // function
  };

  EXPECT_FAILURE_WITH_MSG(
      data,
      "Invalid type in the init expression. The expected "
      "type is 'funcref', but the actual type is 'externref'.");
}

2149 2150
TEST_F(WasmModuleVerifyTest, ElementSectionDontInitExternRefImportedTable) {
  // Test that imported tables of type ExternRef cannot be initialized in the
2151
  // elements section.
2152
  WASM_FEATURE_SCOPE(reftypes);
2153 2154
  static const byte data[] = {
      // sig#0 ---------------------------------------------------------------
2155
      TYPE_SECTION_ONE_SIG_VOID_VOID,
2156
      // imports -------------------------------------------------------------
2157
      SECTION(Import, ENTRY_COUNT(2),
2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169
              ADD_COUNT('m'),  // module name
              ADD_COUNT('t'),  // table name
              kExternalTable,  // import kind
              kFuncRefCode,    // elem_type
              0,               // no maximum field
              5,               // initial size
              ADD_COUNT('m'),  // module name
              ADD_COUNT('s'),  // table name
              kExternalTable,  // import kind
              kExternRefCode,  // elem_type
              0,               // no maximum field
              10),             // initial size
2170
      // funcs ---------------------------------------------------------------
2171
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
2172
      // table declaration ---------------------------------------------------
2173
      SECTION(Table, ENTRY_COUNT(2),  // section header
2174 2175
              kFuncRefCode, 0, 15,    // table 0
              kFuncRefCode, 0, 19),   // table 1
2176
      // elements ------------------------------------------------------------
2177 2178
      SECTION(Element,
              ENTRY_COUNT(4),             // entry count
2179
              TABLE_INDEX0,               // element for table 0
2180 2181 2182 2183 2184
              WASM_INIT_EXPR_I32V_1(10),  // index
              1,                          // elements count
              FUNC_INDEX(0),              // function
              TABLE_INDEX(1),             // element for table 1
              WASM_INIT_EXPR_I32V_1(17),  // index
2185
              kExternalFunction,          // type
2186 2187 2188
              2,                          // elements count
              FUNC_INDEX(0),              // entry 0
              FUNC_INDEX(0)),             // entry 1
2189 2190 2191 2192 2193
  };

  EXPECT_FAILURE(data);
}

2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204
TEST_F(WasmModuleVerifyTest, ElementSectionGlobalGetOutOfBounds) {
  WASM_FEATURE_SCOPE(reftypes);
  static const byte data[] = {
      SECTION(Element, ENTRY_COUNT(1),
              0x05,            // Mode: Passive with expressions-as-elements
              kFuncRefCode,    // type
              ENTRY_COUNT(1),  // element count
              kExprGlobalGet, 0x00, kExprEnd)};  // init. expression
  EXPECT_FAILURE_WITH_MSG(data, "Out-of-bounds global index 0");
}

2205 2206 2207
TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) {
  static const byte data[] = {
      // sig#0 -------------------------------------------------------
2208
      TYPE_SECTION_ONE_SIG_VOID_VOID,
2209
      // indirect table ----------------------------------------------
2210
      SECTION(Table, ENTRY_COUNT(1), 1, 0, 0)};
2211 2212 2213 2214 2215 2216 2217

  EXPECT_FAILURE(data);
}

TEST_F(WasmModuleVerifyTest, IndirectFunctionInvalidIndex) {
  static const byte data[] = {
      // sig#0 -------------------------------------------------------
2218
      TYPE_SECTION_ONE_SIG_VOID_VOID,
2219
      // functions ---------------------------------------------------
2220
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
2221
      // indirect table ----------------------------------------------
2222
      SECTION(Table, ENTRY_COUNT(1), 1, 1, 0)};
2223 2224 2225 2226

  EXPECT_FAILURE(data);
}

2227 2228
TEST_F(WasmModuleVerifyTest, MultipleTablesWithoutFlag) {
  static const byte data[] = {
2229 2230
      SECTION(Table,           // table section
              ENTRY_COUNT(2),  // 2 tables
2231
              kFuncRefCode,    // table 1: type
2232 2233
              0,               // table 1: no maximum
              10,              // table 1: minimum size
2234
              kFuncRefCode,    // table 2: type
2235 2236
              0,               // table 2: no maximum
              10),             // table 2: minimum size
2237 2238 2239 2240 2241
  };
  EXPECT_FAILURE(data);
}

TEST_F(WasmModuleVerifyTest, MultipleTablesWithFlag) {
2242 2243
  WASM_FEATURE_SCOPE(reftypes);
  static const byte data[] = {
2244 2245 2246 2247 2248 2249 2250 2251
      SECTION(Table,           // table section
              ENTRY_COUNT(2),  // 2 tables
              kFuncRefCode,    // table 1: type
              0,               // table 1: no maximum
              10,              // table 1: minimum size
              kExternRefCode,  // table 2: type
              0,               // table 2: no maximum
              11),             // table 2: minimum size
2252 2253 2254 2255 2256
  };

  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);

2257
  EXPECT_EQ(2u, result.value()->tables.size());
2258

2259
  EXPECT_EQ(10u, result.value()->tables[0].initial_size);
2260
  EXPECT_EQ(kWasmFuncRef, result.value()->tables[0].type);
2261

2262
  EXPECT_EQ(11u, result.value()->tables[1].initial_size);
2263
  EXPECT_EQ(kWasmExternRef, result.value()->tables[1].type);
2264 2265
}

2266 2267 2268 2269 2270
TEST_F(WasmModuleVerifyTest, TypedFunctionTable) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);

  static const byte data[] = {
2271 2272 2273 2274 2275
      SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_v_x(kI32Code)),
      SECTION(Table,           // table section
              ENTRY_COUNT(1),  // 1 table
              kOptRefCode, 0,  // table 0: type
              0, 10)};         // table 0: limits
2276 2277 2278 2279 2280 2281

  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
  EXPECT_EQ(ValueType::Ref(0, kNullable), result.value()->tables[0].type);
}

2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299
TEST_F(WasmModuleVerifyTest, NullableTableIllegalInitializer) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);

  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_v_v),  // type section
      ONE_EMPTY_FUNCTION(0),                         // function section
      SECTION(Table,                                 // table section
              ENTRY_COUNT(1),                        // 1 table
              kOptRefCode, 0,                        // table 0: type
              0, 10,                                 // table 0: limits
              kExprRefFunc, 0, kExprEnd)};           // table 0: initializer

  EXPECT_FAILURE_WITH_MSG(
      data,
      "section was shorter than expected size (8 bytes expected, 5 decoded)");
}

2300 2301 2302 2303 2304 2305 2306
TEST_F(WasmModuleVerifyTest, IllegalTableTypes) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);

  using Vec = std::vector<byte>;

2307 2308 2309 2310
  static Vec table_types[] = {{kOptRefCode, 0},
                              {kOptRefCode, 1},
                              {kOptRefCode, kI31RefCode},
                              {kI31RefCode},
2311
                              {kRttWithDepthCode, 2, 0}};
2312 2313 2314 2315

  for (Vec type : table_types) {
    Vec data = {
        SECTION(Type, ENTRY_COUNT(2),
2316 2317
                WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kI32Code, true)),
                WASM_ARRAY_DEF(kI32Code, true)),
2318 2319 2320 2321 2322 2323 2324 2325 2326 2327
        kTableSectionCode, static_cast<byte>(type.size() + 3), byte{1}};
    // Last elements are section size and entry count

    // Add table type
    data.insert(data.end(), type.begin(), type.end());
    // Add table limits
    data.insert(data.end(), {byte{0}, byte{10}});

    auto result = DecodeModule(data.data(), data.data() + data.size());

2328 2329 2330
    EXPECT_NOT_OK(result,
                  "Currently, only externref and function references are "
                  "allowed as table types");
2331 2332 2333
  }
}

2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368
TEST_F(WasmModuleVerifyTest, NonNullableTable) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);

  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_v_v),  // type section
      ONE_EMPTY_FUNCTION(0),                         // function section
      SECTION(Table,                                 // table section
              ENTRY_COUNT(1),                        // 1 table
              kRefCode, 0,                           // table 0: type
              0, 10,                                 // table 0: limits
              kExprRefFunc, 0, kExprEnd),  // table 0: init. expression
      SECTION(Code, ENTRY_COUNT(1), NOP_BODY)};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
  EXPECT_EQ(ValueType::Ref(0, kNonNullable), result.value()->tables[0].type);
}

TEST_F(WasmModuleVerifyTest, NonNullableTableNoInitializer) {
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);

  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_v_x(kI32Code)),
      SECTION(Table,           // table section
              ENTRY_COUNT(2),  // 2 tables
              kRefCode, 0,     // table 0: type
              0, 10,           // table 0: limits
              kRefCode, 0,     // table 1: type
              5, 6)};          // table 1: limits

  EXPECT_FAILURE_WITH_MSG(data,
                          "invalid opcode 0x6b in initializer expression");
}

2369 2370 2371
TEST_F(WasmModuleVerifyTest, TieringCompilationHints) {
  WASM_FEATURE_SCOPE(compilation_hints);
  static const byte data[] = {
2372 2373
      TYPE_SECTION(1, SIG_ENTRY_v_v),
      FUNCTION_SECTION(3, 0, 0, 0),
2374 2375 2376
      SECTION_COMPILATION_HINTS(BASELINE_TIER_BASELINE | TOP_TIER_BASELINE,
                                BASELINE_TIER_BASELINE | TOP_TIER_OPTIMIZED,
                                BASELINE_TIER_OPTIMIZED | TOP_TIER_OPTIMIZED),
2377 2378 2379 2380 2381 2382 2383 2384 2385
      SECTION(Code, ENTRY_COUNT(3), NOP_BODY, NOP_BODY, NOP_BODY),
  };

  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);

  EXPECT_EQ(3u, result.value()->compilation_hints.size());
  EXPECT_EQ(WasmCompilationHintStrategy::kDefault,
            result.value()->compilation_hints[0].strategy);
2386
  EXPECT_EQ(WasmCompilationHintTier::kBaseline,
2387
            result.value()->compilation_hints[0].baseline_tier);
2388
  EXPECT_EQ(WasmCompilationHintTier::kBaseline,
2389
            result.value()->compilation_hints[0].top_tier);
2390 2391 2392
  EXPECT_EQ(WasmCompilationHintStrategy::kDefault,
            result.value()->compilation_hints[1].strategy);
  EXPECT_EQ(WasmCompilationHintTier::kBaseline,
2393
            result.value()->compilation_hints[1].baseline_tier);
2394
  EXPECT_EQ(WasmCompilationHintTier::kOptimized,
2395
            result.value()->compilation_hints[1].top_tier);
2396 2397
  EXPECT_EQ(WasmCompilationHintStrategy::kDefault,
            result.value()->compilation_hints[2].strategy);
2398
  EXPECT_EQ(WasmCompilationHintTier::kOptimized,
2399
            result.value()->compilation_hints[2].baseline_tier);
2400
  EXPECT_EQ(WasmCompilationHintTier::kOptimized,
2401
            result.value()->compilation_hints[2].top_tier);
2402 2403
}

2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427
TEST_F(WasmModuleVerifyTest, BranchHinting) {
  WASM_FEATURE_SCOPE(branch_hinting);
  static const byte data[] = {
      TYPE_SECTION(1, SIG_ENTRY_v_v), FUNCTION_SECTION(2, 0, 0),
      SECTION_BRANCH_HINTS(ENTRY_COUNT(2), 0 /*func_index*/, 0 /*reserved*/,
                           ENTRY_COUNT(1), 1 /*likely*/, 2 /* if offset*/,
                           1 /*func_index*/, 0 /*reserved*/, ENTRY_COUNT(1),
                           0 /*unlikely*/, 4 /* br_if offset*/),
      SECTION(Code, ENTRY_COUNT(2),
              ADD_COUNT(0, /*no locals*/
                        WASM_IF(WASM_I32V_1(1), WASM_NOP), WASM_END),
              ADD_COUNT(0, /*no locals*/
                        WASM_BLOCK(WASM_BR_IF(0, WASM_I32V_1(1))), WASM_END))};

  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);

  EXPECT_EQ(2u, result.value()->branch_hints.size());
  EXPECT_EQ(WasmBranchHint::kLikely,
            result.value()->branch_hints[0].GetHintFor(2));
  EXPECT_EQ(WasmBranchHint::kUnlikely,
            result.value()->branch_hints[1].GetHintFor(4));
}

2428 2429
class WasmSignatureDecodeTest : public TestWithZone {
 public:
2430
  WasmFeatures enabled_features_ = WasmFeatures::None();
2431

2432
  const FunctionSig* DecodeSig(const byte* start, const byte* end) {
2433 2434
    return DecodeWasmSignatureForTesting(enabled_features_, zone(), start, end);
  }
2435
};
2436 2437

TEST_F(WasmSignatureDecodeTest, Ok_v_v) {
2438
  static const byte data[] = {SIG_ENTRY_v_v};
2439
  v8::internal::AccountingAllocator allocator;
2440
  Zone zone(&allocator, ZONE_NAME);
2441
  const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2442 2443

  EXPECT_TRUE(sig != nullptr);
2444 2445
  EXPECT_EQ(0u, sig->parameter_count());
  EXPECT_EQ(0u, sig->return_count());
2446 2447 2448
}

TEST_F(WasmSignatureDecodeTest, Ok_t_v) {
2449
  WASM_FEATURE_SCOPE(reftypes);
2450 2451
  for (size_t i = 0; i < arraysize(kValueTypes); i++) {
    ValueTypePair ret_type = kValueTypes[i];
2452
    const byte data[] = {SIG_ENTRY_x(ret_type.code)};
2453
    const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2454 2455

    EXPECT_TRUE(sig != nullptr);
2456 2457
    EXPECT_EQ(0u, sig->parameter_count());
    EXPECT_EQ(1u, sig->return_count());
2458 2459 2460 2461 2462
    EXPECT_EQ(ret_type.type, sig->GetReturn());
  }
}

TEST_F(WasmSignatureDecodeTest, Ok_v_t) {
2463
  WASM_FEATURE_SCOPE(reftypes);
2464 2465
  for (size_t i = 0; i < arraysize(kValueTypes); i++) {
    ValueTypePair param_type = kValueTypes[i];
2466
    const byte data[] = {SIG_ENTRY_v_x(param_type.code)};
2467
    const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2468 2469

    EXPECT_TRUE(sig != nullptr);
2470 2471
    EXPECT_EQ(1u, sig->parameter_count());
    EXPECT_EQ(0u, sig->return_count());
2472 2473 2474 2475 2476
    EXPECT_EQ(param_type.type, sig->GetParam(0));
  }
}

TEST_F(WasmSignatureDecodeTest, Ok_t_t) {
2477
  WASM_FEATURE_SCOPE(reftypes);
2478 2479 2480 2481
  for (size_t i = 0; i < arraysize(kValueTypes); i++) {
    ValueTypePair ret_type = kValueTypes[i];
    for (size_t j = 0; j < arraysize(kValueTypes); j++) {
      ValueTypePair param_type = kValueTypes[j];
2482
      const byte data[] = {SIG_ENTRY_x_x(ret_type.code, param_type.code)};
2483
      const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2484 2485

      EXPECT_TRUE(sig != nullptr);
2486 2487
      EXPECT_EQ(1u, sig->parameter_count());
      EXPECT_EQ(1u, sig->return_count());
2488 2489 2490 2491 2492 2493 2494
      EXPECT_EQ(param_type.type, sig->GetParam(0));
      EXPECT_EQ(ret_type.type, sig->GetReturn());
    }
  }
}

TEST_F(WasmSignatureDecodeTest, Ok_i_tt) {
2495
  WASM_FEATURE_SCOPE(reftypes);
2496 2497 2498 2499
  for (size_t i = 0; i < arraysize(kValueTypes); i++) {
    ValueTypePair p0_type = kValueTypes[i];
    for (size_t j = 0; j < arraysize(kValueTypes); j++) {
      ValueTypePair p1_type = kValueTypes[j];
2500
      const byte data[] = {
2501
          SIG_ENTRY_x_xx(kI32Code, p0_type.code, p1_type.code)};
2502
      const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2503 2504

      EXPECT_TRUE(sig != nullptr);
2505 2506
      EXPECT_EQ(2u, sig->parameter_count());
      EXPECT_EQ(1u, sig->return_count());
2507 2508 2509 2510 2511 2512
      EXPECT_EQ(p0_type.type, sig->GetParam(0));
      EXPECT_EQ(p1_type.type, sig->GetParam(1));
    }
  }
}

2513
TEST_F(WasmSignatureDecodeTest, Ok_tt_tt) {
2514
  WASM_FEATURE_SCOPE(reftypes);
2515 2516 2517 2518 2519 2520
  for (size_t i = 0; i < arraysize(kValueTypes); i++) {
    ValueTypePair p0_type = kValueTypes[i];
    for (size_t j = 0; j < arraysize(kValueTypes); j++) {
      ValueTypePair p1_type = kValueTypes[j];
      const byte data[] = {SIG_ENTRY_xx_xx(p0_type.code, p1_type.code,
                                           p0_type.code, p1_type.code)};
2521
      const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533

      EXPECT_TRUE(sig != nullptr);
      EXPECT_EQ(2u, sig->parameter_count());
      EXPECT_EQ(2u, sig->return_count());
      EXPECT_EQ(p0_type.type, sig->GetParam(0));
      EXPECT_EQ(p1_type.type, sig->GetParam(1));
      EXPECT_EQ(p0_type.type, sig->GetReturn(0));
      EXPECT_EQ(p1_type.type, sig->GetReturn(1));
    }
  }
}

2534
TEST_F(WasmSignatureDecodeTest, TooManyParams) {
2535
  static const byte data[] = {kWasmFunctionTypeCode,
2536
                              WASM_I32V_3(kV8MaxWasmFunctionParams + 1),
2537
                              kI32Code, 0};
2538
  const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2539 2540 2541 2542 2543
  EXPECT_FALSE(sig != nullptr);
}

TEST_F(WasmSignatureDecodeTest, TooManyReturns) {
  for (int i = 0; i < 2; i++) {
2544 2545
    byte data[] = {kWasmFunctionTypeCode, 0,
                   WASM_I32V_3(kV8MaxWasmFunctionReturns + 1), kI32Code};
2546
    const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2547 2548 2549 2550
    EXPECT_EQ(nullptr, sig);
  }
}

2551 2552 2553
TEST_F(WasmSignatureDecodeTest, Fail_off_end) {
  byte data[256];
  for (int p = 0; p <= 255; p = p + 1 + p * 3) {
2554
    for (int i = 0; i <= p; i++) data[i] = kI32Code;
2555 2556 2557 2558
    data[0] = static_cast<byte>(p);

    for (int i = 0; i < p + 1; i++) {
      // Should fall off the end for all signatures.
2559
      const FunctionSig* sig = DecodeSig(data, data + i);
2560 2561 2562 2563 2564
      EXPECT_EQ(nullptr, sig);
    }
  }
}

2565 2566 2567
TEST_F(WasmSignatureDecodeTest, Fail_externref_without_flag) {
  // Disable ExternRef support and check that decoding fails.
  WASM_FEATURE_SCOPE_VAL(reftypes, false);
2568
  byte ref_types[] = {kFuncRefCode, kExternRefCode};
2569
  for (byte invalid_type : ref_types) {
2570
    for (size_t i = 0;; i++) {
2571
      byte data[] = {SIG_ENTRY_x_xx(kI32Code, kI32Code, kI32Code)};
2572
      if (i >= arraysize(data)) break;
2573
      data[i] = invalid_type;
2574
      const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2575 2576
      EXPECT_EQ(nullptr, sig);
    }
2577 2578 2579
  }
}

2580 2581
TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) {
  byte kInvalidType = 76;
2582
  for (size_t i = 0;; i++) {
2583
    byte data[] = {SIG_ENTRY_x_xx(kI32Code, kI32Code, kI32Code)};
2584
    if (i >= arraysize(data)) break;
2585
    data[i] = kInvalidType;
2586
    const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2587 2588 2589 2590
    EXPECT_EQ(nullptr, sig);
  }
}

2591
TEST_F(WasmSignatureDecodeTest, Fail_invalid_ret_type1) {
2592
  static const byte data[] = {SIG_ENTRY_x_x(kVoidCode, kI32Code)};
2593
  const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2594 2595
  EXPECT_EQ(nullptr, sig);
}
2596

2597
TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type1) {
2598
  static const byte data[] = {SIG_ENTRY_x_x(kI32Code, kVoidCode)};
2599
  const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2600 2601 2602 2603
  EXPECT_EQ(nullptr, sig);
}

TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) {
2604
  static const byte data[] = {SIG_ENTRY_x_xx(kI32Code, kI32Code, kVoidCode)};
2605
  const FunctionSig* sig = DecodeSig(data, data + sizeof(data));
2606
  EXPECT_EQ(nullptr, sig);
2607 2608
}

2609 2610
class WasmFunctionVerifyTest : public TestWithIsolateAndZone {
 public:
2611 2612 2613 2614
  FunctionResult DecodeWasmFunction(const ModuleWireBytes& wire_bytes,
                                    const WasmModule* module,
                                    const byte* function_start,
                                    const byte* function_end) {
2615 2616
    WasmFeatures enabled_features;
    return DecodeWasmFunctionForTesting(enabled_features, zone(), wire_bytes,
2617 2618 2619
                                        module, function_start, function_end,
                                        isolate()->counters());
  }
2620
};
2621 2622

TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
2623
  static const byte data[] = {
2624 2625 2626
      SIG_ENTRY_v_v,  // signature entry
      4,              // locals
      3,
2627
      kI32Code,  // --
2628
      4,
2629
      kI64Code,  // --
2630
      5,
2631
      kF32Code,  // --
2632
      6,
2633 2634
      kF64Code,  // --
      kExprEnd   // body
2635 2636
  };

2637 2638 2639
  WasmModule module;
  FunctionResult result = DecodeWasmFunction(ModuleWireBytes({}), &module, data,
                                             data + sizeof(data));
2640
  EXPECT_OK(result);
2641

2642 2643
  if (result.value() && result.ok()) {
    WasmFunction* function = result.value().get();
2644 2645
    EXPECT_EQ(0u, function->sig->parameter_count());
    EXPECT_EQ(0u, function->sig->return_count());
2646
    EXPECT_EQ(COUNT_ARGS(SIG_ENTRY_v_v), function->code.offset());
2647
    EXPECT_EQ(sizeof(data), function->code.end_offset());
2648
    // TODO(titzer): verify encoding of local declarations
2649 2650
  }
}
2651

2652 2653 2654 2655 2656
TEST_F(WasmModuleVerifyTest, SectionWithoutNameLength) {
  const byte data[] = {1};
  EXPECT_FAILURE(data);
}

2657 2658 2659 2660 2661 2662 2663 2664 2665 2666
TEST_F(WasmModuleVerifyTest, EmptyCustomSectionIsInvalid) {
  // An empty custom section is invalid, because at least one byte for the
  // length of the custom section name is required.
  const byte data[] = {
      0,  // unknown section code.
      0   // section length.
  };
  EXPECT_FAILURE(data);
}

2667
TEST_F(WasmModuleVerifyTest, TheLoneliestOfValidModulesTheTrulyEmptyOne) {
2668
  const byte data[] = {
2669
      0,  // unknown section code.
2670 2671 2672
      1,  // section length, only one byte for the name length.
      0,  // string length of 0.
          // Empty section name, no content, nothing but sadness.
2673
  };
2674
  EXPECT_VERIFIES(data);
2675 2676
}

2677 2678
TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionEmpty) {
  const byte data[] = {
2679
      UNKNOWN_SECTION(0),
2680 2681
  };
  EXPECT_VERIFIES(data);
2682 2683
}

2684 2685
TEST_F(WasmModuleVerifyTest, OnlyUnknownSectionNonEmpty) {
  const byte data[] = {
2686
      UNKNOWN_SECTION(5),
2687 2688 2689 2690 2691
      0xFF,
      0xFF,
      0xFF,
      0xFF,
      0xFF,  // section data
2692
  };
2693
  EXPECT_VERIFIES(data);
2694 2695
}

2696 2697
TEST_F(WasmModuleVerifyTest, SignatureFollowedByEmptyUnknownSection) {
  const byte data[] = {
2698
      // signatures
2699
      TYPE_SECTION_ONE_SIG_VOID_VOID,
2700
      // -----------------------------------------------------------
2701
      UNKNOWN_SECTION(0)};
2702 2703 2704 2705 2706
  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, SignatureFollowedByUnknownSection) {
  const byte data[] = {
2707
      // signatures
2708
      TYPE_SECTION_ONE_SIG_VOID_VOID,
2709
      // -----------------------------------------------------------
2710 2711 2712 2713 2714 2715
      UNKNOWN_SECTION(5),
      0xFF,
      0xFF,
      0xFF,
      0xFF,
      0xFF,
2716 2717
  };
  EXPECT_VERIFIES(data);
2718 2719
}

2720
TEST_F(WasmModuleVerifyTest, UnknownSectionOverflow) {
2721
  static const byte data[] = {
2722
      UNKNOWN_SECTION(9),
2723 2724 2725 2726 2727 2728 2729 2730 2731 2732
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8,
      9,
      10,  // 10 byte section
2733 2734 2735 2736
  };
  EXPECT_FAILURE(data);
}

2737
TEST_F(WasmModuleVerifyTest, UnknownSectionUnderflow) {
2738
  static const byte data[] = {
2739
      UNKNOWN_SECTION(333),
2740 2741 2742 2743
      1,
      2,
      3,
      4,  // 4 byte section
2744 2745 2746 2747
  };
  EXPECT_FAILURE(data);
}

2748 2749
TEST_F(WasmModuleVerifyTest, UnknownSectionSkipped) {
  static const byte data[] = {
2750
      UNKNOWN_SECTION(1),
2751
      0,  // one byte section
2752
      SECTION(Global, ENTRY_COUNT(1),
2753
              kI32Code,                    // memory type
2754 2755
              0,                           // exported
              WASM_INIT_EXPR_I32V_1(33)),  // init
2756
  };
2757
  ModuleResult result = DecodeModule(data, data + sizeof(data));
2758
  EXPECT_OK(result);
2759

2760 2761 2762
  EXPECT_EQ(1u, result.value()->globals.size());
  EXPECT_EQ(0u, result.value()->functions.size());
  EXPECT_EQ(0u, result.value()->data_segments.size());
2763

2764
  const WasmGlobal* global = &result.value()->globals.back();
2765

2766
  EXPECT_EQ(kWasmI32, global->type);
2767
  EXPECT_EQ(0u, global->offset);
2768 2769
}

2770
TEST_F(WasmModuleVerifyTest, ImportTable_empty) {
2771 2772
  static const byte data[] = {SECTION(Type, ENTRY_COUNT(0)),
                              SECTION(Import, ENTRY_COUNT(0))};
2773 2774 2775
  EXPECT_VERIFIES(data);
}

2776
TEST_F(WasmModuleVerifyTest, ImportTable_nosigs1) {
2777
  static const byte data[] = {SECTION(Import, ENTRY_COUNT(0))};
2778 2779 2780
  EXPECT_VERIFIES(data);
}

2781 2782 2783
TEST_F(WasmModuleVerifyTest, ImportTable_mutable_global) {
  {
    static const byte data[] = {
2784 2785
        SECTION(Import,           // section header
                ENTRY_COUNT(1),   // number of imports
2786 2787
                ADD_COUNT('m'),   // module name
                ADD_COUNT('f'),   // global name
2788
                kExternalGlobal,  // import kind
2789
                kI32Code,         // type
2790
                0),               // mutability
2791 2792 2793 2794 2795
    };
    EXPECT_VERIFIES(data);
  }
  {
    static const byte data[] = {
2796 2797
        SECTION(Import,           // section header
                ENTRY_COUNT(1),   // sig table
2798 2799
                ADD_COUNT('m'),   // module name
                ADD_COUNT('f'),   // global name
2800
                kExternalGlobal,  // import kind
2801
                kI32Code,         // type
2802
                1),               // mutability
2803
    };
2804
    EXPECT_VERIFIES(data);
2805 2806 2807
  }
}

2808 2809
TEST_F(WasmModuleVerifyTest, ImportTable_mutability_malformed) {
  static const byte data[] = {
2810 2811
      SECTION(Import,
              ENTRY_COUNT(1),   // --
2812 2813
              ADD_COUNT('m'),   // module name
              ADD_COUNT('g'),   // global name
2814
              kExternalGlobal,  // import kind
2815
              kI32Code,         // type
2816
              2),               // invalid mutability
2817 2818 2819 2820
  };
  EXPECT_FAILURE(data);
}

2821 2822
TEST_F(WasmModuleVerifyTest, ImportTable_nosigs2) {
  static const byte data[] = {
2823
      SECTION(Import, ENTRY_COUNT(1),  // sig table
2824 2825
              ADD_COUNT('m'),          // module name
              ADD_COUNT('f'),          // function name
2826 2827
              kExternalFunction,       // import kind
              SIG_INDEX(0)),           // sig index
2828
  };
2829 2830 2831 2832 2833
  EXPECT_FAILURE(data);
}

TEST_F(WasmModuleVerifyTest, ImportTable_invalid_sig) {
  static const byte data[] = {
2834 2835
      SECTION(Type, ENTRY_COUNT(0)),   // --
      SECTION(Import, ENTRY_COUNT(1),  // --
2836 2837
              ADD_COUNT('m'),          // module name
              ADD_COUNT('f'),          // function name
2838 2839
              kExternalFunction,       // import kind
              SIG_INDEX(0)),           // sig index
2840 2841 2842 2843 2844 2845
  };
  EXPECT_FAILURE(data);
}

TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
  static const byte data[] = {
2846
      // signatures
2847
      TYPE_SECTION_ONE_SIG_VOID_VOID,
2848
      SECTION(Import,
2849 2850 2851
              ENTRY_COUNT(1),     // --
              ADD_COUNT('m'),     // module name
              ADD_COUNT('f'),     // function name
2852 2853
              kExternalFunction,  // import kind
              SIG_INDEX(0)),      // sig index
2854 2855 2856 2857
  };
  EXPECT_VERIFIES(data);
}

2858 2859
TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) {
  static const byte data[] = {
2860
      // signatures
2861 2862 2863 2864 2865 2866 2867 2868
      TYPE_SECTION_ONE_SIG_VOID_VOID,  // --
      SECTION(Import,                  // --
              ENTRY_COUNT(1),          // --
              NO_NAME,                 // module name
              ADD_COUNT('f'),          // function name
              kExternalFunction,       // import kind
              SIG_INDEX(0),            // sig index
              0),                      // auxiliary data
2869 2870 2871 2872
  };
  EXPECT_FAILURE(data);
}

2873 2874
TEST_F(WasmModuleVerifyTest, ImportTable_off_end) {
  static const byte data[] = {
2875
      // signatures
2876
      TYPE_SECTION_ONE_SIG_VOID_VOID,
2877 2878 2879
      SECTION(Import, ENTRY_COUNT(1),
              ADD_COUNT('m'),      // module name
              ADD_COUNT('f'),      // function name
2880 2881
              kExternalFunction),  // import kind
      SIG_INDEX(0),                // sig index (outside import section!)
2882 2883
  };

2884
  EXPECT_OFF_END_FAILURE(data, arraysize(data) - 3);
2885 2886
}

2887
TEST_F(WasmModuleVerifyTest, ExportTable_empty1) {
2888 2889
  static const byte data[] = {                                 // signatures
                              TYPE_SECTION_ONE_SIG_VOID_VOID,  // --
2890
                              ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
2891
                              SECTION(Export, ENTRY_COUNT(0)),  // --
2892 2893
                              ONE_EMPTY_BODY};

2894
  ModuleResult result = DecodeModule(data, data + sizeof(data));
2895 2896
  EXPECT_OK(result);

2897 2898
  EXPECT_EQ(1u, result.value()->functions.size());
  EXPECT_EQ(0u, result.value()->export_table.size());
titzer's avatar
titzer committed
2899 2900
}

2901
TEST_F(WasmModuleVerifyTest, ExportTable_empty2) {
2902 2903
  static const byte data[] = {SECTION(Type, ENTRY_COUNT(0)),
                              SECTION(Export, ENTRY_COUNT(0))};
2904
  EXPECT_VERIFIES(data);
titzer's avatar
titzer committed
2905 2906 2907
}

TEST_F(WasmModuleVerifyTest, ExportTable_NoFunctions2) {
2908
  static const byte data[] = {SECTION(Export, ENTRY_COUNT(0))};
2909
  EXPECT_VERIFIES(data);
titzer's avatar
titzer committed
2910 2911 2912
}

TEST_F(WasmModuleVerifyTest, ExportTableOne) {
2913 2914
  static const byte data[] = {
      // signatures
2915
      TYPE_SECTION_ONE_SIG_VOID_VOID, ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
2916 2917 2918 2919 2920 2921
      SECTION(Export,
              ENTRY_COUNT(1),     // exports
              NO_NAME,            // --
              kExternalFunction,  // --
              FUNC_INDEX(0)),     // --
      ONE_EMPTY_BODY};
2922
  ModuleResult result = DecodeModule(data, data + sizeof(data));
2923 2924
  EXPECT_OK(result);

2925 2926
  EXPECT_EQ(1u, result.value()->functions.size());
  EXPECT_EQ(1u, result.value()->export_table.size());
titzer's avatar
titzer committed
2927 2928
}

2929
TEST_F(WasmModuleVerifyTest, ExportNameWithInvalidStringLength) {
2930 2931
  static const byte data[] = {
      // signatures
2932
      TYPE_SECTION_ONE_SIG_VOID_VOID, ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
2933 2934
      SECTION(Export,
              ENTRY_COUNT(1),     // exports
2935
              U32V_1(84),         // invalid string length
2936 2937 2938 2939 2940
              'e',                // --
              kExternalFunction,  // --
              FUNC_INDEX(0),      // --
              0, 0, 0)            // auxiliary data
  };
2941 2942 2943 2944

  EXPECT_FAILURE(data);
}

titzer's avatar
titzer committed
2945
TEST_F(WasmModuleVerifyTest, ExportTableTwo) {
2946 2947
  static const byte data[] = {
      // signatures
2948
      TYPE_SECTION_ONE_SIG_VOID_VOID, ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
2949
      SECTION(Export,
2950 2951
              ENTRY_COUNT(2),                 // exports
              ADD_COUNT('n', 'a', 'm', 'e'),  // --
2952 2953 2954 2955 2956
              kExternalFunction,              // --
              FUNC_INDEX(0),                  // --
              ADD_COUNT('n', 'o', 'm'),       // --
              kExternalFunction,              // --
              FUNC_INDEX(0)),                 // --
2957
      ONE_EMPTY_BODY};
2958

2959
  ModuleResult result = DecodeModule(data, data + sizeof(data));
2960 2961
  EXPECT_OK(result);

2962 2963
  EXPECT_EQ(1u, result.value()->functions.size());
  EXPECT_EQ(2u, result.value()->export_table.size());
titzer's avatar
titzer committed
2964 2965 2966
}

TEST_F(WasmModuleVerifyTest, ExportTableThree) {
2967 2968
  static const byte data[] = {
      // signatures
2969
      TYPE_SECTION_ONE_SIG_VOID_VOID, THREE_EMPTY_FUNCTIONS(SIG_INDEX(0)),
2970 2971
      SECTION(Export,
              ENTRY_COUNT(3),  // exports
2972
              ADD_COUNT('a'),  // --
2973
              kExternalFunction,
2974 2975
              FUNC_INDEX(0),   // --
              ADD_COUNT('b'),  // --
2976
              kExternalFunction,
2977 2978
              FUNC_INDEX(1),   // --
              ADD_COUNT('c'),  // --
2979 2980 2981
              kExternalFunction,
              FUNC_INDEX(2)),  // --
      THREE_EMPTY_BODIES};
2982
  ModuleResult result = DecodeModule(data, data + sizeof(data));
2983 2984
  EXPECT_OK(result);

2985 2986
  EXPECT_EQ(3u, result.value()->functions.size());
  EXPECT_EQ(3u, result.value()->export_table.size());
titzer's avatar
titzer committed
2987 2988 2989 2990
}

TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) {
  for (int i = 0; i < 6; i++) {
2991 2992
    const byte data[] = {
        // signatures
2993
        TYPE_SECTION_ONE_SIG_VOID_VOID, THREE_EMPTY_FUNCTIONS(SIG_INDEX(0)),
2994
        SECTION(Export,
2995 2996
                ENTRY_COUNT(1),       // exports
                ADD_COUNT('e', 'x'),  // --
2997 2998 2999
                kExternalFunction,
                FUNC_INDEX(i)),  // --
        THREE_EMPTY_BODIES};
titzer's avatar
titzer committed
3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010

    if (i < 3) {
      EXPECT_VERIFIES(data);
    } else {
      EXPECT_FAILURE(data);
    }
  }
}

TEST_F(WasmModuleVerifyTest, ExportTableOne_off_end) {
  static const byte data[] = {
3011
      // signatures
3012
      TYPE_SECTION_ONE_SIG_VOID_VOID, ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
3013 3014 3015 3016 3017 3018
      SECTION(Export,
              ENTRY_COUNT(1),  // exports
              NO_NAME,         // --
              kExternalFunction,
              FUNC_INDEX(0),  // --
              0, 0, 0)        // auxiliary data
titzer's avatar
titzer committed
3019 3020
  };

3021
  EXPECT_OFF_END_FAILURE(data, arraysize(data) - 3);
titzer's avatar
titzer committed
3022 3023
}

3024 3025
TEST_F(WasmModuleVerifyTest, Regression_648070) {
  static const byte data[] = {
3026 3027 3028
      SECTION(Type, ENTRY_COUNT(0)),         // --
      SECTION(Function, U32V_5(3500228624))  // function count = 3500228624
  };                                         // --
3029 3030 3031
  EXPECT_FAILURE(data);
}

3032 3033 3034
TEST_F(WasmModuleVerifyTest, Regression_738097) {
  // The function body size caused an integer overflow in the module decoder.
  static const byte data[] = {
3035 3036 3037 3038 3039 3040
      TYPE_SECTION(1, SIG_ENTRY_v_v),  // --
      FUNCTION_SECTION(1, 0),          // --
      SECTION(Code,                    // --
              ENTRY_COUNT(1),          // --
              U32V_5(0xFFFFFFFF),      // function size,
              0)                       // No real body
3041 3042 3043 3044
  };
  EXPECT_FAILURE(data);
}

3045 3046 3047 3048 3049
TEST_F(WasmModuleVerifyTest, FunctionBodySizeLimit) {
  const uint32_t delta = 3;
  for (uint32_t body_size = kV8MaxWasmFunctionSize - delta;
       body_size < kV8MaxWasmFunctionSize + delta; body_size++) {
    byte data[] = {
3050 3051 3052 3053 3054 3055
        TYPE_SECTION(1, SIG_ENTRY_v_v),  // --
        FUNCTION_SECTION(1, 0),          // --
        kCodeSectionCode,                // code section
        U32V_5(1 + body_size + 5),       // section size
        1,                               // # functions
        U32V_5(body_size)                // body size
3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069
    };
    size_t total = sizeof(data) + body_size;
    byte* buffer = reinterpret_cast<byte*>(calloc(1, total));
    memcpy(buffer, data, sizeof(data));
    ModuleResult result = DecodeModule(buffer, buffer + total);
    if (body_size <= kV8MaxWasmFunctionSize) {
      EXPECT_TRUE(result.ok());
    } else {
      EXPECT_FALSE(result.ok());
    }
    free(buffer);
  }
}

3070 3071 3072 3073 3074
TEST_F(WasmModuleVerifyTest, IllegalTypeCode) {
  static const byte data[] = {TYPE_SECTION(1, SIG_ENTRY_v_x(0x41))};
  EXPECT_FAILURE_WITH_MSG(data, "invalid value type");
}

3075
TEST_F(WasmModuleVerifyTest, FunctionBodies_empty) {
3076
  static const byte data[] = {
3077 3078 3079
      EMPTY_TYPE_SECTION,            // --
      EMPTY_FUNCTION_SECTION,        // --
      EMPTY_FUNCTION_BODIES_SECTION  // --
3080
  };
3081 3082 3083 3084
  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, FunctionBodies_one_empty) {
3085
  static const byte data[] = {
3086 3087 3088
      TYPE_SECTION(1, SIG_ENTRY_v_v),  // --
      FUNCTION_SECTION(1, 0),          // --
      ONE_EMPTY_BODY                   // --
3089
  };
3090 3091 3092 3093
  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, FunctionBodies_one_nop) {
3094
  static const byte data[] = {
3095 3096
      TYPE_SECTION(1, SIG_ENTRY_v_v),          // --
      FUNCTION_SECTION(1, 0),                  // --
3097
      SECTION(Code, ENTRY_COUNT(1), NOP_BODY)  // --
3098
  };
3099 3100 3101 3102
  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch1) {
3103
  static const byte data[] = {
3104 3105 3106
      TYPE_SECTION(1, SIG_ENTRY_v_v),  // --
      FUNCTION_SECTION(2, 0, 0),       // --
      ONE_EMPTY_BODY                   // --
3107
  };
3108 3109 3110 3111
  EXPECT_FAILURE(data);
}

TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch2) {
3112
  static const byte data[] = {
3113 3114
      TYPE_SECTION(1, SIG_ENTRY_v_v),                    // --
      FUNCTION_SECTION(1, 0),                            // --
3115
      SECTION(Code, ENTRY_COUNT(2), NOP_BODY, NOP_BODY)  // --
3116
  };
3117 3118 3119 3120
  EXPECT_FAILURE(data);
}

TEST_F(WasmModuleVerifyTest, Names_empty) {
3121 3122 3123
  static const byte data[] = {EMPTY_TYPE_SECTION, EMPTY_FUNCTION_SECTION,
                              EMPTY_FUNCTION_BODIES_SECTION,
                              EMPTY_NAMES_SECTION};
3124 3125 3126 3127
  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, Names_one_empty) {
3128 3129
  // TODO(wasm): This test does not test anything (corrupt name section does not
  // fail validation).
3130
  static const byte data[] = {
3131 3132
      TYPE_SECTION(1, SIG_ENTRY_v_v),                            // --
      FUNCTION_SECTION(1, 0),                                    // --
3133
      ONE_EMPTY_BODY,                                            // --
3134
      SECTION_NAMES(ENTRY_COUNT(1), FOO_STRING, NO_LOCAL_NAMES)  // --
3135 3136 3137 3138 3139
  };
  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, Names_two_empty) {
3140 3141
  // TODO(wasm): This test does not test anything (corrupt name section does not
  // fail validation).
3142
  static const byte data[] = {
3143 3144
      TYPE_SECTION(1, SIG_ENTRY_v_v),             // --
      FUNCTION_SECTION(2, 0, 0),                  // --
3145 3146 3147 3148
      TWO_EMPTY_BODIES,                           // --
      SECTION_NAMES(ENTRY_COUNT(2),               // --
                    FOO_STRING, NO_LOCAL_NAMES,   // --
                    FOO_STRING, NO_LOCAL_NAMES),  // --
3149 3150 3151 3152
  };
  EXPECT_VERIFIES(data);
}

3153 3154
TEST_F(WasmModuleVerifyTest, Regression684855) {
  static const byte data[] = {
3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166
      SECTION_NAMES(0xFB,  // functions count
                    0x27,  // |
                    0x00,  // function name length
                    0xFF,  // local names count
                    0xFF,  // |
                    0xFF,  // |
                    0xFF,  // |
                    0xFF,  // |
                    0xFF,  // error: "varint too large"
                    0xFF,  // |
                    0x00,  // --
                    0x00)  // --
3167 3168 3169 3170
  };
  EXPECT_VERIFIES(data);
}

3171 3172
TEST_F(WasmModuleVerifyTest, FunctionSectionWithoutCodeSection) {
  static const byte data[] = {
3173 3174
      TYPE_SECTION(1, SIG_ENTRY_v_v),  // Type section.
      FUNCTION_SECTION(1, 0),          // Function section.
3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195
  };
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "function count is 1, but code section is absent");
}

TEST_F(WasmModuleVerifyTest, CodeSectionWithoutFunctionSection) {
  static const byte data[] = {ONE_EMPTY_BODY};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "function body count 1 mismatch (0 expected)");
}

TEST_F(WasmModuleVerifyTest, EmptyFunctionSectionWithoutCodeSection) {
  static const byte data[] = {SECTION(Function, ENTRY_COUNT(0))};
  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, EmptyCodeSectionWithoutFunctionSection) {
  static const byte data[] = {SECTION(Code, ENTRY_COUNT(0))};
  EXPECT_VERIFIES(data);
}

3196 3197
class WasmInitExprDecodeTest : public TestWithZone {
 public:
3198
  WasmInitExprDecodeTest() = default;
3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210

  WasmFeatures enabled_features_;

  WasmInitExpr DecodeInitExpr(const byte* start, const byte* end) {
    return DecodeWasmInitExprForTesting(enabled_features_, start, end);
  }
};

#define EXPECT_INIT_EXPR(Type, type, value, ...)                   \
  {                                                                \
    static const byte data[] = {__VA_ARGS__, kExprEnd};            \
    WasmInitExpr expr = DecodeInitExpr(data, data + sizeof(data)); \
3211 3212
    EXPECT_EQ(WasmInitExpr::k##Type##Const, expr.kind());          \
    EXPECT_EQ(value, expr.immediate().type##_const);               \
3213 3214
  }

3215 3216 3217 3218
#define EXPECT_INIT_EXPR_FAIL(...)                                 \
  {                                                                \
    static const byte data[] = {__VA_ARGS__, kExprEnd};            \
    WasmInitExpr expr = DecodeInitExpr(data, data + sizeof(data)); \
3219
    EXPECT_EQ(WasmInitExpr::kNone, expr.kind());                   \
3220 3221 3222
  }

TEST_F(WasmInitExprDecodeTest, InitExpr_i32) {
3223 3224 3225 3226 3227 3228
  EXPECT_INIT_EXPR(I32, i32, 33, WASM_I32V_1(33));
  EXPECT_INIT_EXPR(I32, i32, -21, WASM_I32V_1(-21));
  EXPECT_INIT_EXPR(I32, i32, 437, WASM_I32V_2(437));
  EXPECT_INIT_EXPR(I32, i32, 77777, WASM_I32V_3(77777));
}

3229
TEST_F(WasmInitExprDecodeTest, InitExpr_f32) {
3230 3231 3232 3233 3234 3235
  EXPECT_INIT_EXPR(F32, f32, static_cast<float>(13.1), WASM_F32(13.1));
  EXPECT_INIT_EXPR(F32, f32, static_cast<float>(-21.1), WASM_F32(-21.1));
  EXPECT_INIT_EXPR(F32, f32, static_cast<float>(437.2), WASM_F32(437.2));
  EXPECT_INIT_EXPR(F32, f32, static_cast<float>(77777.3), WASM_F32(77777.3));
}

3236
TEST_F(WasmInitExprDecodeTest, InitExpr_i64) {
3237 3238 3239 3240 3241 3242
  EXPECT_INIT_EXPR(I64, i64, 33, WASM_I64V_1(33));
  EXPECT_INIT_EXPR(I64, i64, -21, WASM_I64V_2(-21));
  EXPECT_INIT_EXPR(I64, i64, 437, WASM_I64V_5(437));
  EXPECT_INIT_EXPR(I64, i64, 77777, WASM_I64V_7(77777));
}

3243
TEST_F(WasmInitExprDecodeTest, InitExpr_f64) {
3244 3245 3246 3247 3248 3249
  EXPECT_INIT_EXPR(F64, f64, 83.22, WASM_F64(83.22));
  EXPECT_INIT_EXPR(F64, f64, -771.3, WASM_F64(-771.3));
  EXPECT_INIT_EXPR(F64, f64, 43703.0, WASM_F64(43703.0));
  EXPECT_INIT_EXPR(F64, f64, 77999.1, WASM_F64(77999.1));
}

3250 3251
TEST_F(WasmInitExprDecodeTest, InitExpr_ExternRef) {
  WASM_FEATURE_SCOPE(reftypes);
3252
  static const byte data[] = {kExprRefNull, kExternRefCode, kExprEnd};
3253
  WasmInitExpr expr = DecodeInitExpr(data, data + sizeof(data));
3254
  EXPECT_EQ(WasmInitExpr::kRefNullConst, expr.kind());
3255 3256
}

3257
TEST_F(WasmInitExprDecodeTest, InitExpr_illegal) {
3258
  EXPECT_INIT_EXPR_FAIL(WASM_I32V_1(0), WASM_I32V_1(0));
3259 3260
  EXPECT_INIT_EXPR_FAIL(WASM_LOCAL_GET(0));
  EXPECT_INIT_EXPR_FAIL(WASM_LOCAL_SET(0, WASM_I32V_1(0)));
3261 3262 3263 3264
  EXPECT_INIT_EXPR_FAIL(WASM_I32_ADD(WASM_I32V_1(0), WASM_I32V_1(0)));
  EXPECT_INIT_EXPR_FAIL(WASM_IF_ELSE(WASM_ZERO, WASM_ZERO, WASM_ZERO));
}

3265 3266
TEST_F(WasmModuleVerifyTest, Multiple_Named_Sections) {
  static const byte data[] = {
3267 3268 3269
      SECTION(Unknown, ADD_COUNT('X'), 17, 18),                    // --
      SECTION(Unknown, ADD_COUNT('f', 'o', 'o'), 5, 6, 7, 8, 9),   // --
      SECTION(Unknown, ADD_COUNT('o', 't', 'h', 'e', 'r'), 7, 8),  // --
3270 3271 3272
  };
  EXPECT_VERIFIES(data);
}
3273

3274
TEST_F(WasmModuleVerifyTest, Section_Name_No_UTF8) {
3275
  static const byte data[] = {SECTION(Unknown, 1, 0xFF, 17, 18)};
3276 3277 3278
  EXPECT_FAILURE(data);
}

3279 3280 3281
class WasmModuleCustomSectionTest : public TestWithIsolateAndZone {
 public:
  void CheckSections(const byte* module_start, const byte* module_end,
3282
                     const CustomSectionOffset* expected, size_t num_expected) {
3283 3284 3285 3286 3287 3288
    std::vector<CustomSectionOffset> custom_sections =
        DecodeCustomSections(module_start, module_end);

    CHECK_EQ(num_expected, custom_sections.size());

    for (size_t i = 0; i < num_expected; i++) {
3289 3290 3291 3292 3293 3294 3295 3296 3297 3298
      EXPECT_EQ(expected[i].section.offset(),
                custom_sections[i].section.offset());
      EXPECT_EQ(expected[i].section.length(),
                custom_sections[i].section.length());
      EXPECT_EQ(expected[i].name.offset(), custom_sections[i].name.offset());
      EXPECT_EQ(expected[i].name.length(), custom_sections[i].name.length());
      EXPECT_EQ(expected[i].payload.offset(),
                custom_sections[i].payload.offset());
      EXPECT_EQ(expected[i].payload.length(),
                custom_sections[i].payload.length());
3299 3300 3301 3302 3303
    }
  }
};

TEST_F(WasmModuleCustomSectionTest, ThreeUnknownSections) {
3304
  static constexpr byte data[] = {
3305 3306 3307 3308 3309
      U32_LE(kWasmMagic),                                  // --
      U32_LE(kWasmVersion),                                // --
      SECTION(Unknown, 1, 'X', 17, 18),                    // --
      SECTION(Unknown, 3, 'f', 'o', 'o', 5, 6, 7, 8, 9),   // --
      SECTION(Unknown, 5, 'o', 't', 'h', 'e', 'r', 7, 8),  // --
3310 3311
  };

3312 3313 3314 3315 3316
  static const CustomSectionOffset expected[] = {
      // section, name, payload
      {{10, 4}, {11, 1}, {12, 2}},  // --
      {{16, 9}, {17, 3}, {20, 5}},  // --
      {{27, 8}, {28, 5}, {33, 2}},  // --
3317 3318 3319 3320 3321 3322 3323
  };

  CheckSections(data, data + sizeof(data), expected, arraysize(expected));
}

TEST_F(WasmModuleCustomSectionTest, TwoKnownTwoUnknownSections) {
  static const byte data[] = {
3324 3325
      U32_LE(kWasmMagic),                                          // --
      U32_LE(kWasmVersion),                                        // --
3326
      TYPE_SECTION(2, SIG_ENTRY_v_v, SIG_ENTRY_v_v),               // --
3327 3328 3329
      SECTION(Unknown, ADD_COUNT('X'), 17, 18),                    // --
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),                            // --
      SECTION(Unknown, ADD_COUNT('o', 't', 'h', 'e', 'r'), 7, 8),  // --
3330 3331
  };

3332 3333 3334 3335
  static const CustomSectionOffset expected[] = {
      // section, name, payload
      {{19, 4}, {20, 1}, {21, 2}},  // --
      {{29, 8}, {30, 5}, {35, 2}},  // --
3336 3337 3338 3339 3340
  };

  CheckSections(data, data + sizeof(data), expected, arraysize(expected));
}

3341
TEST_F(WasmModuleVerifyTest, SourceMappingURLSection) {
3342
  static const byte data[] = {
3343
      WASM_MODULE_HEADER,
3344
      SECTION_SRC_MAP('s', 'r', 'c', '/', 'x', 'y', 'z', '.', 'c')};
3345
  ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
3346
  EXPECT_TRUE(result.ok());
3347 3348 3349 3350 3351 3352
  EXPECT_EQ(WasmDebugSymbols::Type::SourceMap,
            result.value()->debug_symbols.type);
  ModuleWireBytes wire_bytes(data, data + sizeof(data));
  WasmName external_url =
      wire_bytes.GetNameOrNull(result.value()->debug_symbols.external_url);
  EXPECT_EQ("src/xyz.c", std::string(external_url.data(), external_url.size()));
3353 3354 3355
}

TEST_F(WasmModuleVerifyTest, BadSourceMappingURLSection) {
3356
  static const byte data[] = {
3357
      WASM_MODULE_HEADER,
3358
      SECTION_SRC_MAP('s', 'r', 'c', '/', 'x', 0xff, 'z', '.', 'c')};
3359
  ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
3360
  EXPECT_TRUE(result.ok());
3361 3362
  EXPECT_EQ(WasmDebugSymbols::Type::None, result.value()->debug_symbols.type);
  EXPECT_EQ(0u, result.value()->debug_symbols.external_url.length());
3363 3364 3365
}

TEST_F(WasmModuleVerifyTest, MultipleSourceMappingURLSections) {
3366 3367
  static const byte data[] = {WASM_MODULE_HEADER,
                              SECTION_SRC_MAP('a', 'b', 'c'),
3368
                              SECTION_SRC_MAP('p', 'q', 'r')};
3369
  ModuleResult result = DecodeModuleNoHeader(data, data + sizeof(data));
3370
  EXPECT_TRUE(result.ok());
3371 3372 3373 3374 3375 3376
  EXPECT_EQ(WasmDebugSymbols::Type::SourceMap,
            result.value()->debug_symbols.type);
  ModuleWireBytes wire_bytes(data, data + sizeof(data));
  WasmName external_url =
      wire_bytes.GetNameOrNull(result.value()->debug_symbols.external_url);
  EXPECT_EQ("abc", std::string(external_url.data(), external_url.size()));
3377 3378
}

3379
TEST_F(WasmModuleVerifyTest, MultipleNameSections) {
3380
  static const byte data[] = {
3381 3382
      SECTION_NAMES(0, ADD_COUNT(ADD_COUNT('a', 'b', 'c'))),
      SECTION_NAMES(0, ADD_COUNT(ADD_COUNT('p', 'q', 'r', 's')))};
3383 3384
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_TRUE(result.ok());
3385
  EXPECT_EQ(3u, result.value()->name.length());
3386 3387
}

3388 3389 3390 3391 3392 3393 3394 3395
TEST_F(WasmModuleVerifyTest, BadNameSection) {
  static const byte data[] = {SECTION_NAMES(
      0, ADD_COUNT(ADD_COUNT('s', 'r', 'c', '/', 'x', 0xff, 'z', '.', 'c')))};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_TRUE(result.ok());
  EXPECT_EQ(0u, result.value()->name.length());
}

3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406
TEST_F(WasmModuleVerifyTest, PassiveDataSegment) {
  static const byte data[] = {
      // memory declaration ----------------------------------------------------
      SECTION(Memory, ENTRY_COUNT(1), 0, 1),
      // data segments  --------------------------------------------------------
      SECTION(Data, ENTRY_COUNT(1), PASSIVE, ADD_COUNT('h', 'i')),
  };
  EXPECT_VERIFIES(data);
  EXPECT_OFF_END_FAILURE(data, arraysize(data) - 5);
}

3407
TEST_F(WasmModuleVerifyTest, ActiveElementSegmentWithElements) {
3408 3409
  static const byte data[] = {
      // sig#0 -----------------------------------------------------------------
3410
      TYPE_SECTION_ONE_SIG_VOID_VOID,
3411 3412 3413
      // funcs -----------------------------------------------------------------
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
      // table declaration -----------------------------------------------------
3414
      SECTION(Table, ENTRY_COUNT(1), kFuncRefCode, 0, 1),
3415
      // element segments  -----------------------------------------------------
3416
      SECTION(Element, ENTRY_COUNT(1), ACTIVE_WITH_ELEMENTS, TABLE_INDEX0,
3417
              WASM_INIT_EXPR_I32V_1(0), kFuncRefCode, U32V_1(3),
3418
              REF_FUNC_ELEMENT(0), REF_FUNC_ELEMENT(0), REF_NULL_ELEMENT),
3419 3420
      // code ------------------------------------------------------------------
      ONE_EMPTY_BODY};
3421 3422 3423 3424
  EXPECT_VERIFIES(data);
  EXPECT_OFF_END_FAILURE(data, arraysize(data) - 5);
}

3425 3426 3427
TEST_F(WasmModuleVerifyTest, PassiveElementSegment) {
  static const byte data[] = {
      // sig#0 -----------------------------------------------------------------
3428
      TYPE_SECTION_ONE_SIG_VOID_VOID,
3429 3430 3431
      // funcs -----------------------------------------------------------------
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
      // table declaration -----------------------------------------------------
3432
      SECTION(Table, ENTRY_COUNT(1), kFuncRefCode, 0, 1),
3433
      // element segments  -----------------------------------------------------
3434
      SECTION(Element, ENTRY_COUNT(1), PASSIVE_WITH_ELEMENTS, kFuncRefCode,
3435 3436 3437 3438 3439 3440 3441 3442
              U32V_1(3), REF_FUNC_ELEMENT(0), REF_FUNC_ELEMENT(0),
              REF_NULL_ELEMENT),
      // code ------------------------------------------------------------------
      ONE_EMPTY_BODY};
  EXPECT_VERIFIES(data);
  EXPECT_OFF_END_FAILURE(data, arraysize(data) - 5);
}

3443
TEST_F(WasmModuleVerifyTest, PassiveElementSegmentExternRef) {
3444 3445
  static const byte data[] = {
      // sig#0 -----------------------------------------------------------------
3446
      TYPE_SECTION_ONE_SIG_VOID_VOID,
3447 3448 3449
      // funcs -----------------------------------------------------------------
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
      // table declaration -----------------------------------------------------
3450
      SECTION(Table, ENTRY_COUNT(1), kFuncRefCode, 0, 1),
3451
      // element segments  -----------------------------------------------------
3452
      SECTION(Element, ENTRY_COUNT(1), PASSIVE_WITH_ELEMENTS, kExternRefCode,
3453
              U32V_1(0)),
3454 3455 3456 3457 3458
      // code ------------------------------------------------------------------
      ONE_EMPTY_BODY};
  EXPECT_FAILURE(data);
}

3459 3460 3461
TEST_F(WasmModuleVerifyTest, PassiveElementSegmentWithIndices) {
  static const byte data[] = {
      // sig#0 -----------------------------------------------------------------
3462
      TYPE_SECTION_ONE_SIG_VOID_VOID,
3463 3464 3465
      // funcs -----------------------------------------------------------------
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
      // table declaration -----------------------------------------------------
3466
      SECTION(Table, ENTRY_COUNT(1), kFuncRefCode, 0, 1),
3467
      // element segments ------------------------------------------------------
3468 3469 3470 3471 3472 3473 3474 3475
      SECTION(Element, ENTRY_COUNT(1), PASSIVE, kExternalFunction,
              ENTRY_COUNT(3), U32V_1(0), U32V_1(0), U32V_1(0)),
      // code ------------------------------------------------------------------
      ONE_EMPTY_BODY};
  EXPECT_VERIFIES(data);
  EXPECT_OFF_END_FAILURE(data, arraysize(data) - 5);
}

3476 3477 3478
TEST_F(WasmModuleVerifyTest, DeclarativeElementSegmentFuncRef) {
  static const byte data[] = {
      // sig#0 -----------------------------------------------------------------
3479
      TYPE_SECTION_ONE_SIG_VOID_VOID,
3480 3481 3482 3483 3484 3485
      // funcs -----------------------------------------------------------------
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
      // element segments  -----------------------------------------------------
      SECTION(Element,                    // section name
              ENTRY_COUNT(1),             // entry count
              DECLARATIVE_WITH_ELEMENTS,  // flags
3486
              kFuncRefCode,               // local type
3487 3488 3489 3490
              U32V_1(0)),                 // func ref count
      // code ------------------------------------------------------------------
      ONE_EMPTY_BODY};
  EXPECT_FAILURE(data);
3491
  WASM_FEATURE_SCOPE(reftypes);
3492 3493 3494 3495
  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, DeclarativeElementSegmentWithInvalidIndex) {
3496
  WASM_FEATURE_SCOPE(reftypes);
3497 3498
  static const byte data[] = {
      // sig#0 -----------------------------------------------------------------
3499
      TYPE_SECTION_ONE_SIG_VOID_VOID,
3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514
      // funcs -----------------------------------------------------------------
      ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
      // element segments  -----------------------------------------------------
      SECTION(Element,            // section name
              ENTRY_COUNT(1),     // entry count
              DECLARATIVE,        // flags
              kExternalFunction,  // type
              ENTRY_COUNT(2),     // func index count
              U32V_1(0),          // func index
              U32V_1(1)),         // func index
      // code ------------------------------------------------------------------
      ONE_EMPTY_BODY};
  EXPECT_FAILURE_WITH_MSG(data, "element function index 1 out of bounds");
}

3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533
TEST_F(WasmModuleVerifyTest, DataCountSectionCorrectPlacement) {
  static const byte data[] = {SECTION(Element, ENTRY_COUNT(0)),
                              SECTION(DataCount, ENTRY_COUNT(0)),
                              SECTION(Code, ENTRY_COUNT(0))};
  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, DataCountSectionAfterCode) {
  static const byte data[] = {SECTION(Code, ENTRY_COUNT(0)),
                              SECTION(DataCount, ENTRY_COUNT(0))};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result,
                "The DataCount section must appear before the Code section");
}

TEST_F(WasmModuleVerifyTest, DataCountSectionBeforeElement) {
  static const byte data[] = {SECTION(DataCount, ENTRY_COUNT(0)),
                              SECTION(Element, ENTRY_COUNT(0))};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
3534
  EXPECT_NOT_OK(result, "unexpected section <Element>");
3535 3536 3537 3538 3539 3540 3541 3542
}

TEST_F(WasmModuleVerifyTest, DataCountSectionAfterStartBeforeElement) {
  STATIC_ASSERT(kStartSectionCode + 1 == kElementSectionCode);
  static const byte data[] = {
      // We need the start section for this test, but the start section must
      // reference a valid function, which requires the type and function
      // sections too.
3543 3544
      TYPE_SECTION(1, SIG_ENTRY_v_v),      // Type section.
      FUNCTION_SECTION(1, 0),              // Function section.
3545 3546 3547 3548 3549
      SECTION(Start, U32V_1(0)),           // Start section.
      SECTION(DataCount, ENTRY_COUNT(0)),  // DataCount section.
      SECTION(Element, ENTRY_COUNT(0))     // Element section.
  };
  ModuleResult result = DecodeModule(data, data + sizeof(data));
3550
  EXPECT_NOT_OK(result, "unexpected section <Element>");
3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595
}

TEST_F(WasmModuleVerifyTest, MultipleDataCountSections) {
  static const byte data[] = {SECTION(DataCount, ENTRY_COUNT(0)),
                              SECTION(DataCount, ENTRY_COUNT(0))};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "Multiple DataCount sections not allowed");
}

TEST_F(WasmModuleVerifyTest, DataCountSegmentCountMatch) {
  static const byte data[] = {
      SECTION(Memory, ENTRY_COUNT(1), 0, 1),  // Memory section.
      SECTION(DataCount, ENTRY_COUNT(1)),     // DataCount section.
      SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,  // Data section.
              WASM_INIT_EXPR_I32V_1(12), ADD_COUNT('h', 'i'))};

  EXPECT_VERIFIES(data);
}

TEST_F(WasmModuleVerifyTest, DataCountSegmentCount_greater) {
  static const byte data[] = {
      SECTION(Memory, ENTRY_COUNT(1), 0, 1),  // Memory section.
      SECTION(DataCount, ENTRY_COUNT(3)),     // DataCount section.
      SECTION(Data, ENTRY_COUNT(0))};         // Data section.
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "data segments count 0 mismatch (3 expected)");
}

TEST_F(WasmModuleVerifyTest, DataCountSegmentCount_less) {
  static const byte data[] = {
      SECTION(Memory, ENTRY_COUNT(1), 0, 1),  // Memory section.
      SECTION(DataCount, ENTRY_COUNT(0)),     // DataCount section.
      SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,  // Data section.
              WASM_INIT_EXPR_I32V_1(12), ADD_COUNT('a', 'b', 'c'))};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "data segments count 1 mismatch (0 expected)");
}

TEST_F(WasmModuleVerifyTest, DataCountSegmentCount_omitted) {
  static const byte data[] = {SECTION(Memory, ENTRY_COUNT(1), 0, 1),
                              SECTION(DataCount, ENTRY_COUNT(1))};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_NOT_OK(result, "data segments count 0 mismatch (1 expected)");
}

3596 3597 3598 3599 3600 3601 3602
TEST_F(WasmModuleVerifyTest, GcStructIdsPass) {
  WASM_FEATURE_SCOPE(gc);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(reftypes);

  static const byte data[] = {SECTION(
      Type, ENTRY_COUNT(3),
3603
      WASM_STRUCT_DEF(FIELD_COUNT(3), STRUCT_FIELD(kI32Code, true),
3604 3605 3606 3607 3608 3609 3610 3611 3612
                      STRUCT_FIELD(WASM_OPT_REF(0), true),
                      STRUCT_FIELD(WASM_OPT_REF(1), true)),
      WASM_STRUCT_DEF(FIELD_COUNT(2), STRUCT_FIELD(WASM_OPT_REF(0), true),
                      STRUCT_FIELD(WASM_OPT_REF(2), true)),
      WASM_ARRAY_DEF(WASM_OPT_REF(0), true))};
  ModuleResult result = DecodeModule(data, data + sizeof(data));
  EXPECT_OK(result);
}

3613
TEST_F(WasmModuleVerifyTest, OutOfBoundsTypeInGlobal) {
3614 3615
  WASM_FEATURE_SCOPE(reftypes);
  WASM_FEATURE_SCOPE(typed_funcref);
3616 3617
  static const byte data[] = {
      SECTION(Global, ENTRY_COUNT(1), kRefCode, 0, WASM_REF_NULL(0), kExprEnd)};
3618
  ModuleResult result = DecodeModule(data, data + sizeof(data));
3619
  EXPECT_NOT_OK(result, "Type index 0 is out of bounds");
3620 3621
}

3622
TEST_F(WasmModuleVerifyTest, OutOfBoundsTypeInType) {
3623
  WASM_FEATURE_SCOPE(reftypes);
3624 3625 3626 3627
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(gc);
  static const byte data[] = {
      SECTION(Type, ENTRY_COUNT(1),
3628
              WASM_STRUCT_DEF(FIELD_COUNT(1), STRUCT_FIELD(kRefCode, true)))};
3629
  ModuleResult result = DecodeModule(data, data + sizeof(data));
3630
  EXPECT_NOT_OK(result, "Type index 1 is out of bounds");
3631 3632
}

3633 3634 3635 3636 3637 3638
TEST_F(WasmModuleVerifyTest, IllegalPackedFields) {
  WASM_FEATURE_SCOPE(gc);
  WASM_FEATURE_SCOPE(typed_funcref);
  WASM_FEATURE_SCOPE(reftypes);

  static const byte data[] = {
3639
      SECTION(Global, ENTRY_COUNT(1), kI16Code, 0, WASM_INIT_EXPR_I32V_1(13))};
3640 3641 3642 3643 3644 3645

  ModuleResult result = DecodeModule(data, data + sizeof(data));

  EXPECT_NOT_OK(result, "invalid value type");
}

3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671
TEST_F(WasmModuleVerifyTest, Memory64DataSegment) {
  WASM_FEATURE_SCOPE(memory64);
  for (bool enable_memory64 : {false, true}) {
    for (bool use_memory64 : {false, true}) {
      byte const_opcode = use_memory64 ? kExprI64Const : kExprI32Const;
      const byte data[] = {
          SECTION(Memory, ENTRY_COUNT(1),
                  enable_memory64 ? kMemory64WithMaximum : kWithMaximum, 28,
                  28),
          SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,  // -
                  const_opcode, 0, kExprEnd,                    // dest addr
                  U32V_1(3),                                    // source size
                  'a', 'b', 'c')                                // data bytes
      };

      if (enable_memory64 == use_memory64) {
        EXPECT_VERIFIES(data);
      } else if (enable_memory64) {
        EXPECT_FAILURE_WITH_MSG(data, "expected i64, got i32");
      } else {
        EXPECT_FAILURE_WITH_MSG(data, "expected i32, got i64");
      }
    }
  }
}

3672 3673
#undef EXPECT_INIT_EXPR
#undef EXPECT_INIT_EXPR_FAIL
3674 3675 3676 3677 3678 3679 3680 3681
#undef WASM_INIT_EXPR_I32V_1
#undef WASM_INIT_EXPR_I32V_2
#undef WASM_INIT_EXPR_I32V_3
#undef WASM_INIT_EXPR_I32V_4
#undef WASM_INIT_EXPR_I32V_5
#undef WASM_INIT_EXPR_F32
#undef WASM_INIT_EXPR_I64
#undef WASM_INIT_EXPR_F64
3682
#undef WASM_INIT_EXPR_EXTERN_REF_NULL
3683
#undef WASM_INIT_EXPR_FUNC_REF_NULL
3684
#undef WASM_INIT_EXPR_REF_FUNC
3685
#undef WASM_INIT_EXPR_GLOBAL
3686 3687
#undef REF_NULL_ELEMENT
#undef REF_FUNC_ELEMENT
3688 3689 3690 3691
#undef EMPTY_BODY
#undef NOP_BODY
#undef SIG_ENTRY_i_i
#undef UNKNOWN_SECTION
3692
#undef ADD_COUNT
3693
#undef SECTION
3694 3695
#undef TYPE_SECTION
#undef FUNCTION_SECTION
3696 3697
#undef FOO_STRING
#undef NO_LOCAL_NAMES
3698 3699
#undef EMPTY_TYPE_SECTION
#undef EMPTY_FUNCTION_SECTION
3700 3701 3702
#undef EMPTY_FUNCTION_BODIES_SECTION
#undef SECTION_NAMES
#undef EMPTY_NAMES_SECTION
3703
#undef SECTION_SRC_MAP
3704
#undef SECTION_COMPILATION_HINTS
3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717
#undef FAIL_IF_NO_EXPERIMENTAL_EH
#undef X1
#undef X2
#undef X3
#undef X4
#undef ONE_EMPTY_FUNCTION
#undef TWO_EMPTY_FUNCTIONS
#undef THREE_EMPTY_FUNCTIONS
#undef FOUR_EMPTY_FUNCTIONS
#undef ONE_EMPTY_BODY
#undef TWO_EMPTY_BODIES
#undef THREE_EMPTY_BODIES
#undef FOUR_EMPTY_BODIES
3718
#undef TYPE_SECTION_ONE_SIG_VOID_VOID
3719
#undef LINEAR_MEMORY_INDEX_0
3720 3721 3722 3723 3724 3725 3726 3727

#undef FIELD_COUNT
#undef STRUCT_FIELD
#undef WASM_REF
#undef WASM_OPT_REF
#undef WASM_STRUCT_DEF
#undef WASM_ARRAY_DEF
#undef WASM_FUNCTION_DEF
3728
#undef EXCEPTION_ENTRY
3729 3730 3731 3732 3733
#undef EXPECT_VERIFIES
#undef EXPECT_FAILURE_LEN
#undef EXPECT_FAILURE
#undef EXPECT_OFF_END_FAILURE
#undef EXPECT_OK
3734
#undef EXPECT_NOT_OK
3735

3736
}  // namespace module_decoder_unittest
3737 3738 3739
}  // namespace wasm
}  // namespace internal
}  // namespace v8