| /* |
| * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #ifndef TEST_FUZZERS_FUZZ_DATA_HELPER_H_ |
| #define TEST_FUZZERS_FUZZ_DATA_HELPER_H_ |
| |
| #include <limits> |
| |
| #include "api/array_view.h" |
| #include "modules/rtp_rtcp/source/byte_io.h" |
| |
| namespace webrtc { |
| namespace test { |
| |
| // Helper class to take care of the fuzzer input, read from it, and keep track |
| // of when the end of the data has been reached. |
| class FuzzDataHelper { |
| public: |
| explicit FuzzDataHelper(rtc::ArrayView<const uint8_t> data); |
| |
| // Returns true if n bytes can be read. |
| bool CanReadBytes(size_t n) const { return data_ix_ + n <= data_.size(); } |
| |
| // Reads and returns data of type T. |
| template <typename T> |
| T Read() { |
| RTC_CHECK(CanReadBytes(sizeof(T))); |
| T x = ByteReader<T>::ReadLittleEndian(&data_[data_ix_]); |
| data_ix_ += sizeof(T); |
| return x; |
| } |
| |
| // Reads and returns data of type T. Returns default_value if not enough |
| // fuzzer input remains to read a T. |
| template <typename T> |
| T ReadOrDefaultValue(T default_value) { |
| if (!CanReadBytes(sizeof(T))) { |
| return default_value; |
| } |
| return Read<T>(); |
| } |
| |
| // Like ReadOrDefaultValue, but replaces the value 0 with default_value. |
| template <typename T> |
| T ReadOrDefaultValueNotZero(T default_value) { |
| static_assert(std::is_integral<T>::value, ""); |
| T x = ReadOrDefaultValue(default_value); |
| return x == 0 ? default_value : x; |
| } |
| |
| // Returns one of the elements from the provided input array. The selection |
| // is based on the fuzzer input data. If not enough fuzzer data is available, |
| // the method will return the first element in the input array. The reason for |
| // not flagging this as an error is to allow the method to be called from |
| // class constructors, and in constructors we typically do not handle |
| // errors. The code will work anyway, and the fuzzer will likely see that |
| // providing more data will actually make this method return something else. |
| template <typename T, size_t N> |
| T SelectOneOf(const T (&select_from)[N]) { |
| static_assert(N <= std::numeric_limits<uint8_t>::max(), ""); |
| // Read an index between 0 and select_from.size() - 1 from the fuzzer data. |
| uint8_t index = ReadOrDefaultValue<uint8_t>(0) % N; |
| return select_from[index]; |
| } |
| |
| rtc::ArrayView<const uint8_t> ReadByteArray(size_t bytes) { |
| if (!CanReadBytes(bytes)) { |
| return rtc::ArrayView<const uint8_t>(nullptr, 0); |
| } |
| const size_t index_to_return = data_ix_; |
| data_ix_ += bytes; |
| return data_.subview(index_to_return, bytes); |
| } |
| |
| // If sizeof(T) > BytesLeft then the remaining bytes will be used and the rest |
| // of the object will be zero initialized. |
| template <typename T> |
| void CopyTo(T* object) { |
| memset(object, 0, sizeof(T)); |
| |
| size_t bytes_to_copy = std::min(BytesLeft(), sizeof(T)); |
| memcpy(object, data_.data() + data_ix_, bytes_to_copy); |
| data_ix_ += bytes_to_copy; |
| } |
| |
| size_t BytesRead() const { return data_ix_; } |
| |
| size_t BytesLeft() const { return data_.size() - data_ix_; } |
| |
| private: |
| rtc::ArrayView<const uint8_t> data_; |
| size_t data_ix_ = 0; |
| }; |
| |
| } // namespace test |
| } // namespace webrtc |
| |
| #endif // TEST_FUZZERS_FUZZ_DATA_HELPER_H_ |