0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-02 09:46:52 -05:00

Add roundtrip fuzz tests for CAddress serialization

This commit is contained in:
Pieter Wuille 2020-11-26 18:13:42 -08:00
parent e2f0548b52
commit f8866e8c32
2 changed files with 43 additions and 8 deletions

View file

@ -449,6 +449,13 @@ public:
uint32_t nTime{TIME_INIT}; uint32_t nTime{TIME_INIT};
//! Serialized as uint64_t in V1, and as CompactSize in V2. //! Serialized as uint64_t in V1, and as CompactSize in V2.
ServiceFlags nServices{NODE_NONE}; ServiceFlags nServices{NODE_NONE};
friend bool operator==(const CAddress& a, const CAddress& b)
{
return a.nTime == b.nTime &&
a.nServices == b.nServices &&
static_cast<const CService&>(a) == static_cast<const CService&>(b);
}
}; };
/** getdata message type flags */ /** getdata message type flags */

View file

@ -53,9 +53,9 @@ struct invalid_fuzzing_input_exception : public std::exception {
}; };
template <typename T> template <typename T>
CDataStream Serialize(const T& obj, const int version = INIT_PROTO_VERSION) CDataStream Serialize(const T& obj, const int version = INIT_PROTO_VERSION, const int ser_type = SER_NETWORK)
{ {
CDataStream ds(SER_NETWORK, version); CDataStream ds(ser_type, version);
ds << obj; ds << obj;
return ds; return ds;
} }
@ -69,9 +69,9 @@ T Deserialize(CDataStream ds)
} }
template <typename T> template <typename T>
void DeserializeFromFuzzingInput(FuzzBufferType buffer, T& obj, const std::optional<int> protocol_version = std::nullopt) void DeserializeFromFuzzingInput(FuzzBufferType buffer, T& obj, const std::optional<int> protocol_version = std::nullopt, const int ser_type = SER_NETWORK)
{ {
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); CDataStream ds(buffer, ser_type, INIT_PROTO_VERSION);
if (protocol_version) { if (protocol_version) {
ds.SetVersion(*protocol_version); ds.SetVersion(*protocol_version);
} else { } else {
@ -92,9 +92,9 @@ void DeserializeFromFuzzingInput(FuzzBufferType buffer, T& obj, const std::optio
} }
template <typename T> template <typename T>
void AssertEqualAfterSerializeDeserialize(const T& obj, const int version = INIT_PROTO_VERSION) void AssertEqualAfterSerializeDeserialize(const T& obj, const int version = INIT_PROTO_VERSION, const int ser_type = SER_NETWORK)
{ {
assert(Deserialize<T>(Serialize(obj, version)) == obj); assert(Deserialize<T>(Serialize(obj, version, ser_type)) == obj);
} }
} // namespace } // namespace
@ -251,9 +251,37 @@ FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, {
DeserializeFromFuzzingInput(buffer, mh); DeserializeFromFuzzingInput(buffer, mh);
(void)mh.IsCommandValid(); (void)mh.IsCommandValid();
}) })
FUZZ_TARGET_DESERIALIZE(address_deserialize, { FUZZ_TARGET_DESERIALIZE(address_deserialize_v1_notime, {
CAddress a; CAddress a;
DeserializeFromFuzzingInput(buffer, a); DeserializeFromFuzzingInput(buffer, a, INIT_PROTO_VERSION);
// A CAddress without nTime (as is expected under INIT_PROTO_VERSION) will roundtrip
// in all 5 formats (with/without nTime, v1/v2, network/disk)
AssertEqualAfterSerializeDeserialize(a, INIT_PROTO_VERSION);
AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION);
AssertEqualAfterSerializeDeserialize(a, 0, SER_DISK);
AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION | ADDRV2_FORMAT);
AssertEqualAfterSerializeDeserialize(a, ADDRV2_FORMAT, SER_DISK);
})
FUZZ_TARGET_DESERIALIZE(address_deserialize_v1_withtime, {
CAddress a;
DeserializeFromFuzzingInput(buffer, a, PROTOCOL_VERSION);
// A CAddress in V1 mode will roundtrip in all 4 formats that have nTime.
AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION);
AssertEqualAfterSerializeDeserialize(a, 0, SER_DISK);
AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION | ADDRV2_FORMAT);
AssertEqualAfterSerializeDeserialize(a, ADDRV2_FORMAT, SER_DISK);
})
FUZZ_TARGET_DESERIALIZE(address_deserialize_v2, {
CAddress a;
DeserializeFromFuzzingInput(buffer, a, PROTOCOL_VERSION | ADDRV2_FORMAT);
// A CAddress in V2 mode will roundtrip in both V2 formats, and also in the V1 formats
// with time if it's V1 compatible.
if (a.IsAddrV1Compatible()) {
AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION);
AssertEqualAfterSerializeDeserialize(a, 0, SER_DISK);
}
AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION | ADDRV2_FORMAT);
AssertEqualAfterSerializeDeserialize(a, ADDRV2_FORMAT, SER_DISK);
}) })
FUZZ_TARGET_DESERIALIZE(inv_deserialize, { FUZZ_TARGET_DESERIALIZE(inv_deserialize, {
CInv i; CInv i;