1 // Copyright 2017 The Chromium 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 "base/message_loop/message_loop.h"
6 #include "base/run_loop.h"
7 #include "base/task_scheduler/task_scheduler.h"
8 #include "mojo/core/embedder/embedder.h"
9 #include "mojo/public/cpp/bindings/binding.h"
10 #include "mojo/public/tools/fuzzers/fuzz_impl.h"
11
FuzzMessage(const uint8_t * data,size_t size,base::RunLoop * run)12 void FuzzMessage(const uint8_t* data, size_t size, base::RunLoop* run) {
13 fuzz::mojom::FuzzInterfacePtr fuzz;
14 auto impl = std::make_unique<FuzzImpl>(MakeRequest(&fuzz));
15 auto router = impl->binding_.RouterForTesting();
16
17 /* Create a mojo message with the appropriate payload size. */
18 mojo::Message message(0, 0, size, 0, nullptr);
19 if (message.data_num_bytes() < size) {
20 message.payload_buffer()->Allocate(size - message.data_num_bytes());
21 }
22
23 /* Set the raw message data. */
24 memcpy(message.mutable_data(), data, size);
25
26 /* Run the message through header validation, payload validation, and
27 * dispatch to the impl. */
28 router->SimulateReceivingMessageForTesting(&message);
29
30 /* Allow the harness function to return now. */
31 run->Quit();
32 }
33
34 /* Environment for the fuzzer. Initializes the mojo EDK and sets up a
35 * TaskScheduler, because Mojo messages must be sent and processed from
36 * TaskRunners. */
37 struct Environment {
EnvironmentEnvironment38 Environment() : message_loop(base::MessageLoop::TYPE_UI) {
39 base::TaskScheduler::CreateAndStartWithDefaultParams(
40 "MojoParseMessageFuzzerProcess");
41 mojo::core::Init();
42 }
43
44 /* Message loop to send and handle messages on. */
45 base::MessageLoop message_loop;
46
47 /* Suppress mojo validation failure logs. */
48 mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression;
49 };
50
51 // Entry point for LibFuzzer.
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)52 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
53 static Environment* env = new Environment();
54 /* Pass the data along to run on a MessageLoop, and wait for it to finish. */
55 base::RunLoop run;
56 env->message_loop.task_runner()->PostTask(
57 FROM_HERE, base::BindOnce(&FuzzMessage, data, size, &run));
58 run.Run();
59
60 return 0;
61 }
62