diff options
Diffstat (limited to 'src/test/fuzz/util.h')
-rw-r--r-- | src/test/fuzz/util.h | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h new file mode 100644 index 0000000000..ba4b012f95 --- /dev/null +++ b/src/test/fuzz/util.h @@ -0,0 +1,134 @@ +// Copyright (c) 2009-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_TEST_FUZZ_UTIL_H +#define BITCOIN_TEST_FUZZ_UTIL_H + +#include <amount.h> +#include <arith_uint256.h> +#include <attributes.h> +#include <optional.h> +#include <script/script.h> +#include <serialize.h> +#include <streams.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <uint256.h> +#include <version.h> + +#include <cstdint> +#include <string> +#include <vector> + +NODISCARD inline std::vector<uint8_t> ConsumeRandomLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept +{ + const std::string s = fuzzed_data_provider.ConsumeRandomLengthString(max_length); + return {s.begin(), s.end()}; +} + +NODISCARD inline std::vector<std::string> ConsumeRandomLengthStringVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16, const size_t max_string_length = 16) noexcept +{ + const size_t n_elements = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size); + std::vector<std::string> r; + for (size_t i = 0; i < n_elements; ++i) { + r.push_back(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length)); + } + return r; +} + +template <typename T> +NODISCARD inline std::vector<T> ConsumeRandomLengthIntegralVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16) noexcept +{ + const size_t n_elements = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size); + std::vector<T> r; + for (size_t i = 0; i < n_elements; ++i) { + r.push_back(fuzzed_data_provider.ConsumeIntegral<T>()); + } + return r; +} + +template <typename T> +NODISCARD inline Optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept +{ + const std::vector<uint8_t> buffer = ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length); + CDataStream ds{buffer, SER_NETWORK, INIT_PROTO_VERSION}; + T obj; + try { + ds >> obj; + } catch (const std::ios_base::failure&) { + return nullopt; + } + return obj; +} + +NODISCARD inline opcodetype ConsumeOpcodeType(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return static_cast<opcodetype>(fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, MAX_OPCODE)); +} + +NODISCARD inline CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(0, MAX_MONEY); +} + +NODISCARD inline CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider); + return {b.begin(), b.end()}; +} + +NODISCARD inline CScriptNum ConsumeScriptNum(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()}; +} + +NODISCARD inline uint256 ConsumeUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + const std::vector<unsigned char> v256 = fuzzed_data_provider.ConsumeBytes<unsigned char>(sizeof(uint256)); + if (v256.size() != sizeof(uint256)) { + return {}; + } + return uint256{v256}; +} + +NODISCARD inline arith_uint256 ConsumeArithUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return UintToArith256(ConsumeUInt256(fuzzed_data_provider)); +} + +template <typename T> +NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept +{ + static_assert(std::is_integral<T>::value, "Integral required."); + if (std::numeric_limits<T>::is_signed) { + if (i > 0) { + if (j > 0) { + return i > (std::numeric_limits<T>::max() / j); + } else { + return j < (std::numeric_limits<T>::min() / i); + } + } else { + if (j > 0) { + return i < (std::numeric_limits<T>::min() / j); + } else { + return i != 0 && (j < (std::numeric_limits<T>::max() / i)); + } + } + } else { + return j != 0 && i > std::numeric_limits<T>::max() / j; + } +} + +template <class T> +NODISCARD bool AdditionOverflow(const T i, const T j) noexcept +{ + static_assert(std::is_integral<T>::value, "Integral required."); + if (std::numeric_limits<T>::is_signed) { + return (i > 0 && j > std::numeric_limits<T>::max() - i) || + (i < 0 && j < std::numeric_limits<T>::min() - i); + } + return std::numeric_limits<T>::max() - i < j; +} + +#endif // BITCOIN_TEST_FUZZ_UTIL_H |