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