Changeset View
Changeset View
Standalone View
Standalone View
src/test/fuzz/util.h
// Copyright (c) 2009-2019 The Bitcoin Core developers | // Copyright (c) 2009-2019 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#ifndef BITCOIN_TEST_FUZZ_UTIL_H | #ifndef BITCOIN_TEST_FUZZ_UTIL_H | ||||
#define BITCOIN_TEST_FUZZ_UTIL_H | #define BITCOIN_TEST_FUZZ_UTIL_H | ||||
#include <amount.h> | |||||
#include <attributes.h> | #include <attributes.h> | ||||
#include <script/script.h> | #include <script/script.h> | ||||
#include <serialize.h> | #include <serialize.h> | ||||
#include <streams.h> | #include <streams.h> | ||||
#include <test/fuzz/FuzzedDataProvider.h> | #include <test/fuzz/FuzzedDataProvider.h> | ||||
#include <test/fuzz/fuzz.h> | #include <test/fuzz/fuzz.h> | ||||
#include <version.h> | #include <version.h> | ||||
#include <cstdint> | #include <cstdint> | ||||
#include <string> | #include <string> | ||||
#include <vector> | #include <vector> | ||||
NODISCARD inline std::vector<uint8_t> | NODISCARD inline std::vector<uint8_t> | ||||
ConsumeRandomLengthByteVector(FuzzedDataProvider &fuzzed_data_provider, | ConsumeRandomLengthByteVector(FuzzedDataProvider &fuzzed_data_provider, | ||||
size_t max_length = 4096) noexcept { | size_t max_length = 4096) noexcept { | ||||
const std::string s = | const std::string s = | ||||
fuzzed_data_provider.ConsumeRandomLengthString(max_length); | fuzzed_data_provider.ConsumeRandomLengthString(max_length); | ||||
return {s.begin(), s.end()}; | return {s.begin(), s.end()}; | ||||
} | } | ||||
NODISCARD inline std::vector<std::string> | |||||
ConsumeRandomLengthStringVector(FuzzedDataProvider &fuzzed_data_provider, | |||||
size_t max_vector_size = 16, | |||||
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> | template <typename T> | ||||
NODISCARD inline std::optional<T> | NODISCARD inline std::optional<T> | ||||
ConsumeDeserializable(FuzzedDataProvider &fuzzed_data_provider, | ConsumeDeserializable(FuzzedDataProvider &fuzzed_data_provider, | ||||
size_t max_length = 4096) noexcept { | size_t max_length = 4096) noexcept { | ||||
const std::vector<uint8_t> buffer = | const std::vector<uint8_t> buffer = | ||||
ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length); | ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length); | ||||
CDataStream ds{buffer, SER_NETWORK, INIT_PROTO_VERSION}; | CDataStream ds{buffer, SER_NETWORK, INIT_PROTO_VERSION}; | ||||
T obj; | T obj; | ||||
try { | try { | ||||
ds >> obj; | ds >> obj; | ||||
} catch (const std::ios_base::failure &) { | } catch (const std::ios_base::failure &) { | ||||
return std::nullopt; | return std::nullopt; | ||||
} | } | ||||
return obj; | return obj; | ||||
} | } | ||||
NODISCARD inline opcodetype | NODISCARD inline opcodetype | ||||
ConsumeOpcodeType(FuzzedDataProvider &fuzzed_data_provider) noexcept { | ConsumeOpcodeType(FuzzedDataProvider &fuzzed_data_provider) noexcept { | ||||
return static_cast<opcodetype>( | return static_cast<opcodetype>( | ||||
fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, MAX_OPCODE)); | fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, MAX_OPCODE)); | ||||
} | } | ||||
NODISCARD inline Amount | |||||
ConsumeMoney(FuzzedDataProvider &fuzzed_data_provider) noexcept { | |||||
// FIXME find a better way to avoid duplicating the MAX_MONEY definition | |||||
int64_t maxMoneyAsInt = int64_t(21000000) * int64_t(100000000); | |||||
return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, | |||||
maxMoneyAsInt) * | |||||
SATOSHI; | |||||
} | |||||
NODISCARD inline CScript | NODISCARD inline CScript | ||||
ConsumeScript(FuzzedDataProvider &fuzzed_data_provider) noexcept { | ConsumeScript(FuzzedDataProvider &fuzzed_data_provider) noexcept { | ||||
const std::vector<uint8_t> b = | const std::vector<uint8_t> b = | ||||
ConsumeRandomLengthByteVector(fuzzed_data_provider); | ConsumeRandomLengthByteVector(fuzzed_data_provider); | ||||
return {b.begin(), b.end()}; | return {b.begin(), b.end()}; | ||||
} | } | ||||
NODISCARD inline CScriptNum | NODISCARD inline CScriptNum | ||||
ConsumeScriptNum(FuzzedDataProvider &fuzzed_data_provider) noexcept { | ConsumeScriptNum(FuzzedDataProvider &fuzzed_data_provider) noexcept { | ||||
return CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()}; | return CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()}; | ||||
} | } | ||||
template <typename T> bool MultiplicationOverflow(T i, T j) { | |||||
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; | |||||
} | |||||
} | |||||
#endif // BITCOIN_TEST_FUZZ_UTIL_H | #endif // BITCOIN_TEST_FUZZ_UTIL_H |