| 202 | // be less than or equal to |max|. |
| 203 | template <typename T> |
| 204 | T FuzzedDataProvider::ConsumeIntegralInRange(T min, T max) { |
| 205 | static_assert(std::is_integral<T>::value, "An integral type is required."); |
| 206 | static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type."); |
| 207 | |
| 208 | if (min > max) |
| 209 | abort(); |
| 210 | |
| 211 | // Use the biggest type possible to hold the range and the result. |
| 212 | uint64_t range = static_cast<uint64_t>(max) - min; |
| 213 | uint64_t result = 0; |
| 214 | size_t offset = 0; |
| 215 | |
| 216 | while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 && |
| 217 | remaining_bytes_ != 0) { |
| 218 | // Pull bytes off the end of the seed data. Experimentally, this seems to |
| 219 | // allow the fuzzer to more easily explore the input space. This makes |
| 220 | // sense, since it works by modifying inputs that caused new code to run, |
| 221 | // and this data is often used to encode length of data read by |
| 222 | // |ConsumeBytes|. Separating out read lengths makes it easier modify the |
| 223 | // contents of the data that is actually read. |
| 224 | --remaining_bytes_; |
| 225 | result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_]; |
| 226 | offset += CHAR_BIT; |
| 227 | } |
| 228 | |
| 229 | // Avoid division by 0, in case |range + 1| results in overflow. |
| 230 | if (range != std::numeric_limits<decltype(range)>::max()) |
| 231 | result = result % (range + 1); |
| 232 | |
| 233 | return static_cast<T>(min + result); |
| 234 | } |
| 235 | |
| 236 | // Returns a floating point value in the range [Type's lowest, Type's max] by |
| 237 | // consuming bytes from the input data. If there's no input data left, always |
no outgoing calls
no test coverage detected