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 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 { 38 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. 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