1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <fuzzer/FuzzedDataProvider.h> 18 #include <algorithm> 19 /** 20 * A thread-safe interface to the FuzzedDataProvider 21 */ 22 class ThreadSafeFuzzedDataProvider : FuzzedDataProvider { 23 private: 24 std::mutex mLock; 25 26 public: ThreadSafeFuzzedDataProvider(const uint8_t * data,size_t size)27 ThreadSafeFuzzedDataProvider(const uint8_t* data, size_t size) 28 : FuzzedDataProvider(data, size) {} 29 30 template <typename T> ConsumeBytes(size_t num_bytes)31 std::vector<T> ConsumeBytes(size_t num_bytes) { 32 std::scoped_lock _l(mLock); 33 return FuzzedDataProvider::ConsumeBytes<T>(num_bytes); 34 } 35 36 template <typename T> ConsumeBytesWithTerminator(size_t num_bytes,T terminator)37 std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, T terminator) { 38 std::scoped_lock _l(mLock); 39 return FuzzedDataProvider::ConsumeBytesWithTerminator<T>(num_bytes, terminator); 40 } 41 42 template <typename T> ConsumeRemainingBytes()43 std::vector<T> ConsumeRemainingBytes() { 44 std::scoped_lock _l(mLock); 45 return FuzzedDataProvider::ConsumeRemainingBytes<T>(); 46 } 47 ConsumeBytesAsString(size_t num_bytes)48 std::string ConsumeBytesAsString(size_t num_bytes) { 49 std::scoped_lock _l(mLock); 50 return FuzzedDataProvider::ConsumeBytesAsString(num_bytes); 51 } 52 ConsumeRandomLengthString(size_t max_length)53 std::string ConsumeRandomLengthString(size_t max_length) { 54 std::scoped_lock _l(mLock); 55 return FuzzedDataProvider::ConsumeRandomLengthString(max_length); 56 } 57 ConsumeRandomLengthString()58 std::string ConsumeRandomLengthString() { 59 std::scoped_lock _l(mLock); 60 return FuzzedDataProvider::ConsumeRandomLengthString(); 61 } 62 63 // Converting the string to a UTF-8 string by setting the prefix bits of each 64 // byte according to UTF-8 encoding rules. ConsumeRandomLengthUtf8String(size_t max_length)65 std::string ConsumeRandomLengthUtf8String(size_t max_length) { 66 std::scoped_lock _l(mLock); 67 std::string result = FuzzedDataProvider::ConsumeRandomLengthString(max_length); 68 size_t remaining_bytes = result.length(), idx = 0; 69 while (remaining_bytes > 0) { 70 size_t random_byte_size = FuzzedDataProvider::ConsumeIntegralInRange(1, 4); 71 size_t byte_size = std::min(random_byte_size, remaining_bytes); 72 switch (byte_size) { 73 // Prefix byte: 0xxxxxxx 74 case 1: 75 result[idx++] &= 0b01111111; 76 break; 77 // Prefix bytes: 110xxxxx 10xxxxxx 78 case 2: 79 result[idx++] = (result[idx] & 0b00011111) | 0b11000000; 80 result[idx++] = (result[idx] & 0b00111111) | 0b10000000; 81 break; 82 // Prefix bytes: 1110xxxx 10xxxxxx 10xxxxxx 83 case 3: 84 result[idx++] = (result[idx] & 0b00001111) | 0b11100000; 85 result[idx++] = (result[idx] & 0b00111111) | 0b10000000; 86 result[idx++] = (result[idx] & 0b00111111) | 0b10000000; 87 break; 88 // Prefix bytes: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 89 case 4: 90 result[idx++] = (result[idx] & 0b00000111) | 0b11110000; 91 result[idx++] = (result[idx] & 0b00111111) | 0b10000000; 92 result[idx++] = (result[idx] & 0b00111111) | 0b10000000; 93 result[idx++] = (result[idx] & 0b00111111) | 0b10000000; 94 break; 95 } 96 remaining_bytes -= byte_size; 97 } 98 return result; 99 } 100 ConsumeRemainingBytesAsString()101 std::string ConsumeRemainingBytesAsString() { 102 std::scoped_lock _l(mLock); 103 return FuzzedDataProvider::ConsumeRemainingBytesAsString(); 104 } 105 106 template <typename T> ConsumeIntegral()107 T ConsumeIntegral() { 108 std::scoped_lock _l(mLock); 109 return FuzzedDataProvider::ConsumeIntegral<T>(); 110 } 111 112 template <typename T> ConsumeIntegralInRange(T min,T max)113 T ConsumeIntegralInRange(T min, T max) { 114 std::scoped_lock _l(mLock); 115 return FuzzedDataProvider::ConsumeIntegralInRange<T>(min, max); 116 } 117 118 template <typename T> ConsumeFloatingPoint()119 T ConsumeFloatingPoint() { 120 std::scoped_lock _l(mLock); 121 return FuzzedDataProvider::ConsumeFloatingPoint<T>(); 122 } 123 124 template <typename T> ConsumeFloatingPointInRange(T min,T max)125 T ConsumeFloatingPointInRange(T min, T max) { 126 std::scoped_lock _l(mLock); 127 return FuzzedDataProvider::ConsumeFloatingPointInRange<T>(min, max); 128 } 129 130 template <typename T> ConsumeProbability()131 T ConsumeProbability() { 132 std::scoped_lock _l(mLock); 133 return FuzzedDataProvider::ConsumeProbability<T>(); 134 } 135 ConsumeBool()136 bool ConsumeBool() { 137 std::scoped_lock _l(mLock); 138 return FuzzedDataProvider::ConsumeBool(); 139 } 140 141 template <typename T> ConsumeEnum()142 T ConsumeEnum() { 143 std::scoped_lock _l(mLock); 144 return FuzzedDataProvider::ConsumeEnum<T>(); 145 } 146 147 template <typename T, size_t size> PickValueInArray(const T (& array)[size])148 T PickValueInArray(const T (&array)[size]) { 149 std::scoped_lock _l(mLock); 150 return FuzzedDataProvider::PickValueInArray(array); 151 } 152 153 template <typename T, size_t size> PickValueInArray(const std::array<T,size> & array)154 T PickValueInArray(const std::array<T, size>& array) { 155 std::scoped_lock _l(mLock); 156 return FuzzedDataProvider::PickValueInArray(array); 157 } 158 159 template <typename T> PickValueInArray(std::initializer_list<const T> list)160 T PickValueInArray(std::initializer_list<const T> list) { 161 std::scoped_lock _l(mLock); 162 return FuzzedDataProvider::PickValueInArray(list); 163 } 164 ConsumeData(void * destination,size_t num_bytes)165 size_t ConsumeData(void* destination, size_t num_bytes) { 166 std::scoped_lock _l(mLock); 167 return FuzzedDataProvider::ConsumeData(destination, num_bytes); 168 } 169 remaining_bytes()170 size_t remaining_bytes() { 171 std::scoped_lock _l(mLock); 172 return FuzzedDataProvider::remaining_bytes(); 173 } 174 }; 175