Line data Source code
1 : // Copyright 2017 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 "src/api.h"
6 : #include "src/objects-inl.h"
7 : #include "src/v8.h"
8 : #include "src/vector.h"
9 :
10 : #include "src/wasm/compilation-manager.h"
11 : #include "src/wasm/module-decoder.h"
12 : #include "src/wasm/streaming-decoder.h"
13 : #include "src/wasm/wasm-module-builder.h"
14 : #include "src/wasm/wasm-module.h"
15 :
16 : #include "test/cctest/cctest.h"
17 :
18 : #include "test/common/wasm/test-signatures.h"
19 : #include "test/common/wasm/wasm-macro-gen.h"
20 :
21 : namespace v8 {
22 : namespace internal {
23 : namespace wasm {
24 :
25 : class MockPlatform final : public TestPlatform {
26 : public:
27 450 : MockPlatform() : old_platform_(i::V8::GetCurrentPlatform()) {
28 : // Now that it's completely constructed, make this the current platform.
29 150 : i::V8::SetPlatformForTesting(this);
30 150 : }
31 150 : virtual ~MockPlatform() {
32 : // Delete all remaining tasks in the queue.
33 300 : while (!tasks_.empty()) {
34 0 : Task* task = tasks_.back();
35 : tasks_.pop_back();
36 0 : delete task;
37 : }
38 150 : i::V8::SetPlatformForTesting(old_platform_);
39 150 : }
40 :
41 330 : void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override {
42 330 : tasks_.push_back(task);
43 330 : }
44 :
45 311 : void CallOnBackgroundThread(v8::Task* task,
46 : ExpectedRuntime expected_runtime) override {
47 311 : tasks_.push_back(task);
48 311 : }
49 :
50 0 : bool IdleTasksEnabled(v8::Isolate* isolate) override { return false; }
51 :
52 348 : void ExecuteTasks() {
53 1337 : while (!tasks_.empty()) {
54 641 : Task* task = tasks_.back();
55 : tasks_.pop_back();
56 641 : task->Run();
57 641 : delete task;
58 : }
59 348 : }
60 :
61 : private:
62 : // We do not execute tasks concurrently, so we only need one list of tasks.
63 : std::vector<Task*> tasks_;
64 : v8::Platform* old_platform_;
65 : };
66 :
67 : namespace {
68 :
69 300 : class StreamTester {
70 : public:
71 300 : StreamTester() : zone_(&allocator_, "StreamTester") {
72 150 : v8::Isolate* isolate = CcTest::isolate();
73 : i::Isolate* i_isolate = CcTest::i_isolate();
74 :
75 : // Create the promise for the streaming compilation.
76 150 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
77 : v8::Local<Promise::Resolver> resolver;
78 300 : CHECK(Promise::Resolver::New(context).ToLocal(&resolver));
79 150 : CHECK(!i_isolate->has_scheduled_exception());
80 150 : promise_ = resolver->GetPromise();
81 :
82 150 : i::Handle<i::JSPromise> i_promise = v8::Utils::OpenHandle(*promise_);
83 :
84 300 : stream_ = i_isolate->wasm_compilation_manager()->StartStreamingCompilation(
85 : i_isolate, v8::Utils::OpenHandle(*context), i_promise);
86 150 : }
87 :
88 : std::shared_ptr<StreamingDecoder> stream() { return stream_; }
89 :
90 : // Run all compiler tasks, both foreground and background tasks.
91 : void RunCompilerTasks() {
92 348 : static_cast<MockPlatform*>(i::V8::GetCurrentPlatform())->ExecuteTasks();
93 : }
94 :
95 : bool IsPromiseFulfilled() {
96 24 : return promise_->State() == v8::Promise::kFulfilled;
97 : }
98 :
99 : bool IsPromiseRejected() {
100 54 : return promise_->State() == v8::Promise::kRejected;
101 : }
102 :
103 12 : bool IsPromisePending() { return promise_->State() == v8::Promise::kPending; }
104 :
105 : void OnBytesReceived(const uint8_t* start, size_t length) {
106 366 : stream_->OnBytesReceived(Vector<const uint8_t>(start, length));
107 : }
108 :
109 78 : void FinishStream() { stream_->Finish(); }
110 :
111 : Zone* zone() { return &zone_; }
112 :
113 : private:
114 : AccountingAllocator allocator_;
115 : Zone zone_;
116 : v8::Local<v8::Promise> promise_;
117 : std::shared_ptr<StreamingDecoder> stream_;
118 : };
119 : } // namespace
120 :
121 : #define STREAM_TEST(name) \
122 : void RunStream_##name(); \
123 : TEST(name) { \
124 : MockPlatform platform; \
125 : CcTest::InitializeVM(); \
126 : v8::HandleScope handle_scope(CcTest::isolate()); \
127 : i::HandleScope internal_scope(CcTest::i_isolate()); \
128 : RunStream_##name(); \
129 : } \
130 : void RunStream_##name()
131 :
132 : // Create a valid module with 3 functions.
133 42 : ZoneBuffer GetValidModuleBytes(Zone* zone) {
134 : ZoneBuffer buffer(zone);
135 42 : TestSignatures sigs;
136 42 : WasmModuleBuilder builder(zone);
137 : {
138 42 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
139 42 : uint8_t code[] = {kExprGetLocal, 0, kExprEnd};
140 42 : f->EmitCode(code, arraysize(code));
141 : }
142 : {
143 42 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
144 42 : uint8_t code[] = {kExprGetLocal, 1, kExprEnd};
145 42 : f->EmitCode(code, arraysize(code));
146 : }
147 : {
148 42 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
149 42 : uint8_t code[] = {kExprGetLocal, 2, kExprEnd};
150 42 : f->EmitCode(code, arraysize(code));
151 : }
152 42 : builder.WriteTo(buffer);
153 42 : return buffer;
154 : }
155 :
156 : // Test that all bytes arrive before doing any compilation. FinishStream is
157 : // called immediately.
158 23742 : STREAM_TEST(TestAllBytesArriveImmediatelyStreamFinishesFirst) {
159 6 : StreamTester tester;
160 6 : ZoneBuffer buffer = GetValidModuleBytes(tester.zone());
161 :
162 6 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
163 : tester.FinishStream();
164 :
165 : tester.RunCompilerTasks();
166 :
167 6 : CHECK(tester.IsPromiseFulfilled());
168 6 : }
169 :
170 : // Test that all bytes arrive before doing any compilation. FinishStream is
171 : // called after the compilation is done.
172 23742 : STREAM_TEST(TestAllBytesArriveAOTCompilerFinishesFirst) {
173 6 : StreamTester tester;
174 6 : ZoneBuffer buffer = GetValidModuleBytes(tester.zone());
175 :
176 6 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
177 :
178 : tester.RunCompilerTasks();
179 : tester.FinishStream();
180 : tester.RunCompilerTasks();
181 :
182 6 : CHECK(tester.IsPromiseFulfilled());
183 6 : }
184 :
185 12 : size_t GetFunctionOffset(i::Isolate* isolate, const uint8_t* buffer,
186 : size_t size, size_t index) {
187 : ModuleResult result = SyncDecodeWasmModule(isolate, buffer, buffer + size,
188 24 : false, ModuleOrigin::kWasmOrigin);
189 12 : CHECK(result.ok());
190 : std::unique_ptr<WasmModule> module = std::move(result.val);
191 12 : const WasmFunction* func = &module->functions[1];
192 24 : return func->code.offset();
193 : }
194 :
195 : // Test that some functions come in the beginning, some come after some
196 : // functions already got compiled.
197 23742 : STREAM_TEST(TestCutAfterOneFunctionStreamFinishesFirst) {
198 : i::Isolate* isolate = CcTest::i_isolate();
199 6 : StreamTester tester;
200 6 : ZoneBuffer buffer = GetValidModuleBytes(tester.zone());
201 :
202 6 : size_t offset = GetFunctionOffset(isolate, buffer.begin(), buffer.size(), 1);
203 : tester.OnBytesReceived(buffer.begin(), offset);
204 : tester.RunCompilerTasks();
205 6 : CHECK(tester.IsPromisePending());
206 6 : tester.OnBytesReceived(buffer.begin() + offset, buffer.size() - offset);
207 : tester.FinishStream();
208 : tester.RunCompilerTasks();
209 6 : CHECK(tester.IsPromiseFulfilled());
210 6 : }
211 :
212 : // Test that some functions come in the beginning, some come after some
213 : // functions already got compiled. Call FinishStream after the compilation is
214 : // done.
215 23742 : STREAM_TEST(TestCutAfterOneFunctionCompilerFinishesFirst) {
216 : i::Isolate* isolate = CcTest::i_isolate();
217 6 : StreamTester tester;
218 6 : ZoneBuffer buffer = GetValidModuleBytes(tester.zone());
219 :
220 6 : size_t offset = GetFunctionOffset(isolate, buffer.begin(), buffer.size(), 1);
221 : tester.OnBytesReceived(buffer.begin(), offset);
222 : tester.RunCompilerTasks();
223 6 : CHECK(tester.IsPromisePending());
224 6 : tester.OnBytesReceived(buffer.begin() + offset, buffer.size() - offset);
225 : tester.RunCompilerTasks();
226 : tester.FinishStream();
227 : tester.RunCompilerTasks();
228 6 : CHECK(tester.IsPromiseFulfilled());
229 6 : }
230 :
231 : // Create a module with an invalid global section.
232 18 : ZoneBuffer GetModuleWithInvalidSection(Zone* zone) {
233 : ZoneBuffer buffer(zone);
234 18 : TestSignatures sigs;
235 18 : WasmModuleBuilder builder(zone);
236 : // Add an invalid global to the module. The decoder will fail there.
237 : builder.AddGlobal(kWasmStmt, false, true,
238 18 : WasmInitExpr(WasmInitExpr::kGlobalIndex, 12));
239 : {
240 18 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
241 18 : uint8_t code[] = {kExprGetLocal, 0, kExprEnd};
242 18 : f->EmitCode(code, arraysize(code));
243 : }
244 : {
245 18 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
246 18 : uint8_t code[] = {kExprGetLocal, 1, kExprEnd};
247 18 : f->EmitCode(code, arraysize(code));
248 : }
249 : {
250 18 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
251 18 : uint8_t code[] = {kExprGetLocal, 2, kExprEnd};
252 18 : f->EmitCode(code, arraysize(code));
253 : }
254 18 : builder.WriteTo(buffer);
255 18 : return buffer;
256 : }
257 :
258 : // Test an error in a section, found by the ModuleDecoder.
259 23742 : STREAM_TEST(TestErrorInSectionStreamFinishesFirst) {
260 6 : StreamTester tester;
261 6 : ZoneBuffer buffer = GetModuleWithInvalidSection(tester.zone());
262 :
263 6 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
264 : tester.FinishStream();
265 :
266 : tester.RunCompilerTasks();
267 :
268 6 : CHECK(tester.IsPromiseRejected());
269 6 : }
270 :
271 23742 : STREAM_TEST(TestErrorInSectionCompilerFinishesFirst) {
272 6 : StreamTester tester;
273 6 : ZoneBuffer buffer = GetModuleWithInvalidSection(tester.zone());
274 :
275 6 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
276 : tester.RunCompilerTasks();
277 : tester.FinishStream();
278 : tester.RunCompilerTasks();
279 :
280 6 : CHECK(tester.IsPromiseRejected());
281 6 : }
282 :
283 23742 : STREAM_TEST(TestErrorInSectionWithCuts) {
284 6 : StreamTester tester;
285 6 : ZoneBuffer buffer = GetModuleWithInvalidSection(tester.zone());
286 :
287 : const uint8_t* current = buffer.begin();
288 6 : size_t remaining = buffer.end() - buffer.begin();
289 60 : while (current < buffer.end()) {
290 96 : size_t size = std::min(remaining, size_t{10});
291 : tester.OnBytesReceived(current, size);
292 : tester.RunCompilerTasks();
293 48 : current += 10;
294 48 : remaining -= size;
295 : }
296 : tester.FinishStream();
297 : tester.RunCompilerTasks();
298 :
299 6 : CHECK(tester.IsPromiseRejected());
300 6 : }
301 :
302 18 : ZoneBuffer GetModuleWithInvalidSectionSize(Zone* zone) {
303 : // We get a valid module and overwrite the size of the first section with an
304 : // invalid value.
305 18 : ZoneBuffer buffer = GetValidModuleBytes(zone);
306 : // 9 == 4 (wasm magic) + 4 (version) + 1 (section code)
307 18 : uint8_t* section_size_address = const_cast<uint8_t*>(buffer.begin()) + 9;
308 : // 0x808080800f is an invalid module size in leb encoding.
309 18 : section_size_address[0] = 0x80;
310 18 : section_size_address[1] = 0x80;
311 18 : section_size_address[2] = 0x80;
312 18 : section_size_address[3] = 0x80;
313 18 : section_size_address[4] = 0x0f;
314 18 : return buffer;
315 : }
316 :
317 23742 : STREAM_TEST(TestErrorInSectionSizeStreamFinishesFirst) {
318 6 : StreamTester tester;
319 6 : ZoneBuffer buffer = GetModuleWithInvalidSectionSize(tester.zone());
320 6 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
321 : tester.FinishStream();
322 : tester.RunCompilerTasks();
323 :
324 6 : CHECK(tester.IsPromiseRejected());
325 6 : }
326 :
327 23742 : STREAM_TEST(TestErrorInSectionSizeCompilerFinishesFirst) {
328 6 : StreamTester tester;
329 6 : ZoneBuffer buffer = GetModuleWithInvalidSectionSize(tester.zone());
330 6 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
331 : tester.RunCompilerTasks();
332 : tester.FinishStream();
333 : tester.RunCompilerTasks();
334 :
335 6 : CHECK(tester.IsPromiseRejected());
336 6 : }
337 :
338 23742 : STREAM_TEST(TestErrorInSectionSizeWithCuts) {
339 6 : StreamTester tester;
340 6 : ZoneBuffer buffer = GetModuleWithInvalidSectionSize(tester.zone());
341 : const uint8_t* current = buffer.begin();
342 6 : size_t remaining = buffer.end() - buffer.begin();
343 54 : while (current < buffer.end()) {
344 84 : size_t size = std::min(remaining, size_t{10});
345 : tester.OnBytesReceived(current, size);
346 : tester.RunCompilerTasks();
347 42 : current += 10;
348 42 : remaining -= size;
349 : }
350 : tester.RunCompilerTasks();
351 : tester.FinishStream();
352 : tester.RunCompilerTasks();
353 :
354 6 : CHECK(tester.IsPromiseRejected());
355 6 : }
356 :
357 : // Test an error in the code section, found by the ModuleDecoder. The error is a
358 : // functions count in the code section which differs from the functions count in
359 : // the function section.
360 23742 : STREAM_TEST(TestErrorInCodeSectionDetectedByModuleDecoder) {
361 6 : StreamTester tester;
362 :
363 : uint8_t code[] = {
364 : U32V_1(4), // body size
365 : U32V_1(0), // locals count
366 : kExprGetLocal, 0, kExprEnd // body
367 6 : };
368 :
369 : const uint8_t bytes[] = {
370 : WASM_MODULE_HEADER, // module header
371 : kTypeSectionCode, // section code
372 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
373 : U32V_1(1), // type count
374 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
375 : kFunctionSectionCode, // section code
376 : U32V_1(1 + 3), // section size
377 : U32V_1(3), // functions count
378 : 0, // signature index
379 : 0, // signature index
380 : 0, // signature index
381 : kCodeSectionCode, // section code
382 : U32V_1(1 + arraysize(code) * 2), // section size
383 : U32V_1(2), // !!! invalid function count !!!
384 6 : };
385 :
386 : tester.OnBytesReceived(bytes, arraysize(bytes));
387 : tester.OnBytesReceived(code, arraysize(code));
388 : tester.OnBytesReceived(code, arraysize(code));
389 : tester.FinishStream();
390 :
391 : tester.RunCompilerTasks();
392 :
393 6 : CHECK(tester.IsPromiseRejected());
394 6 : }
395 :
396 : // Test an error in the code section, found by the StreamingDecoder. The error
397 : // is an invalid function body size, so that there are not enough bytes in the
398 : // code section for the function body.
399 23742 : STREAM_TEST(TestErrorInCodeSectionDetectedByStreamingDecoder) {
400 6 : StreamTester tester;
401 :
402 : uint8_t code[] = {
403 : U32V_1(26), // !!! invalid body size !!!
404 : U32V_1(0), // locals count
405 : kExprGetLocal, 0, kExprEnd // body
406 6 : };
407 :
408 : const uint8_t bytes[] = {
409 : WASM_MODULE_HEADER, // module header
410 : kTypeSectionCode, // section code
411 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
412 : U32V_1(1), // type count
413 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
414 : kFunctionSectionCode, // section code
415 : U32V_1(1 + 3), // section size
416 : U32V_1(3), // functions count
417 : 0, // signature index
418 : 0, // signature index
419 : 0, // signature index
420 : kCodeSectionCode, // section code
421 : U32V_1(1 + arraysize(code) * 3), // section size
422 : U32V_1(3), // functions count
423 6 : };
424 :
425 : tester.OnBytesReceived(bytes, arraysize(bytes));
426 : tester.OnBytesReceived(code, arraysize(code));
427 : tester.OnBytesReceived(code, arraysize(code));
428 : tester.OnBytesReceived(code, arraysize(code));
429 : tester.FinishStream();
430 :
431 : tester.RunCompilerTasks();
432 :
433 6 : CHECK(tester.IsPromiseRejected());
434 6 : }
435 :
436 : // Test an error in the code section, found by the Compiler. The error is an
437 : // invalid return type.
438 23742 : STREAM_TEST(TestErrorInCodeSectionDetectedByCompiler) {
439 6 : StreamTester tester;
440 :
441 : uint8_t code[] = {
442 : U32V_1(4), // !!! invalid body size !!!
443 : U32V_1(0), // locals count
444 : kExprGetLocal, 0, kExprEnd // body
445 6 : };
446 :
447 : uint8_t invalid_code[] = {
448 : U32V_1(4), // !!! invalid body size !!!
449 : U32V_1(0), // locals count
450 : kExprI64Const, 0, kExprEnd // body
451 6 : };
452 :
453 : const uint8_t bytes[] = {
454 : WASM_MODULE_HEADER, // module header
455 : kTypeSectionCode, // section code
456 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
457 : U32V_1(1), // type count
458 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
459 : kFunctionSectionCode, // section code
460 : U32V_1(1 + 3), // section size
461 : U32V_1(3), // functions count
462 : 0, // signature index
463 : 0, // signature index
464 : 0, // signature index
465 : kCodeSectionCode, // section code
466 : U32V_1(1 + arraysize(code) * 2 +
467 : arraysize(invalid_code)), // section size
468 : U32V_1(3), // functions count
469 6 : };
470 :
471 : tester.OnBytesReceived(bytes, arraysize(bytes));
472 : tester.RunCompilerTasks();
473 : tester.OnBytesReceived(code, arraysize(code));
474 : tester.RunCompilerTasks();
475 : tester.OnBytesReceived(invalid_code, arraysize(invalid_code));
476 : tester.RunCompilerTasks();
477 : tester.OnBytesReceived(code, arraysize(code));
478 : tester.RunCompilerTasks();
479 : tester.FinishStream();
480 : tester.RunCompilerTasks();
481 :
482 6 : CHECK(tester.IsPromiseRejected());
483 6 : }
484 :
485 : // Test Abort before any bytes arrive.
486 23742 : STREAM_TEST(TestAbortImmediately) {
487 6 : StreamTester tester;
488 6 : tester.stream()->Abort();
489 6 : tester.RunCompilerTasks();
490 6 : }
491 :
492 : // Test Abort within a section.
493 23742 : STREAM_TEST(TestAbortWithinSection1) {
494 6 : StreamTester tester;
495 : const uint8_t bytes[] = {
496 : WASM_MODULE_HEADER, // module header
497 : kTypeSectionCode, // section code
498 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
499 : U32V_1(1) // type count
500 : // Type section is not yet complete.
501 6 : };
502 : tester.OnBytesReceived(bytes, arraysize(bytes));
503 : tester.RunCompilerTasks();
504 6 : tester.stream()->Abort();
505 6 : tester.RunCompilerTasks();
506 6 : }
507 :
508 : // Test Abort within a section.
509 23742 : STREAM_TEST(TestAbortWithinSection2) {
510 6 : StreamTester tester;
511 : const uint8_t bytes[] = {
512 : WASM_MODULE_HEADER, // module header
513 : kTypeSectionCode, // section code
514 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
515 : U32V_1(1), // type count
516 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
517 : kFunctionSectionCode, // section code
518 : U32V_1(1 + 3), // section size
519 : U32V_1(3), // functions count
520 : // Function section is not yet complete.
521 6 : };
522 : tester.OnBytesReceived(bytes, arraysize(bytes));
523 : tester.RunCompilerTasks();
524 6 : tester.stream()->Abort();
525 6 : tester.RunCompilerTasks();
526 6 : }
527 :
528 : // Test Abort just before the code section.
529 23742 : STREAM_TEST(TestAbortAfterSection) {
530 6 : StreamTester tester;
531 : const uint8_t bytes[] = {
532 : WASM_MODULE_HEADER, // module header
533 : kTypeSectionCode, // section code
534 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
535 : U32V_1(1), // type count
536 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
537 6 : };
538 : tester.OnBytesReceived(bytes, arraysize(bytes));
539 : tester.RunCompilerTasks();
540 6 : tester.stream()->Abort();
541 6 : tester.RunCompilerTasks();
542 6 : }
543 :
544 : // Test Abort after the function count in the code section. The compiler tasks
545 : // execute before the abort.
546 23742 : STREAM_TEST(TestAbortAfterFunctionsCount1) {
547 6 : StreamTester tester;
548 : const uint8_t bytes[] = {
549 : WASM_MODULE_HEADER, // module header
550 : kTypeSectionCode, // section code
551 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
552 : U32V_1(1), // type count
553 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
554 : kFunctionSectionCode, // section code
555 : U32V_1(1 + 3), // section size
556 : U32V_1(3), // functions count
557 : 0, // signature index
558 : 0, // signature index
559 : 0, // signature index
560 : kCodeSectionCode, // section code
561 : U32V_1(20), // section size
562 : U32V_1(3), // functions count
563 6 : };
564 : tester.OnBytesReceived(bytes, arraysize(bytes));
565 : tester.RunCompilerTasks();
566 6 : tester.stream()->Abort();
567 6 : tester.RunCompilerTasks();
568 6 : }
569 :
570 : // Test Abort after the function count in the code section. The compiler tasks
571 : // do not execute before the abort.
572 23742 : STREAM_TEST(TestAbortAfterFunctionsCount2) {
573 6 : StreamTester tester;
574 : const uint8_t bytes[] = {
575 : WASM_MODULE_HEADER, // module header
576 : kTypeSectionCode, // section code
577 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
578 : U32V_1(1), // type count
579 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
580 : kFunctionSectionCode, // section code
581 : U32V_1(1 + 3), // section size
582 : U32V_1(3), // functions count
583 : 0, // signature index
584 : 0, // signature index
585 : 0, // signature index
586 : kCodeSectionCode, // section code
587 : U32V_1(20), // section size
588 : U32V_1(3), // functions count
589 6 : };
590 : tester.OnBytesReceived(bytes, arraysize(bytes));
591 6 : tester.stream()->Abort();
592 6 : tester.RunCompilerTasks();
593 6 : }
594 :
595 : // Test Abort after some functions got compiled. The compiler tasks execute
596 : // before the abort.
597 23742 : STREAM_TEST(TestAbortAfterFunctionGotCompiled1) {
598 6 : StreamTester tester;
599 :
600 : uint8_t code[] = {
601 : U32V_1(4), // !!! invalid body size !!!
602 : U32V_1(0), // locals count
603 : kExprGetLocal, 0, kExprEnd // body
604 6 : };
605 :
606 : const uint8_t bytes[] = {
607 : WASM_MODULE_HEADER, // module header
608 : kTypeSectionCode, // section code
609 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
610 : U32V_1(1), // type count
611 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
612 : kFunctionSectionCode, // section code
613 : U32V_1(1 + 3), // section size
614 : U32V_1(3), // functions count
615 : 0, // signature index
616 : 0, // signature index
617 : 0, // signature index
618 : kCodeSectionCode, // section code
619 : U32V_1(20), // section size
620 : U32V_1(3), // functions count
621 6 : };
622 : tester.OnBytesReceived(bytes, arraysize(bytes));
623 : tester.OnBytesReceived(code, arraysize(code));
624 : tester.RunCompilerTasks();
625 6 : tester.stream()->Abort();
626 6 : tester.RunCompilerTasks();
627 6 : }
628 :
629 : // Test Abort after some functions got compiled. The compiler tasks execute
630 : // before the abort.
631 23742 : STREAM_TEST(TestAbortAfterFunctionGotCompiled2) {
632 6 : StreamTester tester;
633 :
634 : uint8_t code[] = {
635 : U32V_1(4), // !!! invalid body size !!!
636 : U32V_1(0), // locals count
637 : kExprGetLocal, 0, kExprEnd // body
638 6 : };
639 :
640 : const uint8_t bytes[] = {
641 : WASM_MODULE_HEADER, // module header
642 : kTypeSectionCode, // section code
643 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
644 : U32V_1(1), // type count
645 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
646 : kFunctionSectionCode, // section code
647 : U32V_1(1 + 3), // section size
648 : U32V_1(3), // functions count
649 : 0, // signature index
650 : 0, // signature index
651 : 0, // signature index
652 : kCodeSectionCode, // section code
653 : U32V_1(20), // section size
654 : U32V_1(3), // functions count
655 6 : };
656 : tester.OnBytesReceived(bytes, arraysize(bytes));
657 : tester.OnBytesReceived(code, arraysize(code));
658 6 : tester.stream()->Abort();
659 6 : tester.RunCompilerTasks();
660 6 : }
661 :
662 : // Test Abort after all functions got compiled.
663 23742 : STREAM_TEST(TestAbortAfterCodeSection1) {
664 6 : StreamTester tester;
665 :
666 : uint8_t code[] = {
667 : U32V_1(4), // body size
668 : U32V_1(0), // locals count
669 : kExprGetLocal, 0, kExprEnd // body
670 6 : };
671 :
672 : const uint8_t bytes[] = {
673 : WASM_MODULE_HEADER, // module header
674 : kTypeSectionCode, // section code
675 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
676 : U32V_1(1), // type count
677 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
678 : kFunctionSectionCode, // section code
679 : U32V_1(1 + 3), // section size
680 : U32V_1(3), // functions count
681 : 0, // signature index
682 : 0, // signature index
683 : 0, // signature index
684 : kCodeSectionCode, // section code
685 : U32V_1(1 + arraysize(code) * 3), // section size
686 : U32V_1(3), // functions count
687 6 : };
688 :
689 : tester.OnBytesReceived(bytes, arraysize(bytes));
690 : tester.OnBytesReceived(code, arraysize(code));
691 : tester.OnBytesReceived(code, arraysize(code));
692 : tester.OnBytesReceived(code, arraysize(code));
693 : tester.RunCompilerTasks();
694 6 : tester.stream()->Abort();
695 6 : tester.RunCompilerTasks();
696 6 : }
697 :
698 : // Test Abort after all functions got compiled.
699 23742 : STREAM_TEST(TestAbortAfterCodeSection2) {
700 6 : StreamTester tester;
701 :
702 : uint8_t code[] = {
703 : U32V_1(4), // body size
704 : U32V_1(0), // locals count
705 : kExprGetLocal, 0, kExprEnd // body
706 6 : };
707 :
708 : const uint8_t bytes[] = {
709 : WASM_MODULE_HEADER, // module header
710 : kTypeSectionCode, // section code
711 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
712 : U32V_1(1), // type count
713 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
714 : kFunctionSectionCode, // section code
715 : U32V_1(1 + 3), // section size
716 : U32V_1(3), // functions count
717 : 0, // signature index
718 : 0, // signature index
719 : 0, // signature index
720 : kCodeSectionCode, // section code
721 : U32V_1(1 + arraysize(code) * 3), // section size
722 : U32V_1(3), // functions count
723 6 : };
724 :
725 : tester.OnBytesReceived(bytes, arraysize(bytes));
726 : tester.OnBytesReceived(code, arraysize(code));
727 : tester.OnBytesReceived(code, arraysize(code));
728 : tester.OnBytesReceived(code, arraysize(code));
729 6 : tester.stream()->Abort();
730 6 : tester.RunCompilerTasks();
731 6 : }
732 :
733 23742 : STREAM_TEST(TestAbortAfterCompilationError1) {
734 6 : StreamTester tester;
735 :
736 : uint8_t code[] = {
737 : U32V_1(4), // !!! invalid body size !!!
738 : U32V_1(0), // locals count
739 : kExprGetLocal, 0, kExprEnd // body
740 6 : };
741 :
742 : uint8_t invalid_code[] = {
743 : U32V_1(4), // !!! invalid body size !!!
744 : U32V_1(0), // locals count
745 : kExprI64Const, 0, kExprEnd // body
746 6 : };
747 :
748 : const uint8_t bytes[] = {
749 : WASM_MODULE_HEADER, // module header
750 : kTypeSectionCode, // section code
751 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
752 : U32V_1(1), // type count
753 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
754 : kFunctionSectionCode, // section code
755 : U32V_1(1 + 3), // section size
756 : U32V_1(3), // functions count
757 : 0, // signature index
758 : 0, // signature index
759 : 0, // signature index
760 : kCodeSectionCode, // section code
761 : U32V_1(1 + arraysize(code) * 2 +
762 : arraysize(invalid_code)), // section size
763 : U32V_1(3), // functions count
764 6 : };
765 :
766 : tester.OnBytesReceived(bytes, arraysize(bytes));
767 : tester.OnBytesReceived(code, arraysize(code));
768 : tester.OnBytesReceived(invalid_code, arraysize(invalid_code));
769 : tester.OnBytesReceived(code, arraysize(code));
770 : tester.RunCompilerTasks();
771 6 : tester.stream()->Abort();
772 6 : tester.RunCompilerTasks();
773 6 : }
774 :
775 23742 : STREAM_TEST(TestAbortAfterCompilationError2) {
776 6 : StreamTester tester;
777 :
778 : uint8_t code[] = {
779 : U32V_1(4), // !!! invalid body size !!!
780 : U32V_1(0), // locals count
781 : kExprGetLocal, 0, kExprEnd // body
782 6 : };
783 :
784 : uint8_t invalid_code[] = {
785 : U32V_1(4), // !!! invalid body size !!!
786 : U32V_1(0), // locals count
787 : kExprI64Const, 0, kExprEnd // body
788 6 : };
789 :
790 : const uint8_t bytes[] = {
791 : WASM_MODULE_HEADER, // module header
792 : kTypeSectionCode, // section code
793 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
794 : U32V_1(1), // type count
795 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
796 : kFunctionSectionCode, // section code
797 : U32V_1(1 + 3), // section size
798 : U32V_1(3), // functions count
799 : 0, // signature index
800 : 0, // signature index
801 : 0, // signature index
802 : kCodeSectionCode, // section code
803 : U32V_1(1 + arraysize(code) * 2 +
804 : arraysize(invalid_code)), // section size
805 : U32V_1(3), // functions count
806 6 : };
807 :
808 : tester.OnBytesReceived(bytes, arraysize(bytes));
809 : tester.OnBytesReceived(code, arraysize(code));
810 : tester.OnBytesReceived(invalid_code, arraysize(invalid_code));
811 : tester.OnBytesReceived(code, arraysize(code));
812 6 : tester.stream()->Abort();
813 6 : tester.RunCompilerTasks();
814 6 : }
815 :
816 : #undef STREAM_TEST
817 :
818 : } // namespace wasm
819 : } // namespace internal
820 71154 : } // namespace v8
|