| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
- // Exceptions. See /LICENSE for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- #include <cstdint>
- #include <cstring>
- #include <numeric>
- #include <string>
- #include "driver/driver.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/Support/raw_ostream.h"
- namespace Carbon {
- static auto Read(const unsigned char*& data, size_t& size, int& output)
- -> bool {
- if (size < sizeof(output)) {
- return false;
- }
- std::memcpy(&output, data, sizeof(output));
- size -= sizeof(output);
- data += sizeof(output);
- return true;
- }
- extern "C" auto LLVMFuzzerTestOneInput(const unsigned char* data, size_t size)
- -> int {
- // First use the data to compute the number of arguments. Note that for
- // scaling reasons we don't allow 2^31 arguments, even empty ones. Simply
- // creating the vector of those won't work. We limit this to 2^20 arguments
- // total.
- int num_args;
- if (!Read(data, size, num_args) || num_args < 0 || num_args > (1 << 20)) {
- return 0;
- }
- // Now use the data to compute the length of each argument. We don't want to
- // exhaust all memory, so bound the search space to using 2^17 bytes of
- // memory for the argument text itself.
- size_t arg_length_sum = 0;
- llvm::SmallVector<int, 16> arg_lengths(num_args);
- for (int& arg_length : arg_lengths) {
- if (!Read(data, size, arg_length) || arg_length < 0) {
- return 0;
- }
- arg_length_sum += arg_length;
- if (arg_length_sum > (1 << 17)) {
- return 0;
- }
- }
- // Ensure we have enough data for all the arguments.
- if (size < arg_length_sum) {
- return 0;
- }
- // Lastly, read the contents of each argument out of the data.
- llvm::SmallVector<llvm::StringRef, 16> args;
- args.reserve(num_args);
- for (int arg_length : arg_lengths) {
- args.push_back(
- llvm::StringRef(reinterpret_cast<const char*>(data), arg_length));
- data += arg_length;
- size -= arg_length;
- }
- std::string error_text;
- llvm::raw_string_ostream error_stream(error_text);
- llvm::raw_null_ostream output_stream;
- Driver d(output_stream, error_stream);
- if (!d.RunFullCommand(args)) {
- error_stream.flush();
- if (error_text.find("ERROR:") == std::string::npos) {
- llvm::errs() << "No error message on a failure!\n";
- return 1;
- }
- }
- return 0;
- }
- } // namespace Carbon
|