No description provided.
fuzz: Check banman roundtrip #22322
pull MarcoFalke wants to merge 1 commits into bitcoin:master from MarcoFalke:2106-fuzzBanman changing 1 files +20 −2-
MarcoFalke commented at 10:50 AM on June 23, 2021: member
- MarcoFalke requested review from vasild on Jun 23, 2021
- MarcoFalke requested review from practicalswift on Jun 23, 2021
- fanquake added the label Tests on Jun 23, 2021
-
jonatack commented at 11:00 AM on June 23, 2021: member
Concept ACK, good idea.
-
in src/test/fuzz/banman.cpp:113 in fabadb7702 outdated
108 | + auto it2{banmap_read.begin()}; 109 | + for (; it1 != banmap.end(); ++it1, ++it2) { 110 | + assert(it1->first == it2->first); 111 | + assert(it1->second.ToJson().write() == it2->second.ToJson().write()); 112 | + } 113 | + }
jonatack commented at 1:21 PM on June 23, 2021:proposed docs if you like
- BanMan ban_man{banlist_file, nullptr, offset}; + BanMan ban_man{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ offset}; while (--limit_max_ops >= 0 && fuzzed_data_provider.ConsumeBool()) { CallOneOf( fuzzed_data_provider, @@ -100,15 +100,15 @@ FUZZ_TARGET_INIT(banman, initialize_banman) SetMockTime(ConsumeTime(fuzzed_data_provider)); banmap_t banmap; ban_man.GetBanned(banmap); - BanMan ban_man_read{banlist_file, nullptr, offset}; + BanMan ban_man_read{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ offset}; banmap_t banmap_read; ban_man_read.GetBanned(banmap_read); assert(banmap.size() == banmap_read.size()); auto it1{banmap.begin()}; auto it2{banmap_read.begin()}; for (; it1 != banmap.end(); ++it1, ++it2) { - assert(it1->first == it2->first); - assert(it1->second.ToJson().write() == it2->second.ToJson().write()); + assert(it1->first == it2->first); // CSubNet + assert(it1->second.ToJson().write() == it2->second.ToJson().write()); // CBanEntry } } }
MarcoFalke commented at 10:04 AM on June 24, 2021:Thanks, added comments
jonatack commented at 1:22 PM on June 23, 2021: membertACK fabadb7702a9cbe477e9e5f91706620456154903
practicalswift approvedpracticalswift commented at 2:41 PM on June 23, 2021: contributorcr ACK fabadb7702a9cbe477e9e5f91706620456154903
Great work!
in src/test/fuzz/banman.cpp:59 in fabadb7702 outdated
56 | } 57 | } 58 | 59 | { 60 | - BanMan ban_man{banlist_file, nullptr, ConsumeBanTimeOffset(fuzzed_data_provider)}; 61 | + const auto offset{ConsumeBanTimeOffset(fuzzed_data_provider)};
vasild commented at 3:41 PM on June 23, 2021:Unrelated to this PR, why is this called "offset"? It is actually "ban_time" - number of seconds to keep the ban entry after the misbehavior occurred.
There is some "offset" involved inBanMan::Ban(), but that is completely internal toBanMan.
MarcoFalke commented at 10:04 AM on June 24, 2021:Removed
offsetin src/test/fuzz/banman.cpp:111 in fabadb7702 outdated
100 | + SetMockTime(ConsumeTime(fuzzed_data_provider)); 101 | + banmap_t banmap; 102 | + ban_man.GetBanned(banmap); 103 | + BanMan ban_man_read{banlist_file, nullptr, offset}; 104 | + banmap_t banmap_read; 105 | + ban_man_read.GetBanned(banmap_read);
vasild commented at 3:49 PM on June 23, 2021:The dumped data may end up containing more entries than
banmapandbanmap_readbecauseSweepBanned()may leave them when called fromDumpBanlist()but when called fromGetBanned()afterSetMockTime()it may remove "expired" entries.It is ok since both
banmapandbanmap_readwill contain the same, but if somebody ends up debugging this and looking at the file, then it may be confusing. Maybe swap lines 99 and 100.
MarcoFalke commented at 4:42 PM on June 23, 2021:This was done on purpose to check
SweepBannedis called on read
vasild commented at 7:53 AM on June 24, 2021:Hmm, then maybe add one entry that will certainly expire? This will also make the intention more explicit:
diff --git i/src/test/fuzz/banman.cpp w/src/test/fuzz/banman.cpp index 6aa95b484f..b3b10da084 100644 --- i/src/test/fuzz/banman.cpp +++ w/src/test/fuzz/banman.cpp @@ -93,16 +93,23 @@ FUZZ_TARGET_INIT(banman, initialize_banman) }, [&] { ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider)); }); } if (!force_read_and_write_to_err) { + const auto mock_time = ConsumeTime(fuzzed_data_provider); + SetMockTime(mock_time); + // Add one ban entry that will expire to check that on read expired entries are removed. + ban_man.Ban(ConsumeNetAddr(fuzzed_data_provider), mock_time + 5, true); ban_man.DumpBanlist(); - SetMockTime(ConsumeTime(fuzzed_data_provider)); + banmap_t banmap_unexpired; + ban_man.GetBanned(banmap_unexpired); + SetMockTime(mock_time + 10); banmap_t banmap; ban_man.GetBanned(banmap); + assert(banmap.size() < banmap_unexpired.size()); // At least one should have expired. BanMan ban_man_read{banlist_file, nullptr, offset}; banmap_t banmap_read; ban_man_read.GetBanned(banmap_read); assert(banmap.size() == banmap_read.size()); auto it1{banmap.begin()}; auto it2{banmap_read.begin()};in src/test/fuzz/banman.cpp:109 in fabadb7702 outdated
104 | + banmap_t banmap_read; 105 | + ban_man_read.GetBanned(banmap_read); 106 | + assert(banmap.size() == banmap_read.size()); 107 | + auto it1{banmap.begin()}; 108 | + auto it2{banmap_read.begin()}; 109 | + for (; it1 != banmap.end(); ++it1, ++it2) {
vasild commented at 3:57 PM on June 23, 2021:This may brick if
banmap_tis changed fromstd::maptostd::unordered_map. It should be changed because the latter is faster and we don't need an order into this container.Maybe add something like
static_assert(std::is_base_of<std::map, banmap_t>::value)to ensure this gets adjusted ifbanmap_tis changed in the future?Or a slower, but more robust variant: for each entry in
banmapensure that it can be found inbanmap_readand that both maps have the same size.
vasild commented at 8:03 AM on June 24, 2021:assert(banmap.size() == banmap_read.size()); - auto it1{banmap.begin()}; - auto it2{banmap_read.begin()}; - for (; it1 != banmap.end(); ++it1, ++it2) { - assert(it1->first == it2->first); - assert(it1->second.ToJson().write() == it2->second.ToJson().write()); + for (const auto& [subnet, ban_entry] : banmap) { + const auto it = banmap_read.find(subnet); + assert(it != banmap_read.end()); + assert(it->second.ToJson().write() == ban_entry.ToJson().write()); }
vasild commented at 8:18 AM on June 24, 2021:Or even better:
diff --git i/src/test/fuzz/banman.cpp w/src/test/fuzz/banman.cpp index 6aa95b484f..15ccd9df3c 100644 --- i/src/test/fuzz/banman.cpp +++ w/src/test/fuzz/banman.cpp @@ -29,12 +29,18 @@ int64_t ConsumeBanTimeOffset(FuzzedDataProvider& fuzzed_data_provider) noexcept void initialize_banman() { static const auto testing_setup = MakeNoLogFileContext<>(); } +static bool operator==(const CBanEntry& lhs, const CBanEntry& rhs) +{ + return lhs.nVersion == rhs.nVersion && lhs.nCreateTime == rhs.nCreateTime && + lhs.nBanUntil == rhs.nBanUntil; +} + FUZZ_TARGET_INIT(banman, initialize_banman) { // The complexity is O(N^2), where N is the input size, because each call // might call DumpBanlist (or other methods that are at least linear // complexity of the input size). int limit_max_ops{300}; @@ -100,18 +106,12 @@ FUZZ_TARGET_INIT(banman, initialize_banman) SetMockTime(ConsumeTime(fuzzed_data_provider)); banmap_t banmap; ban_man.GetBanned(banmap); BanMan ban_man_read{banlist_file, nullptr, offset}; banmap_t banmap_read; ban_man_read.GetBanned(banmap_read); - assert(banmap.size() == banmap_read.size()); - auto it1{banmap.begin()}; - auto it2{banmap_read.begin()}; - for (; it1 != banmap.end(); ++it1, ++it2) { - assert(it1->first == it2->first); - assert(it1->second.ToJson().write() == it2->second.ToJson().write()); - } + assert(banmap_read == banmap); } } fs::remove(banlist_file.string() + ".dat"); fs::remove(banlist_file.string() + ".json"); }
MarcoFalke commented at 10:04 AM on June 24, 2021:Made it a compile failure to change the type without touching this file
vasild commented at 10:32 AM on June 24, 2021:This is now addressed in another way. Just out of curiosity - why not the
assert(banmap_read == banmap);variant? It is shorter and works for bothmapandunordered_map.in src/test/fuzz/banman.cpp:103 in fabadb7702 outdated
94 | @@ -93,6 +95,22 @@ FUZZ_TARGET_INIT(banman, initialize_banman) 95 | ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider)); 96 | }); 97 | } 98 | + if (!force_read_and_write_to_err) { 99 | + ban_man.DumpBanlist(); 100 | + SetMockTime(ConsumeTime(fuzzed_data_provider)); 101 | + banmap_t banmap; 102 | + ban_man.GetBanned(banmap); 103 | + BanMan ban_man_read{banlist_file, nullptr, offset};
vasild commented at 7:28 AM on June 24, 2021:The 3rd argument
offsetis only used byBanMan::Ban()which we never call onban_man_read. So this can beBanMan ban_man_read{banlist_file, nullptr, 0};and then the
offsetvariable is not necessary.
MarcoFalke commented at 10:04 AM on June 24, 2021:Thanks, done
MarcoFalke force-pushed on Jun 24, 2021MarcoFalke commented at 10:05 AM on June 24, 2021: memberAddressed feedback
vasild approvedvasild commented at 10:29 AM on June 24, 2021: memberACK fa57878340e6e9e34b01e26091d9d57f1c26f771
jonatack commented at 1:42 PM on June 24, 2021: memberThanks for updating.
Tested ACK fa57878340e6e9e34b01e26091d9d57f1c26f771
fuzz: Check banman roundtrip fa485d06ecMarcoFalke force-pushed on Jun 24, 2021vasild approvedvasild commented at 5:41 AM on June 25, 2021: memberACK fa485d06ec10acd9a791f8d29689e1e82591fb70
practicalswift commented at 6:14 AM on June 25, 2021: contributorcr ACK fa485d06ec10acd9a791f8d29689e1e82591fb70
MarcoFalke merged this on Jun 25, 2021MarcoFalke closed this on Jun 25, 2021MarcoFalke deleted the branch on Jun 25, 2021sidhujag referenced this in commit 68ec9eae51 on Jun 25, 2021in src/test/fuzz/banman.cpp:112 in fa485d06ec
107 | + banmap_t banmap; 108 | + ban_man.GetBanned(banmap); 109 | + BanMan ban_man_read{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ 0}; 110 | + banmap_t banmap_read; 111 | + ban_man_read.GetBanned(banmap_read); 112 | + assert(banmap == banmap_read);
hebasto commented at 1:48 PM on August 6, 2021:Errors in CI job (https://cirrus-ci.com/task/6055643191705600?logs=ci#L2769):
fuzz: test/fuzz/banman.cpp:112: void banman_fuzz_target(FuzzBufferType): Assertion `banmap == banmap_read' failed.
vasild commented at 2:28 PM on August 6, 2021:Is there a way to retrieve
./crash-0671aac15e619e99522e2119487eaa9cc97e5a34from the CI machine or make the fuzzer print it in base64?Latest
master(d67330d11245b11fbdd5e2dd5343ee451186931e) has been changed to:gwillen referenced this in commit 9a6ea2c704 on Jun 1, 2022DrahtBot locked this on Aug 16, 2022ContributorsLabels
github-metadata-mirror
This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-15 00:14 UTC
This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me