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-inl.h"
6 : #include "src/objects-inl.h"
7 : #include "src/objects/managed.h"
8 : #include "src/v8.h"
9 : #include "src/vector.h"
10 :
11 : #include "src/wasm/module-decoder.h"
12 : #include "src/wasm/streaming-decoder.h"
13 : #include "src/wasm/wasm-engine.h"
14 : #include "src/wasm/wasm-module-builder.h"
15 : #include "src/wasm/wasm-module.h"
16 : #include "src/wasm/wasm-objects-inl.h"
17 : #include "src/wasm/wasm-objects.h"
18 : #include "src/wasm/wasm-serialization.h"
19 :
20 : #include "test/cctest/cctest.h"
21 :
22 : #include "test/common/wasm/test-signatures.h"
23 : #include "test/common/wasm/wasm-macro-gen.h"
24 :
25 : namespace v8 {
26 : namespace internal {
27 : namespace wasm {
28 :
29 288 : class MockPlatform final : public TestPlatform {
30 : public:
31 288 : MockPlatform() : task_runner_(std::make_shared<MockTaskRunner>()) {
32 : // Now that it's completely constructed, make this the current platform.
33 144 : i::V8::SetPlatformForTesting(this);
34 144 : }
35 :
36 344 : std::shared_ptr<TaskRunner> GetForegroundTaskRunner(
37 : v8::Isolate* isolate) override {
38 344 : return task_runner_;
39 : }
40 :
41 0 : void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override {
42 0 : task_runner_->PostTask(std::unique_ptr<Task>(task));
43 0 : }
44 :
45 1159 : void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override {
46 1159 : task_runner_->PostTask(std::move(task));
47 1159 : }
48 :
49 0 : bool IdleTasksEnabled(v8::Isolate* isolate) override { return false; }
50 :
51 304 : void ExecuteTasks() { task_runner_->ExecuteTasks(); }
52 :
53 : private:
54 720 : class MockTaskRunner final : public TaskRunner {
55 : public:
56 247 : void PostTask(std::unique_ptr<v8::Task> task) override {
57 : tasks_.push(std::move(task));
58 247 : }
59 :
60 17 : void PostDelayedTask(std::unique_ptr<Task> task,
61 : double delay_in_seconds) override {
62 : tasks_.push(std::move(task));
63 17 : }
64 :
65 0 : void PostIdleTask(std::unique_ptr<IdleTask> task) override {
66 0 : UNREACHABLE();
67 : }
68 :
69 0 : bool IdleTasksEnabled() override { return false; }
70 :
71 304 : void ExecuteTasks() {
72 3150 : while (!tasks_.empty()) {
73 : std::unique_ptr<Task> task = std::move(tasks_.front());
74 : tasks_.pop();
75 1423 : task->Run();
76 : }
77 304 : }
78 :
79 : private:
80 : // We do not execute tasks concurrently, so we only need one list of tasks.
81 : std::queue<std::unique_ptr<v8::Task>> tasks_;
82 : };
83 :
84 : std::shared_ptr<MockTaskRunner> task_runner_;
85 : };
86 :
87 : namespace {
88 :
89 : enum class CompilationState {
90 : kPending,
91 : kFinished,
92 : kFailed,
93 : };
94 :
95 312 : class TestResolver : public CompilationResultResolver {
96 : public:
97 : TestResolver(CompilationState* state, std::string* error_message,
98 : std::shared_ptr<NativeModule>* native_module)
99 : : state_(state),
100 : error_message_(error_message),
101 156 : native_module_(native_module) {}
102 :
103 56 : void OnCompilationSucceeded(i::Handle<i::WasmModuleObject> module) override {
104 56 : *state_ = CompilationState::kFinished;
105 56 : if (!module.is_null()) {
106 56 : *native_module_ = module->shared_native_module();
107 : }
108 56 : }
109 :
110 52 : void OnCompilationFailed(i::Handle<i::Object> error_reason) override {
111 52 : *state_ = CompilationState::kFailed;
112 : Handle<String> str =
113 104 : Object::ToString(CcTest::i_isolate(), error_reason).ToHandleChecked();
114 156 : error_message_->assign(str->ToCString().get());
115 52 : }
116 :
117 : private:
118 : CompilationState* const state_;
119 : std::string* const error_message_;
120 : std::shared_ptr<NativeModule>* const native_module_;
121 : };
122 :
123 312 : class StreamTester {
124 : public:
125 156 : StreamTester()
126 : : zone_(&allocator_, "StreamTester"),
127 312 : internal_scope_(CcTest::i_isolate()) {
128 156 : v8::Isolate* isolate = CcTest::isolate();
129 : i::Isolate* i_isolate = CcTest::i_isolate();
130 :
131 156 : v8::Local<v8::Context> context = isolate->GetCurrentContext();
132 :
133 468 : stream_ = i_isolate->wasm_engine()->StartStreamingCompilation(
134 : i_isolate, kAllWasmFeatures, v8::Utils::OpenHandle(*context),
135 312 : std::make_shared<TestResolver>(&state_, &error_message_,
136 : &native_module_));
137 156 : }
138 :
139 : std::shared_ptr<StreamingDecoder> stream() { return stream_; }
140 :
141 : // Compiled native module, valid after successful compile.
142 : std::shared_ptr<NativeModule> native_module() { return native_module_; }
143 :
144 : // Run all compiler tasks, both foreground and background tasks.
145 : void RunCompilerTasks() {
146 304 : static_cast<MockPlatform*>(i::V8::GetCurrentPlatform())->ExecuteTasks();
147 : }
148 :
149 : bool IsPromiseFulfilled() { return state_ == CompilationState::kFinished; }
150 :
151 : bool IsPromiseRejected() { return state_ == CompilationState::kFailed; }
152 :
153 : bool IsPromisePending() { return state_ == CompilationState::kPending; }
154 :
155 : void OnBytesReceived(const uint8_t* start, size_t length) {
156 348 : stream_->OnBytesReceived(Vector<const uint8_t>(start, length));
157 : }
158 :
159 108 : void FinishStream() { stream_->Finish(); }
160 :
161 : void SetCompiledModuleBytes(const uint8_t* start, size_t length) {
162 8 : stream_->SetCompiledModuleBytes(Vector<const uint8_t>(start, length));
163 : }
164 :
165 : Zone* zone() { return &zone_; }
166 :
167 : const std::string& error_message() const { return error_message_; }
168 :
169 : private:
170 : AccountingAllocator allocator_;
171 : Zone zone_;
172 : i::HandleScope internal_scope_;
173 : CompilationState state_ = CompilationState::kPending;
174 : std::string error_message_;
175 : std::shared_ptr<NativeModule> native_module_;
176 : std::shared_ptr<StreamingDecoder> stream_;
177 : };
178 : } // namespace
179 :
180 : #define STREAM_TEST(name) \
181 : void RunStream_##name(); \
182 : TEST(name) { \
183 : MockPlatform platform; \
184 : CcTest::InitializeVM(); \
185 : RunStream_##name(); \
186 : } \
187 : void RunStream_##name()
188 :
189 : // Create a valid module with 3 functions.
190 36 : ZoneBuffer GetValidModuleBytes(Zone* zone) {
191 : ZoneBuffer buffer(zone);
192 36 : TestSignatures sigs;
193 36 : WasmModuleBuilder builder(zone);
194 : {
195 36 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
196 36 : uint8_t code[] = {kExprGetLocal, 0, kExprEnd};
197 36 : f->EmitCode(code, arraysize(code));
198 : }
199 : {
200 36 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
201 36 : uint8_t code[] = {kExprGetLocal, 1, kExprEnd};
202 36 : f->EmitCode(code, arraysize(code));
203 : }
204 : {
205 36 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
206 36 : uint8_t code[] = {kExprGetLocal, 2, kExprEnd};
207 36 : f->EmitCode(code, arraysize(code));
208 : }
209 36 : builder.WriteTo(buffer);
210 36 : return buffer;
211 : }
212 :
213 : // Create the same valid module as above and serialize it to test streaming
214 : // with compiled module caching.
215 8 : ZoneBuffer GetValidCompiledModuleBytes(Zone* zone, ZoneBuffer wire_bytes) {
216 : // Use a tester to compile to a NativeModule.
217 16 : StreamTester tester;
218 : tester.OnBytesReceived(wire_bytes.begin(), wire_bytes.size());
219 : tester.FinishStream();
220 : tester.RunCompilerTasks();
221 8 : CHECK(tester.IsPromiseFulfilled());
222 : // Serialize the NativeModule.
223 : std::shared_ptr<NativeModule> native_module = tester.native_module();
224 8 : CHECK(native_module);
225 8 : i::wasm::WasmSerializer serializer(native_module.get());
226 8 : size_t size = serializer.GetSerializedNativeModuleSize();
227 8 : std::vector<byte> buffer(size);
228 8 : CHECK(serializer.SerializeNativeModule({buffer.data(), size}));
229 : ZoneBuffer result(zone, size);
230 8 : result.write(buffer.data(), size);
231 8 : return result;
232 : }
233 :
234 : // Test that all bytes arrive before doing any compilation. FinishStream is
235 : // called immediately.
236 26664 : STREAM_TEST(TestAllBytesArriveImmediatelyStreamFinishesFirst) {
237 8 : StreamTester tester;
238 4 : ZoneBuffer buffer = GetValidModuleBytes(tester.zone());
239 :
240 4 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
241 : tester.FinishStream();
242 :
243 : tester.RunCompilerTasks();
244 :
245 4 : CHECK(tester.IsPromiseFulfilled());
246 4 : }
247 :
248 : // Test that all bytes arrive before doing any compilation. FinishStream is
249 : // called after the compilation is done.
250 26664 : STREAM_TEST(TestAllBytesArriveAOTCompilerFinishesFirst) {
251 8 : StreamTester tester;
252 4 : ZoneBuffer buffer = GetValidModuleBytes(tester.zone());
253 :
254 4 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
255 :
256 : tester.RunCompilerTasks();
257 : tester.FinishStream();
258 : tester.RunCompilerTasks();
259 :
260 4 : CHECK(tester.IsPromiseFulfilled());
261 4 : }
262 :
263 8 : size_t GetFunctionOffset(i::Isolate* isolate, const uint8_t* buffer,
264 : size_t size, size_t index) {
265 16 : ModuleResult result = DecodeWasmModule(
266 : kAllWasmFeatures, buffer, buffer + size, false, ModuleOrigin::kWasmOrigin,
267 16 : isolate->counters(), isolate->wasm_engine()->allocator());
268 8 : CHECK(result.ok());
269 : const WasmFunction* func = &result.value()->functions[1];
270 16 : return func->code.offset();
271 : }
272 :
273 : // Test that some functions come in the beginning, some come after some
274 : // functions already got compiled.
275 26664 : STREAM_TEST(TestCutAfterOneFunctionStreamFinishesFirst) {
276 : i::Isolate* isolate = CcTest::i_isolate();
277 8 : StreamTester tester;
278 4 : ZoneBuffer buffer = GetValidModuleBytes(tester.zone());
279 :
280 4 : size_t offset = GetFunctionOffset(isolate, buffer.begin(), buffer.size(), 1);
281 : tester.OnBytesReceived(buffer.begin(), offset);
282 : tester.RunCompilerTasks();
283 4 : CHECK(tester.IsPromisePending());
284 4 : tester.OnBytesReceived(buffer.begin() + offset, buffer.size() - offset);
285 : tester.FinishStream();
286 : tester.RunCompilerTasks();
287 4 : CHECK(tester.IsPromiseFulfilled());
288 4 : }
289 :
290 : // Test that some functions come in the beginning, some come after some
291 : // functions already got compiled. Call FinishStream after the compilation is
292 : // done.
293 26664 : STREAM_TEST(TestCutAfterOneFunctionCompilerFinishesFirst) {
294 : i::Isolate* isolate = CcTest::i_isolate();
295 8 : StreamTester tester;
296 4 : ZoneBuffer buffer = GetValidModuleBytes(tester.zone());
297 :
298 4 : size_t offset = GetFunctionOffset(isolate, buffer.begin(), buffer.size(), 1);
299 : tester.OnBytesReceived(buffer.begin(), offset);
300 : tester.RunCompilerTasks();
301 4 : CHECK(tester.IsPromisePending());
302 4 : tester.OnBytesReceived(buffer.begin() + offset, buffer.size() - offset);
303 : tester.RunCompilerTasks();
304 : tester.FinishStream();
305 : tester.RunCompilerTasks();
306 4 : CHECK(tester.IsPromiseFulfilled());
307 4 : }
308 :
309 : // Create a module with an invalid global section.
310 12 : ZoneBuffer GetModuleWithInvalidSection(Zone* zone) {
311 : ZoneBuffer buffer(zone);
312 12 : TestSignatures sigs;
313 12 : WasmModuleBuilder builder(zone);
314 : // Add an invalid global to the module. The decoder will fail there.
315 12 : builder.AddGlobal(kWasmStmt, false, true,
316 12 : WasmInitExpr(WasmInitExpr::kGlobalIndex, 12));
317 : {
318 12 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
319 12 : uint8_t code[] = {kExprGetLocal, 0, kExprEnd};
320 12 : f->EmitCode(code, arraysize(code));
321 : }
322 : {
323 12 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
324 12 : uint8_t code[] = {kExprGetLocal, 1, kExprEnd};
325 12 : f->EmitCode(code, arraysize(code));
326 : }
327 : {
328 12 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
329 12 : uint8_t code[] = {kExprGetLocal, 2, kExprEnd};
330 12 : f->EmitCode(code, arraysize(code));
331 : }
332 12 : builder.WriteTo(buffer);
333 12 : return buffer;
334 : }
335 :
336 : // Test an error in a section, found by the ModuleDecoder.
337 26664 : STREAM_TEST(TestErrorInSectionStreamFinishesFirst) {
338 8 : StreamTester tester;
339 4 : ZoneBuffer buffer = GetModuleWithInvalidSection(tester.zone());
340 :
341 4 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
342 : tester.FinishStream();
343 :
344 : tester.RunCompilerTasks();
345 :
346 4 : CHECK(tester.IsPromiseRejected());
347 4 : }
348 :
349 26664 : STREAM_TEST(TestErrorInSectionCompilerFinishesFirst) {
350 8 : StreamTester tester;
351 4 : ZoneBuffer buffer = GetModuleWithInvalidSection(tester.zone());
352 :
353 4 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
354 : tester.RunCompilerTasks();
355 : tester.FinishStream();
356 : tester.RunCompilerTasks();
357 :
358 4 : CHECK(tester.IsPromiseRejected());
359 4 : }
360 :
361 26664 : STREAM_TEST(TestErrorInSectionWithCuts) {
362 8 : StreamTester tester;
363 4 : ZoneBuffer buffer = GetModuleWithInvalidSection(tester.zone());
364 :
365 : const uint8_t* current = buffer.begin();
366 4 : size_t remaining = buffer.end() - buffer.begin();
367 68 : while (current < buffer.end()) {
368 64 : size_t size = std::min(remaining, size_t{10});
369 : tester.OnBytesReceived(current, size);
370 : tester.RunCompilerTasks();
371 32 : current += 10;
372 32 : remaining -= size;
373 : }
374 : tester.FinishStream();
375 : tester.RunCompilerTasks();
376 :
377 4 : CHECK(tester.IsPromiseRejected());
378 4 : }
379 :
380 0 : ZoneBuffer GetModuleWithInvalidSectionSize(Zone* zone) {
381 : // We get a valid module and overwrite the size of the first section with an
382 : // invalid value.
383 12 : ZoneBuffer buffer = GetValidModuleBytes(zone);
384 : // 9 == 4 (wasm magic) + 4 (version) + 1 (section code)
385 : uint8_t* section_size_address = const_cast<uint8_t*>(buffer.begin()) + 9;
386 : // 0x808080800F is an invalid module size in leb encoding.
387 12 : section_size_address[0] = 0x80;
388 12 : section_size_address[1] = 0x80;
389 12 : section_size_address[2] = 0x80;
390 12 : section_size_address[3] = 0x80;
391 12 : section_size_address[4] = 0x0F;
392 0 : return buffer;
393 : }
394 :
395 26664 : STREAM_TEST(TestErrorInSectionSizeStreamFinishesFirst) {
396 8 : StreamTester tester;
397 : ZoneBuffer buffer = GetModuleWithInvalidSectionSize(tester.zone());
398 4 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
399 : tester.FinishStream();
400 : tester.RunCompilerTasks();
401 :
402 4 : CHECK(tester.IsPromiseRejected());
403 4 : }
404 :
405 26664 : STREAM_TEST(TestErrorInSectionSizeCompilerFinishesFirst) {
406 8 : StreamTester tester;
407 : ZoneBuffer buffer = GetModuleWithInvalidSectionSize(tester.zone());
408 4 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
409 : tester.RunCompilerTasks();
410 : tester.FinishStream();
411 : tester.RunCompilerTasks();
412 :
413 4 : CHECK(tester.IsPromiseRejected());
414 4 : }
415 :
416 26664 : STREAM_TEST(TestErrorInSectionSizeWithCuts) {
417 8 : StreamTester tester;
418 : ZoneBuffer buffer = GetModuleWithInvalidSectionSize(tester.zone());
419 : const uint8_t* current = buffer.begin();
420 4 : size_t remaining = buffer.end() - buffer.begin();
421 60 : while (current < buffer.end()) {
422 56 : size_t size = std::min(remaining, size_t{10});
423 : tester.OnBytesReceived(current, size);
424 : tester.RunCompilerTasks();
425 28 : current += 10;
426 28 : remaining -= size;
427 : }
428 : tester.RunCompilerTasks();
429 : tester.FinishStream();
430 : tester.RunCompilerTasks();
431 :
432 4 : CHECK(tester.IsPromiseRejected());
433 4 : }
434 :
435 : // Test an error in the code section, found by the ModuleDecoder. The error is a
436 : // functions count in the code section which differs from the functions count in
437 : // the function section.
438 26664 : STREAM_TEST(TestErrorInCodeSectionDetectedByModuleDecoder) {
439 8 : StreamTester tester;
440 :
441 : uint8_t code[] = {
442 : U32V_1(4), // body size
443 : U32V_1(0), // locals count
444 : kExprGetLocal, 0, kExprEnd // body
445 4 : };
446 :
447 : const uint8_t bytes[] = {
448 : WASM_MODULE_HEADER, // module header
449 : kTypeSectionCode, // section code
450 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
451 : U32V_1(1), // type count
452 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
453 : kFunctionSectionCode, // section code
454 : U32V_1(1 + 3), // section size
455 : U32V_1(3), // functions count
456 : 0, // signature index
457 : 0, // signature index
458 : 0, // signature index
459 : kCodeSectionCode, // section code
460 : U32V_1(1 + arraysize(code) * 2), // section size
461 : U32V_1(2), // !!! invalid function count !!!
462 4 : };
463 :
464 : tester.OnBytesReceived(bytes, arraysize(bytes));
465 : tester.OnBytesReceived(code, arraysize(code));
466 : tester.OnBytesReceived(code, arraysize(code));
467 : tester.FinishStream();
468 :
469 : tester.RunCompilerTasks();
470 :
471 4 : CHECK(tester.IsPromiseRejected());
472 4 : }
473 :
474 : // Test an error in the code section, found by the StreamingDecoder. The error
475 : // is an invalid function body size, so that there are not enough bytes in the
476 : // code section for the function body.
477 26664 : STREAM_TEST(TestErrorInCodeSectionDetectedByStreamingDecoder) {
478 8 : StreamTester tester;
479 :
480 : uint8_t code[] = {
481 : U32V_1(26), // !!! invalid body size !!!
482 : U32V_1(0), // locals count
483 : kExprGetLocal, 0, kExprEnd // body
484 4 : };
485 :
486 : const uint8_t bytes[] = {
487 : WASM_MODULE_HEADER, // module header
488 : kTypeSectionCode, // section code
489 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
490 : U32V_1(1), // type count
491 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
492 : kFunctionSectionCode, // section code
493 : U32V_1(1 + 3), // section size
494 : U32V_1(3), // functions count
495 : 0, // signature index
496 : 0, // signature index
497 : 0, // signature index
498 : kCodeSectionCode, // section code
499 : U32V_1(1 + arraysize(code) * 3), // section size
500 : U32V_1(3), // functions count
501 4 : };
502 :
503 : tester.OnBytesReceived(bytes, arraysize(bytes));
504 : tester.OnBytesReceived(code, arraysize(code));
505 : tester.OnBytesReceived(code, arraysize(code));
506 : tester.OnBytesReceived(code, arraysize(code));
507 : tester.FinishStream();
508 :
509 : tester.RunCompilerTasks();
510 :
511 4 : CHECK(tester.IsPromiseRejected());
512 4 : }
513 :
514 : // Test an error in the code section, found by the Compiler. The error is an
515 : // invalid return type.
516 26664 : STREAM_TEST(TestErrorInCodeSectionDetectedByCompiler) {
517 8 : StreamTester tester;
518 :
519 : uint8_t code[] = {
520 : U32V_1(4), // !!! invalid body size !!!
521 : U32V_1(0), // locals count
522 : kExprGetLocal, 0, kExprEnd // body
523 4 : };
524 :
525 : uint8_t invalid_code[] = {
526 : U32V_1(4), // !!! invalid body size !!!
527 : U32V_1(0), // locals count
528 : kExprI64Const, 0, kExprEnd // body
529 4 : };
530 :
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 : kFunctionSectionCode, // section code
538 : U32V_1(1 + 3), // section size
539 : U32V_1(3), // functions count
540 : 0, // signature index
541 : 0, // signature index
542 : 0, // signature index
543 : kCodeSectionCode, // section code
544 : U32V_1(1 + arraysize(code) * 2 +
545 : arraysize(invalid_code)), // section size
546 : U32V_1(3), // functions count
547 4 : };
548 :
549 : tester.OnBytesReceived(bytes, arraysize(bytes));
550 : tester.RunCompilerTasks();
551 : tester.OnBytesReceived(code, arraysize(code));
552 : tester.RunCompilerTasks();
553 : tester.OnBytesReceived(invalid_code, arraysize(invalid_code));
554 : tester.RunCompilerTasks();
555 : tester.OnBytesReceived(code, arraysize(code));
556 : tester.RunCompilerTasks();
557 : tester.FinishStream();
558 : tester.RunCompilerTasks();
559 :
560 4 : CHECK(tester.IsPromiseRejected());
561 4 : }
562 :
563 : // Test Abort before any bytes arrive.
564 26664 : STREAM_TEST(TestAbortImmediately) {
565 8 : StreamTester tester;
566 8 : tester.stream()->Abort();
567 : tester.RunCompilerTasks();
568 4 : }
569 :
570 : // Test Abort within a section.
571 26664 : STREAM_TEST(TestAbortWithinSection1) {
572 8 : StreamTester tester;
573 : const uint8_t bytes[] = {
574 : WASM_MODULE_HEADER, // module header
575 : kTypeSectionCode, // section code
576 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
577 : U32V_1(1) // type count
578 : // Type section is not yet complete.
579 4 : };
580 : tester.OnBytesReceived(bytes, arraysize(bytes));
581 : tester.RunCompilerTasks();
582 8 : tester.stream()->Abort();
583 : tester.RunCompilerTasks();
584 4 : }
585 :
586 : // Test Abort within a section.
587 26664 : STREAM_TEST(TestAbortWithinSection2) {
588 8 : StreamTester tester;
589 : const uint8_t bytes[] = {
590 : WASM_MODULE_HEADER, // module header
591 : kTypeSectionCode, // section code
592 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
593 : U32V_1(1), // type count
594 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
595 : kFunctionSectionCode, // section code
596 : U32V_1(1 + 3), // section size
597 : U32V_1(3), // functions count
598 : // Function section is not yet complete.
599 4 : };
600 : tester.OnBytesReceived(bytes, arraysize(bytes));
601 : tester.RunCompilerTasks();
602 8 : tester.stream()->Abort();
603 : tester.RunCompilerTasks();
604 4 : }
605 :
606 : // Test Abort just before the code section.
607 26664 : STREAM_TEST(TestAbortAfterSection) {
608 8 : StreamTester tester;
609 : const uint8_t bytes[] = {
610 : WASM_MODULE_HEADER, // module header
611 : kTypeSectionCode, // section code
612 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
613 : U32V_1(1), // type count
614 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
615 4 : };
616 : tester.OnBytesReceived(bytes, arraysize(bytes));
617 : tester.RunCompilerTasks();
618 8 : tester.stream()->Abort();
619 : tester.RunCompilerTasks();
620 4 : }
621 :
622 : // Test Abort after the function count in the code section. The compiler tasks
623 : // execute before the abort.
624 26664 : STREAM_TEST(TestAbortAfterFunctionsCount1) {
625 8 : StreamTester tester;
626 : const uint8_t bytes[] = {
627 : WASM_MODULE_HEADER, // module header
628 : kTypeSectionCode, // section code
629 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
630 : U32V_1(1), // type count
631 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
632 : kFunctionSectionCode, // section code
633 : U32V_1(1 + 3), // section size
634 : U32V_1(3), // functions count
635 : 0, // signature index
636 : 0, // signature index
637 : 0, // signature index
638 : kCodeSectionCode, // section code
639 : U32V_1(20), // section size
640 : U32V_1(3), // functions count
641 4 : };
642 : tester.OnBytesReceived(bytes, arraysize(bytes));
643 : tester.RunCompilerTasks();
644 8 : tester.stream()->Abort();
645 : tester.RunCompilerTasks();
646 4 : }
647 :
648 : // Test Abort after the function count in the code section. The compiler tasks
649 : // do not execute before the abort.
650 26664 : STREAM_TEST(TestAbortAfterFunctionsCount2) {
651 8 : StreamTester tester;
652 : const uint8_t bytes[] = {
653 : WASM_MODULE_HEADER, // module header
654 : kTypeSectionCode, // section code
655 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
656 : U32V_1(1), // type count
657 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
658 : kFunctionSectionCode, // section code
659 : U32V_1(1 + 3), // section size
660 : U32V_1(3), // functions count
661 : 0, // signature index
662 : 0, // signature index
663 : 0, // signature index
664 : kCodeSectionCode, // section code
665 : U32V_1(20), // section size
666 : U32V_1(3), // functions count
667 4 : };
668 : tester.OnBytesReceived(bytes, arraysize(bytes));
669 8 : tester.stream()->Abort();
670 : tester.RunCompilerTasks();
671 4 : }
672 :
673 : // Test Abort after some functions got compiled. The compiler tasks execute
674 : // before the abort.
675 26664 : STREAM_TEST(TestAbortAfterFunctionGotCompiled1) {
676 8 : StreamTester tester;
677 :
678 : uint8_t code[] = {
679 : U32V_1(4), // !!! invalid body size !!!
680 : U32V_1(0), // locals count
681 : kExprGetLocal, 0, kExprEnd // body
682 4 : };
683 :
684 : const uint8_t bytes[] = {
685 : WASM_MODULE_HEADER, // module header
686 : kTypeSectionCode, // section code
687 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
688 : U32V_1(1), // type count
689 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
690 : kFunctionSectionCode, // section code
691 : U32V_1(1 + 3), // section size
692 : U32V_1(3), // functions count
693 : 0, // signature index
694 : 0, // signature index
695 : 0, // signature index
696 : kCodeSectionCode, // section code
697 : U32V_1(20), // section size
698 : U32V_1(3), // functions count
699 4 : };
700 : tester.OnBytesReceived(bytes, arraysize(bytes));
701 : tester.OnBytesReceived(code, arraysize(code));
702 : tester.RunCompilerTasks();
703 8 : tester.stream()->Abort();
704 : tester.RunCompilerTasks();
705 4 : }
706 :
707 : // Test Abort after some functions got compiled. The compiler tasks execute
708 : // before the abort.
709 26664 : STREAM_TEST(TestAbortAfterFunctionGotCompiled2) {
710 8 : StreamTester tester;
711 :
712 : uint8_t code[] = {
713 : U32V_1(4), // !!! invalid body size !!!
714 : U32V_1(0), // locals count
715 : kExprGetLocal, 0, kExprEnd // body
716 4 : };
717 :
718 : const uint8_t bytes[] = {
719 : WASM_MODULE_HEADER, // module header
720 : kTypeSectionCode, // section code
721 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
722 : U32V_1(1), // type count
723 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
724 : kFunctionSectionCode, // section code
725 : U32V_1(1 + 3), // section size
726 : U32V_1(3), // functions count
727 : 0, // signature index
728 : 0, // signature index
729 : 0, // signature index
730 : kCodeSectionCode, // section code
731 : U32V_1(20), // section size
732 : U32V_1(3), // functions count
733 4 : };
734 : tester.OnBytesReceived(bytes, arraysize(bytes));
735 : tester.OnBytesReceived(code, arraysize(code));
736 8 : tester.stream()->Abort();
737 : tester.RunCompilerTasks();
738 4 : }
739 :
740 : // Test Abort after all functions got compiled.
741 26664 : STREAM_TEST(TestAbortAfterCodeSection1) {
742 8 : StreamTester tester;
743 :
744 : uint8_t code[] = {
745 : U32V_1(4), // body size
746 : U32V_1(0), // locals count
747 : kExprGetLocal, 0, kExprEnd // body
748 4 : };
749 :
750 : const uint8_t bytes[] = {
751 : WASM_MODULE_HEADER, // module header
752 : kTypeSectionCode, // section code
753 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
754 : U32V_1(1), // type count
755 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
756 : kFunctionSectionCode, // section code
757 : U32V_1(1 + 3), // section size
758 : U32V_1(3), // functions count
759 : 0, // signature index
760 : 0, // signature index
761 : 0, // signature index
762 : kCodeSectionCode, // section code
763 : U32V_1(1 + arraysize(code) * 3), // section size
764 : U32V_1(3), // functions count
765 4 : };
766 :
767 : tester.OnBytesReceived(bytes, arraysize(bytes));
768 : tester.OnBytesReceived(code, arraysize(code));
769 : tester.OnBytesReceived(code, arraysize(code));
770 : tester.OnBytesReceived(code, arraysize(code));
771 : tester.RunCompilerTasks();
772 8 : tester.stream()->Abort();
773 : tester.RunCompilerTasks();
774 4 : }
775 :
776 : // Test Abort after all functions got compiled.
777 26664 : STREAM_TEST(TestAbortAfterCodeSection2) {
778 8 : StreamTester tester;
779 :
780 : uint8_t code[] = {
781 : U32V_1(4), // body size
782 : U32V_1(0), // locals count
783 : kExprGetLocal, 0, kExprEnd // body
784 4 : };
785 :
786 : const uint8_t bytes[] = {
787 : WASM_MODULE_HEADER, // module header
788 : kTypeSectionCode, // section code
789 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
790 : U32V_1(1), // type count
791 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
792 : kFunctionSectionCode, // section code
793 : U32V_1(1 + 3), // section size
794 : U32V_1(3), // functions count
795 : 0, // signature index
796 : 0, // signature index
797 : 0, // signature index
798 : kCodeSectionCode, // section code
799 : U32V_1(1 + arraysize(code) * 3), // section size
800 : U32V_1(3), // functions count
801 4 : };
802 :
803 : tester.OnBytesReceived(bytes, arraysize(bytes));
804 : tester.OnBytesReceived(code, arraysize(code));
805 : tester.OnBytesReceived(code, arraysize(code));
806 : tester.OnBytesReceived(code, arraysize(code));
807 8 : tester.stream()->Abort();
808 : tester.RunCompilerTasks();
809 4 : }
810 :
811 26664 : STREAM_TEST(TestAbortAfterCompilationError1) {
812 8 : StreamTester tester;
813 :
814 : uint8_t code[] = {
815 : U32V_1(4), // !!! invalid body size !!!
816 : U32V_1(0), // locals count
817 : kExprGetLocal, 0, kExprEnd // body
818 4 : };
819 :
820 : uint8_t invalid_code[] = {
821 : U32V_1(4), // !!! invalid body size !!!
822 : U32V_1(0), // locals count
823 : kExprI64Const, 0, kExprEnd // body
824 4 : };
825 :
826 : const uint8_t bytes[] = {
827 : WASM_MODULE_HEADER, // module header
828 : kTypeSectionCode, // section code
829 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
830 : U32V_1(1), // type count
831 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
832 : kFunctionSectionCode, // section code
833 : U32V_1(1 + 3), // section size
834 : U32V_1(3), // functions count
835 : 0, // signature index
836 : 0, // signature index
837 : 0, // signature index
838 : kCodeSectionCode, // section code
839 : U32V_1(1 + arraysize(code) * 2 +
840 : arraysize(invalid_code)), // section size
841 : U32V_1(3), // functions count
842 4 : };
843 :
844 : tester.OnBytesReceived(bytes, arraysize(bytes));
845 : tester.OnBytesReceived(code, arraysize(code));
846 : tester.OnBytesReceived(invalid_code, arraysize(invalid_code));
847 : tester.OnBytesReceived(code, arraysize(code));
848 : tester.RunCompilerTasks();
849 8 : tester.stream()->Abort();
850 : tester.RunCompilerTasks();
851 4 : }
852 :
853 26664 : STREAM_TEST(TestAbortAfterCompilationError2) {
854 8 : StreamTester tester;
855 :
856 : uint8_t code[] = {
857 : U32V_1(4), // !!! invalid body size !!!
858 : U32V_1(0), // locals count
859 : kExprGetLocal, 0, kExprEnd // body
860 4 : };
861 :
862 : uint8_t invalid_code[] = {
863 : U32V_1(4), // !!! invalid body size !!!
864 : U32V_1(0), // locals count
865 : kExprI64Const, 0, kExprEnd // body
866 4 : };
867 :
868 : const uint8_t bytes[] = {
869 : WASM_MODULE_HEADER, // module header
870 : kTypeSectionCode, // section code
871 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
872 : U32V_1(1), // type count
873 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
874 : kFunctionSectionCode, // section code
875 : U32V_1(1 + 3), // section size
876 : U32V_1(3), // functions count
877 : 0, // signature index
878 : 0, // signature index
879 : 0, // signature index
880 : kCodeSectionCode, // section code
881 : U32V_1(1 + arraysize(code) * 2 +
882 : arraysize(invalid_code)), // section size
883 : U32V_1(3), // functions count
884 4 : };
885 :
886 : tester.OnBytesReceived(bytes, arraysize(bytes));
887 : tester.OnBytesReceived(code, arraysize(code));
888 : tester.OnBytesReceived(invalid_code, arraysize(invalid_code));
889 : tester.OnBytesReceived(code, arraysize(code));
890 8 : tester.stream()->Abort();
891 : tester.RunCompilerTasks();
892 4 : }
893 :
894 26664 : STREAM_TEST(TestOnlyModuleHeader) {
895 8 : StreamTester tester;
896 :
897 : const uint8_t bytes[] = {
898 : WASM_MODULE_HEADER, // module header
899 4 : };
900 :
901 : tester.OnBytesReceived(bytes, arraysize(bytes));
902 : tester.FinishStream();
903 : tester.RunCompilerTasks();
904 :
905 4 : CHECK(tester.IsPromiseFulfilled());
906 4 : }
907 :
908 26664 : STREAM_TEST(TestModuleWithZeroFunctions) {
909 8 : StreamTester tester;
910 :
911 : const uint8_t bytes[] = {
912 : WASM_MODULE_HEADER, // module header
913 : kTypeSectionCode, // section code
914 : U32V_1(1), // section size
915 : U32V_1(0), // type count
916 : kFunctionSectionCode, // section code
917 : U32V_1(1), // section size
918 : U32V_1(0), // functions count
919 : kCodeSectionCode, // section code
920 : U32V_1(1), // section size
921 : U32V_1(0), // functions count
922 4 : };
923 :
924 : tester.OnBytesReceived(bytes, arraysize(bytes));
925 : tester.FinishStream();
926 : tester.RunCompilerTasks();
927 4 : CHECK(tester.IsPromiseFulfilled());
928 4 : }
929 :
930 26664 : STREAM_TEST(TestModuleWithMultipleFunctions) {
931 8 : StreamTester tester;
932 :
933 : uint8_t code[] = {
934 : U32V_1(4), // body size
935 : U32V_1(0), // locals count
936 : kExprGetLocal, 0, kExprEnd // body
937 4 : };
938 :
939 : const uint8_t bytes[] = {
940 : WASM_MODULE_HEADER, // module header
941 : kTypeSectionCode, // section code
942 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
943 : U32V_1(1), // type count
944 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
945 : kFunctionSectionCode, // section code
946 : U32V_1(1 + 3), // section size
947 : U32V_1(3), // functions count
948 : 0, // signature index
949 : 0, // signature index
950 : 0, // signature index
951 : kCodeSectionCode, // section code
952 : U32V_1(1 + arraysize(code) * 3), // section size
953 : U32V_1(3), // functions count
954 4 : };
955 :
956 : tester.OnBytesReceived(bytes, arraysize(bytes));
957 : tester.OnBytesReceived(code, arraysize(code));
958 : tester.OnBytesReceived(code, arraysize(code));
959 : tester.RunCompilerTasks();
960 : tester.OnBytesReceived(code, arraysize(code));
961 : tester.FinishStream();
962 : tester.RunCompilerTasks();
963 4 : CHECK(tester.IsPromiseFulfilled());
964 4 : }
965 :
966 26664 : STREAM_TEST(TestModuleWithDataSection) {
967 8 : StreamTester tester;
968 :
969 : uint8_t code[] = {
970 : U32V_1(4), // body size
971 : U32V_1(0), // locals count
972 : kExprGetLocal, 0, kExprEnd // body
973 4 : };
974 :
975 : const uint8_t bytes[] = {
976 : WASM_MODULE_HEADER, // module header
977 : kTypeSectionCode, // section code
978 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
979 : U32V_1(1), // type count
980 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
981 : kFunctionSectionCode, // section code
982 : U32V_1(1 + 3), // section size
983 : U32V_1(3), // functions count
984 : 0, // signature index
985 : 0, // signature index
986 : 0, // signature index
987 : kCodeSectionCode, // section code
988 : U32V_1(1 + arraysize(code) * 3), // section size
989 : U32V_1(3), // functions count
990 4 : };
991 :
992 : const uint8_t data_section[] = {
993 : kDataSectionCode, // section code
994 : U32V_1(1), // section size
995 : U32V_1(0), // data segment count
996 4 : };
997 : tester.OnBytesReceived(bytes, arraysize(bytes));
998 : tester.OnBytesReceived(code, arraysize(code));
999 : tester.OnBytesReceived(code, arraysize(code));
1000 : tester.OnBytesReceived(code, arraysize(code));
1001 : tester.RunCompilerTasks();
1002 : tester.OnBytesReceived(data_section, arraysize(data_section));
1003 : tester.RunCompilerTasks();
1004 : tester.FinishStream();
1005 : tester.RunCompilerTasks();
1006 4 : CHECK(tester.IsPromiseFulfilled());
1007 4 : }
1008 : // Test that all bytes arrive before doing any compilation. FinishStream is
1009 : // called immediately.
1010 26664 : STREAM_TEST(TestModuleWithImportedFunction) {
1011 8 : StreamTester tester;
1012 : ZoneBuffer buffer(tester.zone());
1013 4 : TestSignatures sigs;
1014 4 : WasmModuleBuilder builder(tester.zone());
1015 4 : builder.AddImport(ArrayVector("Test"), sigs.i_iii());
1016 : {
1017 4 : WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
1018 4 : uint8_t code[] = {kExprGetLocal, 0, kExprEnd};
1019 4 : f->EmitCode(code, arraysize(code));
1020 : }
1021 4 : builder.WriteTo(buffer);
1022 :
1023 4 : tester.OnBytesReceived(buffer.begin(), buffer.end() - buffer.begin());
1024 : tester.FinishStream();
1025 :
1026 : tester.RunCompilerTasks();
1027 :
1028 4 : CHECK(tester.IsPromiseFulfilled());
1029 4 : }
1030 :
1031 26664 : STREAM_TEST(TestModuleWithErrorAfterDataSection) {
1032 8 : StreamTester tester;
1033 :
1034 : const uint8_t bytes[] = {
1035 : WASM_MODULE_HEADER, // module header
1036 : kTypeSectionCode, // section code
1037 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
1038 : U32V_1(1), // type count
1039 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
1040 : kFunctionSectionCode, // section code
1041 : U32V_1(1 + 1), // section size
1042 : U32V_1(1), // functions count
1043 : 0, // signature index
1044 : kCodeSectionCode, // section code
1045 : U32V_1(6), // section size
1046 : U32V_1(1), // functions count
1047 : U32V_1(4), // body size
1048 : U32V_1(0), // locals count
1049 : kExprGetLocal, // some code
1050 : 0, // some code
1051 : kExprEnd, // some code
1052 : kDataSectionCode, // section code
1053 : U32V_1(1), // section size
1054 : U32V_1(0), // data segment count
1055 : kUnknownSectionCode, // section code
1056 : U32V_1(1), // invalid section size
1057 4 : };
1058 :
1059 : tester.OnBytesReceived(bytes, arraysize(bytes));
1060 : tester.FinishStream();
1061 : tester.RunCompilerTasks();
1062 4 : CHECK(tester.IsPromiseRejected());
1063 4 : }
1064 :
1065 : // Test that cached bytes work.
1066 26664 : STREAM_TEST(TestDeserializationBypassesCompilation) {
1067 8 : StreamTester tester;
1068 4 : ZoneBuffer wire_bytes = GetValidModuleBytes(tester.zone());
1069 : ZoneBuffer module_bytes =
1070 4 : GetValidCompiledModuleBytes(tester.zone(), wire_bytes);
1071 : tester.SetCompiledModuleBytes(module_bytes.begin(), module_bytes.size());
1072 : tester.OnBytesReceived(wire_bytes.begin(), wire_bytes.size());
1073 : tester.FinishStream();
1074 :
1075 : tester.RunCompilerTasks();
1076 :
1077 4 : CHECK(tester.IsPromiseFulfilled());
1078 4 : }
1079 :
1080 : // Test that bad cached bytes don't cause compilation of wire bytes to fail.
1081 26664 : STREAM_TEST(TestDeserializationFails) {
1082 8 : StreamTester tester;
1083 4 : ZoneBuffer wire_bytes = GetValidModuleBytes(tester.zone());
1084 : ZoneBuffer module_bytes =
1085 4 : GetValidCompiledModuleBytes(tester.zone(), wire_bytes);
1086 : // corrupt header
1087 4 : byte first_byte = *module_bytes.begin();
1088 4 : module_bytes.patch_u8(0, first_byte + 1);
1089 : tester.SetCompiledModuleBytes(module_bytes.begin(), module_bytes.size());
1090 : tester.OnBytesReceived(wire_bytes.begin(), wire_bytes.size());
1091 : tester.FinishStream();
1092 :
1093 : tester.RunCompilerTasks();
1094 :
1095 4 : CHECK(tester.IsPromiseFulfilled());
1096 4 : }
1097 :
1098 : // Test that a non-empty function section with a missing code section fails.
1099 26664 : STREAM_TEST(TestFunctionSectionWithoutCodeSection) {
1100 8 : StreamTester tester;
1101 :
1102 : const uint8_t bytes[] = {
1103 : WASM_MODULE_HEADER, // module header
1104 : kTypeSectionCode, // section code
1105 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
1106 : U32V_1(1), // type count
1107 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
1108 : kFunctionSectionCode, // section code
1109 : U32V_1(1 + 3), // section size
1110 : U32V_1(3), // functions count
1111 : 0, // signature index
1112 : 0, // signature index
1113 : 0, // signature index
1114 4 : };
1115 :
1116 : tester.OnBytesReceived(bytes, arraysize(bytes));
1117 : tester.FinishStream();
1118 :
1119 : tester.RunCompilerTasks();
1120 :
1121 4 : CHECK(tester.IsPromiseRejected());
1122 4 : }
1123 :
1124 26664 : STREAM_TEST(TestSetModuleCompiledCallback) {
1125 8 : StreamTester tester;
1126 4 : bool callback_called = false;
1127 8 : tester.stream()->SetModuleCompiledCallback(
1128 4 : [&callback_called](const std::shared_ptr<NativeModule> module) {
1129 4 : callback_called = true;
1130 4 : });
1131 :
1132 : uint8_t code[] = {
1133 : U32V_1(4), // body size
1134 : U32V_1(0), // locals count
1135 : kExprGetLocal, 0, kExprEnd // body
1136 4 : };
1137 :
1138 : const uint8_t bytes[] = {
1139 : WASM_MODULE_HEADER, // module header
1140 : kTypeSectionCode, // section code
1141 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
1142 : U32V_1(1), // type count
1143 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
1144 : kFunctionSectionCode, // section code
1145 : U32V_1(1 + 3), // section size
1146 : U32V_1(3), // functions count
1147 : 0, // signature index
1148 : 0, // signature index
1149 : 0, // signature index
1150 : kCodeSectionCode, // section code
1151 : U32V_1(1 + arraysize(code) * 3), // section size
1152 : U32V_1(3), // functions count
1153 4 : };
1154 :
1155 : tester.OnBytesReceived(bytes, arraysize(bytes));
1156 : tester.OnBytesReceived(code, arraysize(code));
1157 : tester.OnBytesReceived(code, arraysize(code));
1158 : tester.OnBytesReceived(code, arraysize(code));
1159 : tester.FinishStream();
1160 : tester.RunCompilerTasks();
1161 4 : CHECK(tester.IsPromiseFulfilled());
1162 4 : CHECK(callback_called);
1163 4 : }
1164 :
1165 : // Test that a compile error contains the name of the function, even if the name
1166 : // section is not present at the time the error is detected.
1167 26664 : STREAM_TEST(TestCompileErrorFunctionName) {
1168 : const uint8_t bytes_module_with_code[] = {
1169 : WASM_MODULE_HEADER, // module header
1170 : kTypeSectionCode, // section code
1171 : U32V_1(1 + SIZEOF_SIG_ENTRY_x_x), // section size
1172 : U32V_1(1), // type count
1173 : SIG_ENTRY_x_x(kLocalI32, kLocalI32), // signature entry
1174 : kFunctionSectionCode, // section code
1175 : U32V_1(2), // section size
1176 : U32V_1(1), // functions count
1177 : 0, // signature index
1178 : kCodeSectionCode, // section code
1179 : U32V_1(3), // section size
1180 : U32V_1(1), // functions count
1181 : 1, // body size
1182 : kExprNop, // body
1183 4 : };
1184 :
1185 : const uint8_t bytes_names[] = {
1186 : kUnknownSectionCode, // section code
1187 : U32V_1(11), // section size
1188 : 4, // section name length
1189 : 'n', // section name
1190 : 'a', // section name
1191 : 'm', // section name
1192 : 'e', // section name
1193 : NameSectionKindCode::kFunction, // name section kind
1194 : 4, // name section kind length
1195 : 1, // num function names
1196 : 0, // function index
1197 : 1, // function name length
1198 : 'f', // function name
1199 4 : };
1200 :
1201 20 : for (bool late_names : {false, true}) {
1202 16 : StreamTester tester;
1203 :
1204 : tester.OnBytesReceived(bytes_module_with_code,
1205 : arraysize(bytes_module_with_code));
1206 8 : if (late_names) tester.RunCompilerTasks();
1207 : tester.OnBytesReceived(bytes_names, arraysize(bytes_names));
1208 : tester.FinishStream();
1209 :
1210 : tester.RunCompilerTasks();
1211 :
1212 8 : CHECK(tester.IsPromiseRejected());
1213 8 : CHECK_EQ(
1214 : "CompileError: WebAssembly.compile(): Compiling function #0:\"f\" "
1215 : "failed: function body must end with \"end\" opcode @+25",
1216 : tester.error_message());
1217 : }
1218 4 : }
1219 :
1220 : #undef STREAM_TEST
1221 :
1222 : } // namespace wasm
1223 : } // namespace internal
1224 79968 : } // namespace v8
|