diff options
Diffstat (limited to 'third_party/libwebrtc/test/fuzzers/fuzz_data_helper.h')
-rw-r--r-- | third_party/libwebrtc/test/fuzzers/fuzz_data_helper.h | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/third_party/libwebrtc/test/fuzzers/fuzz_data_helper.h b/third_party/libwebrtc/test/fuzzers/fuzz_data_helper.h new file mode 100644 index 0000000000..cedc31d0a4 --- /dev/null +++ b/third_party/libwebrtc/test/fuzzers/fuzz_data_helper.h @@ -0,0 +1,105 @@ +/* + * 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_ |