/* * 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 "specification_parser/InterfaceSpecificationParser.h" #include "test/vts/proto/ComponentSpecificationMessage.pb.h" #include <unistd.h> #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 Random random{static_cast<uint64_t>(time(0))}; // Parameters that passed in to fuzzer. static ProtoFuzzerParams params; // CompSpec corresponding to the interface targeted by // fuzzer. static CompSpec target_comp_spec; // VTS hal driver used to call functions of targeted interface. static unique_ptr<FuzzerBase> hal; // Used to mutate inputs to hal driver. static unique_ptr<ProtoFuzzerMutator> mutator; 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}}; extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { params = ExtractProtoFuzzerParams(*argc, *argv); target_comp_spec = FindTargetCompSpec(params.comp_specs_, params.target_iface_); mutator = make_unique<ProtoFuzzerMutator>( random, ExtractPredefinedTypes(params.comp_specs_), mutator_config); hal.reset( InitHalDriver(target_comp_spec, params.service_name_, params.get_stub_)); return 0; } extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t max_size, unsigned int seed) { ExecSpec exec_spec; if (!exec_spec.ParseFromArray(data, size)) { exec_spec = mutator->RandomGen(target_comp_spec.interface(), params.exec_size_); } else { mutator->Mutate(target_comp_spec.interface(), &exec_spec); } cout << exec_spec.DebugString() << endl; exec_spec.SerializeToArray(data, exec_spec.ByteSize()); return exec_spec.ByteSize(); } // 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 (!exec_spec.ParseFromArray(data, size) || exec_spec.api_size() == 0) { return 0; } Execute(hal.get(), exec_spec); return 0; } } // namespace fuzzer } // namespace vts } // namespace android