/* * Copyright 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ProtoFuzzerMutator.h" #include "test/vts/proto/ComponentSpecificationMessage.pb.h" #include <unistd.h> #include <cstdlib> #include <iostream> #include <memory> #include <string> #include <vector> using std::cout; using std::endl; using std::make_unique; using std::string; using std::unique_ptr; using std::vector; namespace android { namespace vts { namespace fuzzer { // 64-bit random number generator. static unique_ptr<Random> random; // Parameters that were passed in to fuzzer. static ProtoFuzzerParams params; // Used to mutate inputs to hal driver. static unique_ptr<ProtoFuzzerMutator> mutator; // Used to exercise HIDL HAL's API. static unique_ptr<ProtoFuzzerRunner> runner; static ProtoFuzzerMutatorConfig mutator_config{ // Heuristic: values close to 0 are likely to be meaningful scalar input // values. [](Random &rand) { size_t dice_roll = rand(10); if (dice_roll < 3) { // With probability of 30% return an integer in range [0, 10). return rand(10); } else if (dice_roll >= 3 && dice_roll < 6) { // With probability of 30% return an integer in range [0, 100). return rand(100); } else if (dice_roll >= 6 && dice_roll < 9) { // With probability of 30% return an integer in range [0, 100). return rand(1000); } if (rand(10) == 0) { // With probability of 1% return 0xffffffffffffffff. return 0xffffffffffffffff; } // With probability 9% result is uniformly random. return rand.Rand(); }, // Odds of an enum being treated like a scalar are 1:1000. {1, 1000}}; // Executed when fuzzer process exits. We use this to print out useful // information about the state of the fuzzer. static void AtExit() { // Print currently opened interfaces. cerr << "Currently opened interfaces: " << endl; for (const auto &iface_desc : runner->GetOpenedIfaces()) { cerr << iface_desc.first << endl; } cerr << endl; cerr << runner->GetStats().StatsString(); } extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { params = ExtractProtoFuzzerParams(*argc, *argv); cerr << params.DebugString() << endl; random = make_unique<Random>(params.seed_); mutator = make_unique<ProtoFuzzerMutator>( *random.get(), ExtractPredefinedTypes(params.comp_specs_), mutator_config); runner = make_unique<ProtoFuzzerRunner>(params.comp_specs_); runner->Init(params.target_iface_, params.binder_mode_); // Register atexit handler after all static objects' initialization. std::atexit(AtExit); return 0; } extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t max_size, unsigned int seed) { ExecSpec exec_spec{}; // An Execution is randomly generated if: // 1. It can't be serialized from the given buffer OR // 2. The runner has opened interfaces that have not been touched. // Otherwise, the Execution is mutated. if (!FromArray(data, size, &exec_spec) || runner->UntouchedIfaces()) { exec_spec = mutator->RandomGen(runner->GetOpenedIfaces(), params.exec_size_); } else { mutator->Mutate(runner->GetOpenedIfaces(), &exec_spec); } return ToArray(data, size, &exec_spec); } // TODO(trong): implement a meaningful cross-over mechanism. size_t LLVMFuzzerCustomCrossOver(const uint8_t *data1, size_t size1, const uint8_t *data2, size_t size2, uint8_t *out, size_t max_out_size, unsigned int seed) { memcpy(out, data1, size1); return size1; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ExecSpec exec_spec{}; if (!FromArray(data, size, &exec_spec)) { cerr << "Failed to deserialize an ExecSpec." << endl; return 0; } runner->Execute(exec_spec); return 0; } } // namespace fuzzer } // namespace vts } // namespace android