|  | /* | 
|  | *  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_ |