1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // A fuzzer that checks correctness of json parser/writer. 6 // The fuzzer input is passed through parsing twice, 7 // so that presumably valid json is parsed/written again. 8 9 #include <stddef.h> 10 #include <stdint.h> 11 12 #include <string> 13 #include <string_view> 14 15 #include "base/compiler_specific.h" 16 #include "base/containers/heap_array.h" 17 #include "base/containers/span.h" 18 #include "base/json/json_reader.h" 19 #include "base/json/json_writer.h" 20 #include "base/json/string_escape.h" 21 #include "base/logging.h" 22 #include "base/values.h" 23 24 // Entry point for libFuzzer. 25 // We will use the last byte of data as parsing options. 26 // The rest will be used as text input to the parser. LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)27extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 28 if (size < 2) 29 return 0; 30 31 // SAFETY: required from fuzzer. 32 auto all_input = UNSAFE_BUFFERS(base::span<const uint8_t>(data, size)); 33 34 // Create a copy of input buffer, as otherwise we don't catch 35 // overflow that touches the last byte (which is used in options). 36 auto input = base::HeapArray<char>::CopiedFrom( 37 base::as_chars(all_input.first(size - 1))); 38 39 std::string_view input_string = base::as_string_view(input.as_span()); 40 41 const int options = all_input[size - 1]; 42 auto result = 43 base::JSONReader::ReadAndReturnValueWithError(input_string, options); 44 if (!result.has_value()) 45 return 0; 46 47 std::string parsed_output; 48 bool b = base::JSONWriter::Write(*result, &parsed_output); 49 LOG_ASSERT(b); 50 51 auto double_result = 52 base::JSONReader::ReadAndReturnValueWithError(parsed_output, options); 53 LOG_ASSERT(double_result.has_value()); 54 std::string double_parsed_output; 55 bool b2 = base::JSONWriter::Write(*double_result, &double_parsed_output); 56 LOG_ASSERT(b2); 57 58 LOG_ASSERT(parsed_output == double_parsed_output) 59 << "Parser/Writer mismatch." 60 << "\nInput=" << base::GetQuotedJSONString(parsed_output) 61 << "\nOutput=" << base::GetQuotedJSONString(double_parsed_output); 62 63 return 0; 64 } 65