1 // Copyright 2018 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 #ifdef UNSAFE_BUFFERS_BUILD 6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors. 7 #pragma allow_unsafe_buffers 8 #endif 9 10 #include <fuzzer/FuzzedDataProvider.h> 11 12 #include <string_view> 13 #include <tuple> 14 15 #include "base/containers/span.h" 16 #include "base/pickle.h" 17 18 namespace { 19 constexpr int kIterations = 16; 20 constexpr int kReadControlBytes = 32; 21 constexpr int kReadDataTypes = 17; 22 constexpr int kMaxReadLength = 1024; 23 constexpr int kMaxSkipBytes = 1024; 24 } // namespace 25 LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)26extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 27 if (size < kReadControlBytes) { 28 return 0; 29 } 30 // Use the first kReadControlBytes bytes of the fuzzer input to control how 31 // the pickled data is read. 32 FuzzedDataProvider data_provider(data, kReadControlBytes); 33 data += kReadControlBytes; 34 size -= kReadControlBytes; 35 36 base::Pickle pickle = 37 base::Pickle::WithUnownedBuffer(UNSAFE_BUFFERS(base::span(data, size))); 38 base::PickleIterator iter(pickle); 39 for (int i = 0; i < kIterations; i++) { 40 uint8_t read_type = data_provider.ConsumeIntegral<uint8_t>(); 41 switch (read_type % kReadDataTypes) { 42 case 0: { 43 bool result = 0; 44 std::ignore = iter.ReadBool(&result); 45 break; 46 } 47 case 1: { 48 int result = 0; 49 std::ignore = iter.ReadInt(&result); 50 break; 51 } 52 case 2: { 53 long result = 0; 54 std::ignore = iter.ReadLong(&result); 55 break; 56 } 57 case 3: { 58 uint16_t result = 0; 59 std::ignore = iter.ReadUInt16(&result); 60 break; 61 } 62 case 4: { 63 uint32_t result = 0; 64 std::ignore = iter.ReadUInt32(&result); 65 break; 66 } 67 case 5: { 68 int64_t result = 0; 69 std::ignore = iter.ReadInt64(&result); 70 break; 71 } 72 case 6: { 73 uint64_t result = 0; 74 std::ignore = iter.ReadUInt64(&result); 75 break; 76 } 77 case 7: { 78 float result = 0; 79 std::ignore = iter.ReadFloat(&result); 80 break; 81 } 82 case 8: { 83 double result = 0; 84 std::ignore = iter.ReadDouble(&result); 85 break; 86 } 87 case 9: { 88 std::string result; 89 std::ignore = iter.ReadString(&result); 90 break; 91 } 92 case 10: { 93 std::string_view result; 94 std::ignore = iter.ReadStringPiece(&result); 95 break; 96 } 97 case 11: { 98 std::u16string result; 99 std::ignore = iter.ReadString16(&result); 100 break; 101 } 102 case 12: { 103 std::u16string_view result; 104 std::ignore = iter.ReadStringPiece16(&result); 105 break; 106 } 107 case 13: { 108 const char* data_result = nullptr; 109 size_t length_result = 0; 110 std::ignore = iter.ReadData(&data_result, &length_result); 111 break; 112 } 113 case 14: { 114 const char* data_result = nullptr; 115 int read_length = 116 data_provider.ConsumeIntegralInRange(0, kMaxReadLength); 117 std::ignore = 118 iter.ReadBytes(&data_result, static_cast<size_t>(read_length)); 119 break; 120 } 121 case 15: { 122 size_t result = 0; 123 std::ignore = iter.ReadLength(&result); 124 break; 125 } 126 case 16: { 127 std::ignore = iter.SkipBytes(static_cast<size_t>( 128 data_provider.ConsumeIntegralInRange(0, kMaxSkipBytes))); 129 break; 130 } 131 } 132 } 133 134 return 0; 135 } 136