fabed982ad9143cddaca8346f6b4c243dd84e0c4 re-enabled the assert assert(banmap == banmap_read)
in banman
:
0ban_man.DumpBanlist();
1SetMockTime(ConsumeTime(fuzzed_data_provider));
2banmap_t banmap;
3ban_man.GetBanned(banmap);
4BanMan ban_man_read{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ 0};
5banmap_t banmap_read;
6ban_man_read.GetBanned(banmap_read);
7assert(banmap == banmap_read);
However, my server crashed because of it. Debugging it I could realize the problem is the function LookupSubnet
.
During the execution that caused the crash, the banman has been filled with the following subnets:
02e:6f6e:696f:6ef3:a080:b18d:5d5d:5d00%2038004089/121
1191:b491:7979:7979:7979:7979:79ff:ff80%2037980897/121
2207:fc26:b9ce:7aae:798b:5f2d:1d39:4380%2038004089/121
3676:c962:7962:b787:b392:fed8:7058:c500%2038004089/121
4...
After dumping it (DumpBanlist
), we initialize a BanMan
reading same file:
0BanMan ban_man_read{banlist_file, /* client_interface */ nullptr, /* default_ban_time */ 0};
1banmap_t banmap_read;
2ban_man_read.GetBanned(banmap_read);
However, when we initialize a BanMan
it will - at some point - call BanMapFromJson
.
Taking a look at BanMapFromJson
, I noticed we have:
0if (!LookupSubNet(subnet_str, subnet)) {
1 LogPrintf("Dropping entry with unparseable address or subnet (%s) from ban list\n", subnet_str);
2 continue;
3}
Calling LookupSubNet
, for example, with 2e:6f6e:696f:6ef3:a080:b18d:5d5d:5d00%2038004089/121
, will return true, but the subnet will be 2e:6f6e:696f:6ef3:a080:b18d:5d5d:5d00%31097
making the assertion assert(banmap == banmap_read)
to fail.
Got this with macOS Ventura 13.0.
0./configure --enable-fuzz --with-sanitizers=fuzzer,address,undefined --disable-asm CC=$(brew --prefix llvm)/bin/clang CXX=$(brew --prefix llvm)/bin/clang++
Crash:
0INFO: Running with entropic power schedule (0xFF, 100).
1INFO: Seed: 3851287319
2INFO: Loaded 1 modules (1130675 inline 8-bit counters): 1130675 [0x107b6cd60, 0x107c80e13),
3INFO: Loaded 1 PC tables (1130675 PCs): 1130675 [0x107c80e18,0x108dc1948),
4src/test/fuzz/fuzz: Running 1 inputs 1 time(s) each.
5Running: crash-cc17009262908f232f471481d1ad808e2bf6dc14
6Assertion failed: (banmap == banmap_read), function banman_fuzz_target, file banman.cpp, line 112.
7==79739== ERROR: libFuzzer: deadly signal
8 [#0](/bitcoin-bitcoin/0/) 0x10a453ea4 in __sanitizer_print_stack_trace+0x28 (libclang_rt.asan_osx_dynamic.dylib:arm64+0x5bea4) (BuildId: 5c04277be4ee3a049b85963fe58ab4e132000000200000000100000000000b00)
9 [#1](/bitcoin-bitcoin/1/) 0x1070bf970 in fuzzer::PrintStackTrace() FuzzerUtil.cpp:210
10 [#2](/bitcoin-bitcoin/2/) 0x1070a3d8c in fuzzer::Fuzzer::CrashCallback() FuzzerLoop.cpp:233
11 [#3](/bitcoin-bitcoin/3/) 0x18065c2a0 in _sigtramp+0x34 (libsystem_platform.dylib:arm64+0x42a0) (BuildId: 781896702f47332c9a59a210157aa97b32000000200000000100000000000d00)
12 [#4](/bitcoin-bitcoin/4/) 0xfa7f80018062dce8 (<unknown module>)
13 [#5](/bitcoin-bitcoin/5/) 0x51270001805672c4 (<unknown module>)
14 [#6](/bitcoin-bitcoin/6/) 0x614a00018056661c (<unknown module>)
15 [#7](/bitcoin-bitcoin/7/) 0x382f000104c37c88 (<unknown module>)
16 [#8](/bitcoin-bitcoin/8/) 0x1052468f8 in LLVMFuzzerTestOneInput fuzz.cpp:169
17 [#9](/bitcoin-bitcoin/9/) 0x1070a51c8 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) FuzzerLoop.cpp:617
18 [#10](/bitcoin-bitcoin/10/) 0x107091590 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) FuzzerDriver.cpp:324
19 [#11](/bitcoin-bitcoin/11/) 0x1070967c4 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) FuzzerDriver.cpp:860
20 [#12](/bitcoin-bitcoin/12/) 0x1070c0bc0 in main FuzzerMain.cpp:20
21 [#13](/bitcoin-bitcoin/13/) 0x180303e4c (<unknown module>)
22 [#14](/bitcoin-bitcoin/14/) 0x7d03fffffffffffc (<unknown module>)
23
24NOTE: libFuzzer has rudimentary signal handlers.
25 Combine libFuzzer with AddressSanitizer or similar for better crash reports.
26SUMMARY: libFuzzer: deadly signal
Seed:
0X3J1bmViYX39GgAAAAAAAAD///8AACsAXAAAAFx00UUXXXQBFRUVFRUVFRUVFRVvLwB/AAAAgAABAAABAQcAAACRtJGdEZGRQAAAAMQgf38AQAqRkf/w/6cCAZG0kXl5eXl5eXl5ef//////////eXl5eXl5eXl5eXl5eXl5jMCDHsFtvdtVxH7U1agiqUM6FTiq9Tg1OfCMddTHrRhzOQ0wCFHRVS3D7kqAmf4ii4FzNYkn9XcN8ubYNitv6cgN9E1kKPbQJOCC2dYrPDwDDQHZQeqOD7K+uD8GdslieWK3h7OS/thwWMUdw+KmgryaSZvunotnNKkz/uq98HjtQrUH/LUmUeb7pTZHqTApZ3jXVmGS2Muo96HLI9g3d0EG5LHce+mRSy2jB6TFuBRAQpwjghLRiU+S75ltwhrmRUXBfa4kpmjq2FrBYiVbbTYisifxMsnvPS7ix+IwpTats2ewEGQITg/MeZbhvKcZxxczHeb6ht1PrRV4/o/msCwN2d8RVC0DYh2gqj1aC06cGMXgoZw+T3ll5CH8dghESnW98W3i283GUy/3tSwPV8GLot5X/DupHLge/RQxtmgnIJhXgq/UMzTL7XK9y1oMooLSPiDhJiVmrKE95f549o1H9UZXSx1mwGCqap51HHrCSsnjiP13Wn1+WtyEUUAObNBDhcSjuHMMWY95B938zoOKTbFpyY3gzAi5Z8ujR2KmnEaKT4MKAVGQAAAAAAAAAAAAAAAAAAAAAP5W0ABJaWjFneFMmuY9koAoGVtScppmwwOw9++Ufx0dTyvFjZHkROJ6mlu0UKCvY6sTccKSugFu0/QncpR5/DBzYqTSe0OKQSMhzIN2HQEAo05OWxU9XQsTKRfg/bSB1//EXudt4jZEIyns29ZRAAAAAAAAAAB5cXFxcXFxcXFxcXFxcXFxcXl5PgAAAAAAAABwkZiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmEAAAC5vbmlvbvOggLGNXV1dDV0NAABVlEQAXRAAP11d+gj/f7+12l1VlABdEF0AROA9//////8I/38I/yZ/CP9/CP9/CP9/CP9/B/9/CHl5eXn/////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeXl5eQB5ecJ5eQF0eXl5eXl5eXl5eXkAgDsAAACAeXkmeXmwV3P1HqaLvq9HJCO3LQzu6Khz1/N6ndp/+0uXhvDVw6ekexeobSVOnFS7455nfwXAfGVyqxh8mvHWMdOKECKCa6HLBzj/rHbPG+HNtG/wvAIH/Ca5znqueYtfLR05Q66eoEheVZbgZSZn9xtbTUOMCPf+fwZ/3/wCs5ve9RqjRhRopnTXzm6R53SyY8OhPkjZfmHekZiP4qpCUN0rFIU8cZojTVAUZWJjT7OKXmAgZ5GWTGuyos8GKQMfmo4KCFuwt0/0+x9aKSC2z5JDTqebow5cVrdEjrozEjNXNL36tvOaLdGvcMfJ8xlUmOjI6DU+pmEn4ZUXUxUu9CnwZ8ZsjJcs0bOiVJd5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eYeHeXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5fXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5/YfYfutDeXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXkAeXl5eeEeeXl5eXl6eYATE3l5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl9eXl5eQCAOwAAAIB5eXl5eQ==
The following diff reproduces the behavior:
0diff --git a/src/test/banman_tests.cpp b/src/test/banman_tests.cpp
1index cebe3629d..d24f55979 100644
2--- a/src/test/banman_tests.cpp
3+++ b/src/test/banman_tests.cpp
4@@ -20,11 +20,12 @@ BOOST_AUTO_TEST_CASE(file)
5 SetMockTime(777s);
6 const fs::path banlist_path{m_args.GetDataDirBase() / "banlist_test"};
7 {
8+ const std::string suspect_subnet{"2e:6f6e:696f:6ef3:a080:b18d:5d5d:5d00%2038004089/121"};
9 const std::string entries_write{
10 "{ \"banned_nets\": ["
11 " { \"version\": 1, \"ban_created\": 0, \"banned_until\": 778, \"address\": \"aaaaaaaaa\" },"
12 " { \"version\": 2, \"ban_created\": 0, \"banned_until\": 778, \"address\": \"bbbbbbbbb\" },"
13- " { \"version\": 1, \"ban_created\": 0, \"banned_until\": 778, \"address\": \"1.0.0.0/8\" }"
14+ " { \"version\": 1, \"ban_created\": 0, \"banned_until\": 778, \"address\": \"2e:6f6e:696f:6ef3:a080:b18d:5d5d:5d00%2038004089/121\" }"
15 "] }",
16 };
17 BOOST_REQUIRE(WriteBinaryFile(banlist_path + ".json", entries_write));
18@@ -36,6 +37,11 @@ BOOST_AUTO_TEST_CASE(file)
19 banmap_t entries_read;
20 banman.GetBanned(entries_read);
21 BOOST_CHECK_EQUAL(entries_read.size(), 1);
22+
23+ for (const auto& it : entries_read) {
24+ CSubNet sub_net = it.first;
25+ BOOST_CHECK_EQUAL(sub_net.ToString(), suspect_subnet);
26+ }
27 }
28 }
29 }
0diff --git a/test/functional/rpc_setban.py b/test/functional/rpc_setban.py
1index b4f3d77e5..93a19920c 100755
2--- a/test/functional/rpc_setban.py
3+++ b/test/functional/rpc_setban.py
4@@ -25,6 +25,10 @@ class SetBanTests(BitcoinTestFramework):
5 peerinfo = self.nodes[1].getpeerinfo()[0]
6 assert not "noban" in peerinfo["permissions"]
7
8+ subnet = "2e:6f6e:696f:6ef3:a080:b18d:5d5d:5d00%2038004089/121"
9+ self.nodes[1].setban(subnet, "add")
10+ assert self.is_banned(self.nodes[1], subnet)
11+
12 # Node 0 get banned by Node 1
13 self.nodes[1].setban("127.0.0.1", "add")