Skip to content

Conversation

@vasild
Copy link
Contributor

@vasild vasild commented Mar 8, 2021

Change the networking code and the I2P code to be fully mockable and use FuzzedSocket to fuzz the I2P methods Listen(), Accept() and Connect().

Add a mocked Sock implementation that returns a predefined data on reads and use it for a regression unit test for the bug fixed in #21407.

@jonatack
Copy link
Member

jonatack commented Mar 8, 2021

Concept ACK

src/netbase.cpp Outdated
Comment on lines -645 to -575
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to reviewers: this old code was inconsistent with the events it requested depending on which function was used - it requested "in" or "out" (POLLIN | POLLOUT) when using poll() but only "out" when using select() (did not pass fdset as 2'nd arg to select()).

This is now replaced by Sock::Wait(..., requested Sock::RECV | Sock::SEND) which, if ends up calling select(), will ask it for both "in" and "out".

I think this is ok.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be good to split the non-fuzz "refactors" out into their own pull

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets see which are the non-fuzz refactors:

[7] i2p: add fuzz tests on the I2P Session public interface
[6] i2p: use pointers to Sock to accommodate mocking
[5] net: change ConnectSocketDirectly() to take a Sock argument
[4] net: add connect() and getsockopt() wrappers to Sock
[3] fuzz: avoid FuzzedSock::Recv() repeated errors with EAGAIN
[2] fuzz: extend FuzzedSock::Recv() to support MSG_PEEK
[1] fuzz: implement unimplemented FuzzedSock methods

1-3 are obviously fuzz. 4 touches FuzzedSocket. 7 adds fuzz tests. So only 5 and 6 remain. 5 depends on the previous commits. 6 is non-fuzz, does not depend on the previous commits and can be extracted, but 7 depends on it.
So a split can be:
PR-A: 6
PR-B: 1-5, 7

I think it is not worth to split, given that 6 is a small mechanical change.

src/netbase.cpp Outdated
Comment on lines -645 to -575
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be good to split the non-fuzz "refactors" out into their own pull

@practicalswift
Copy link
Contributor

Concept ACK

Thanks for improving FuzzedSock with connect, getsockopt and MSG_PEEK (recv) support! :)

Very happy to see the I2P code being thoroughly fuzzed before landing in a release! "Fuzz before release" is a nice high bar I think we should try to aim for going forward for new features :)

@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 8, 2021

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@vasild
Copy link
Contributor Author

vasild commented Mar 9, 2021

a6c20d2b8...933d181a8: avoid calling memcpy() with NULL argument even if size is 0

@jonatack
Copy link
Member

jonatack commented Mar 10, 2021

Saw this OOM error three times, but only with ../qa-assets/fuzz_seed_corpus/ (git pulled the latest head)

fuzz output

$ FUZZ=i2p src/test/fuzz/fuzz ../qa-assets/fuzz_seed_corpus/
INFO: Seed: 2309095707
INFO: Loaded 1 modules   (642728 inline 8-bit counters): 642728 [0x55bbf8e17668, 0x55bbf8eb4510), 
INFO: Loaded 1 PC tables (642728 PCs): 642728 [0x55bbf8eb4510,0x55bbf9882f90), 
INFO:   237105 files found in ../qa-assets/fuzz_seed_corpus/
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 1048576 bytes
INFO: seed corpus: files: 237105 min: 1b max: 3986616b total: 4147898382b rss: 359Mb
#4096	pulse  cov: 1461 ft: 1820 corp: 8/29b exec/s: 2048 rss: 445Mb
#8192	pulse  cov: 1862 ft: 2571 corp: 23/136b exec/s: 2048 rss: 520Mb
#16384	pulse  cov: 2655 ft: 4120 corp: 38/278b exec/s: 2340 rss: 659Mb
#32768	pulse  cov: 2749 ft: 5425 corp: 81/926b exec/s: 2730 rss: 722Mb
#65536	pulse  cov: 2813 ft: 6711 corp: 132/2841b exec/s: 2849 rss: 722Mb
#131072	pulse  cov: 2911 ft: 8428 corp: 169/7173b exec/s: 2730 rss: 722Mb
==16390== ERROR: libFuzzer: out-of-memory (used: 2191Mb; limit: 2048Mb)
   To change the out-of-memory limit use -rss_limit_mb=<N>

Live Heap Allocations: 89301481 bytes in 242997 chunks; quarantined: 245829231 bytes in 30252 chunks; 1909049 other chunks; total chunks: 2182298; showing top 95% (at most 8 unique contexts)
22746576 byte(s) (25%) in 237105 allocation(s)
    #0 0x55bbf4cf94fd in malloc (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2d444fd)
    #1 0x55bbf4c0bde7 in operator new(unsigned long) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c56de7)
    #2 0x55bbf4c23aac in fuzzer::ReadCorpora(std::Fuzzer::vector<std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> >, fuzzer::fuzzer_allocator<std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> > > > const&, std::Fuzzer::vector<std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> >, fuzzer::fuzzer_allocator<std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> > > > const&) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c6eaac)
    #3 0x55bbf4c23672 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c6e672)
    #4 0x55bbf4c4cb12 in main (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c97b12)
    #5 0x7f929ca83d09 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26d09)

21499328 byte(s) (24%) in 12 allocation(s)
    #0 0x55bbf4cf94fd in malloc (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2d444fd)
    #1 0x55bbf4c0bde7 in operator new(unsigned long) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c56de7)
    #2 0x55bbf4c4cb12 in main (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c97b12)
    #3 0x7f929ca83d09 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26d09)

16777216 byte(s) (18%) in 1 allocation(s)
    #0 0x55bbf4d28c3d in operator new(unsigned long) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2d73c3d)
    #1 0x55bbf4e228c5 in __gnu_cxx::new_allocator<uint256>::allocate(unsigned long, void const*) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/ext/new_allocator.h:115:27
    #2 0x55bbf4e228c5 in std::allocator_traits<std::allocator<uint256> >::allocate(std::allocator<uint256>&, unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/alloc_traits.h:460:20
    #3 0x55bbf4e228c5 in std::_Vector_base<uint256, std::allocator<uint256> >::_M_allocate(unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_vector.h:346:20
    #4 0x55bbf575d27a in std::vector<uint256, std::allocator<uint256> >::_M_default_append(unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/vector.tcc:635:34
    #5 0x55bbf575cdd2 in std::vector<uint256, std::allocator<uint256> >::resize(unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_vector.h:940:4
    #6 0x55bbf575c623 in CuckooCache::cache<uint256, SignatureCacheHasher>::setup(unsigned int) /home/jon/projects/bitcoin/bitcoin/src/./cuckoocache.h:344:15
    #7 0x55bbf59809e6 in CuckooCache::cache<uint256, SignatureCacheHasher>::setup_bytes(unsigned long) /home/jon/projects/bitcoin/bitcoin/src/./cuckoocache.h:368:16
    #8 0x55bbf59809e6 in InitScriptExecutionCache() /home/jon/projects/bitcoin/bitcoin/src/validation.cpp:1468:44
    #9 0x55bbf607ba7f in BasicTestingSetup::BasicTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&) /home/jon/projects/bitcoin/bitcoin/src/test/util/setup_common.cpp:110:5
    #10 0x55bbf4dc2187 in std::_MakeUniq<BasicTestingSetup const>::__single_object std::make_unique<BasicTestingSetup const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/unique_ptr.h:962:34
    #11 0x55bbf4dbe382 in std::unique_ptr<BasicTestingSetup const, std::default_delete<BasicTestingSetup const> > MakeNoLogFileContext<BasicTestingSetup const>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&) /home/jon/projects/bitcoin/bitcoin/src/./test/util/setup_common.h:170:12
    #12 0x55bbf4fe4723 in initialize_i2p() /home/jon/projects/bitcoin/bitcoin/src/test/fuzz/i2p.cpp:17:39
    #13 0x55bbf4d2f80c in void std::__invoke_impl<void, void (*&)()>(std::__invoke_other, void (*&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:60:14
    #14 0x55bbf4d2f80c in std::enable_if<is_invocable_r_v<void, void (*&)()>, void>::type std::__invoke_r<void, void (*&)()>(void (*&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:110:2
    #15 0x55bbf4d2f80c in std::_Function_handler<void (), void (*)()>::_M_invoke(std::_Any_data const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h:291:9
    #16 0x55bbf531c54c in std::function<void ()>::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h:622:14
    #17 0x55bbf66a3c92 in initialize() /home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz.cpp:44:5
    #18 0x55bbf66a51cd in LLVMFuzzerInitialize /home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz.cpp:70:5
    #19 0x55bbf4c218ac in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c6c8ac)
    #20 0x55bbf4c4cb12 in main (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c97b12)
    #21 0x7f929ca83d09 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26d09)

16777216 byte(s) (18%) in 1 allocation(s)
    #0 0x55bbf4d28c3d in operator new(unsigned long) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2d73c3d)
    #1 0x55bbf4e228c5 in __gnu_cxx::new_allocator<uint256>::allocate(unsigned long, void const*) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/ext/new_allocator.h:115:27
    #2 0x55bbf4e228c5 in std::allocator_traits<std::allocator<uint256> >::allocate(std::allocator<uint256>&, unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/alloc_traits.h:460:20
    #3 0x55bbf4e228c5 in std::_Vector_base<uint256, std::allocator<uint256> >::_M_allocate(unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_vector.h:346:20
    #4 0x55bbf575d27a in std::vector<uint256, std::allocator<uint256> >::_M_default_append(unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/vector.tcc:635:34
    #5 0x55bbf575cdd2 in std::vector<uint256, std::allocator<uint256> >::resize(unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/stl_vector.h:940:4
    #6 0x55bbf575c623 in CuckooCache::cache<uint256, SignatureCacheHasher>::setup(unsigned int) /home/jon/projects/bitcoin/bitcoin/src/./cuckoocache.h:344:15
    #7 0x55bbf5759dc2 in CuckooCache::cache<uint256, SignatureCacheHasher>::setup_bytes(unsigned long) /home/jon/projects/bitcoin/bitcoin/src/./cuckoocache.h:368:16
    #8 0x55bbf5759dc2 in (anonymous namespace)::CSignatureCache::setup_bytes(unsigned long) /home/jon/projects/bitcoin/bitcoin/src/script/sigcache.cpp:80:25
    #9 0x55bbf5759dc2 in InitSignatureCache() /home/jon/projects/bitcoin/bitcoin/src/script/sigcache.cpp:100:36
    #10 0x55bbf607ba6f in BasicTestingSetup::BasicTestingSetup(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&) /home/jon/projects/bitcoin/bitcoin/src/test/util/setup_common.cpp:109:5
    #11 0x55bbf4dc2187 in std::_MakeUniq<BasicTestingSetup const>::__single_object std::make_unique<BasicTestingSetup const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/unique_ptr.h:962:34
    #12 0x55bbf4dbe382 in std::unique_ptr<BasicTestingSetup const, std::default_delete<BasicTestingSetup const> > MakeNoLogFileContext<BasicTestingSetup const>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::vector<char const*, std::allocator<char const*> > const&) /home/jon/projects/bitcoin/bitcoin/src/./test/util/setup_common.h:170:12
    #13 0x55bbf4fe4723 in initialize_i2p() /home/jon/projects/bitcoin/bitcoin/src/test/fuzz/i2p.cpp:17:39
    #14 0x55bbf4d2f80c in void std::__invoke_impl<void, void (*&)()>(std::__invoke_other, void (*&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:60:14
    #15 0x55bbf4d2f80c in std::enable_if<is_invocable_r_v<void, void (*&)()>, void>::type std::__invoke_r<void, void (*&)()>(void (*&)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:110:2
    #16 0x55bbf4d2f80c in std::_Function_handler<void (), void (*)()>::_M_invoke(std::_Any_data const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h:291:9
    #17 0x55bbf531c54c in std::function<void ()>::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h:622:14
    #18 0x55bbf66a3c92 in initialize() /home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz.cpp:44:5
    #19 0x55bbf66a51cd in LLVMFuzzerInitialize /home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz.cpp:70:5
    #20 0x55bbf4c218ac in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c6c8ac)
    #21 0x55bbf4c4cb12 in main (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c97b12)
    #22 0x7f929ca83d09 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26d09)

8388608 byte(s) (9%) in 1 allocation(s)
    #0 0x55bbf4cf94fd in malloc (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2d444fd)
    #1 0x55bbf4c0bde7 in operator new(unsigned long) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c56de7)
    #2 0x55bbf4c2f807 in fuzzer::GetSizedFilesFromDir(std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> > const&, std::Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >*) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c7a807)
    #3 0x55bbf4c23aac in fuzzer::ReadCorpora(std::Fuzzer::vector<std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> >, fuzzer::fuzzer_allocator<std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> > > > const&, std::Fuzzer::vector<std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> >, fuzzer::fuzzer_allocator<std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> > > > const&) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c6eaac)
    #4 0x55bbf4c23672 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c6e672)
    #5 0x55bbf4c4cb12 in main (/home/jon/projects/bitcoin/bitcoin/src/test/fuzz/fuzz+0x2c97b12)
    #6 0x7f929ca83d09 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26d09)

MS: 0 ; base unit: 0000000000000000000000000000000000000000


artifact_prefix='./'; Test unit written to ./oom-da39a3ee5e6b4b0d3255bfef95601890afd80709
Base64: 
SUMMARY: libFuzzer: out-of-memory

@jonatack
Copy link
Member

Had the same OOM issue today with another fuzz PR, so I'm proceeding on the assumption that it's a regression that is not related to this PR.

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Built and reviewed each commit up to 34c199db11b36eee91e56cdd046c090f62da18d6.

In the 3rd commit, "avoid repeated errors," it looks like the commit message should be "to retry the operation." e.g. s/to/the/

@vasild
Copy link
Contributor Author

vasild commented Mar 12, 2021

Had the same OOM issue today with another fuzz PR

Can you reproduce it? E.g. FUZZ=i2p src/test/fuzz/fuzz ./oom-da39a3ee5e6b4b0d3255bfef95601890afd80709

@jonatack
Copy link
Member

INFO: Seed: 3949145381
INFO: Loaded 1 modules   (643885 inline 8-bit counters): 643885 [0x56188117c288, 0x5618812195b5), 
INFO: Loaded 1 PC tables (643885 PCs): 643885 [0x5618812195b8,0x561881bec888), 
src/test/fuzz/fuzz: Running 1 inputs 1 time(s) each.
Running: oom-da39a3ee5e6b4b0d3255bfef95601890afd80709
Executed oom-da39a3ee5e6b4b0d3255bfef95601890afd80709 in 0 ms
***
*** NOTE: fuzzing was not performed, you have only
***       executed the target code on a fixed set of inputs.
***

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 933d181a8c0c41318204b1657765d582418a80a1 modulo a few thoughts/questions above

@vasild
Copy link
Contributor Author

vasild commented Mar 12, 2021

933d181a8...7c6fc2de5: address suggestions and also fuzz the IsConnected() method of Sock / FuzzedSock.

@vasild
Copy link
Contributor Author

vasild commented Mar 12, 2021

7c6fc2de5...23c861d6f: fix Windows CI

@jonatack
Copy link
Member

re-ACK 23c861d6ff995b7e6034d4bec6af2f6a3d595dca

vasild added 2 commits March 16, 2021 13:53
We want `Get()` to always return the same value, otherwise it will look
like the `FuzzedSock` implementation itself is broken. So assign
`m_socket` a random number in the `FuzzedSock` constructor.

There is nothing to fuzz about the `Get()` and `Release()` methods, so
use the ones from the base class `Sock`.

`Reset()` is just setting our socket to `INVALID_SOCKET`. We don't want
to use the base `Reset()` because it will close `m_socket` and given
that our `m_socket` is just a random number it may end up closing a real
opened file descriptor if it coincides with our random `m_socket`.
A conforming `recv(2)` call is supposed to return the same data on a
call following `recv(..., MSG_PEEK)`. Extend `FuzzedSock::Recv()` to do
that.

For simplicity we only return 1 byte when `MSG_PEEK` is used. If we
would return a buffer of N bytes, then we would have to keep track how
many of them were consumed on subsequent non-`MSG_PEEK` calls.
@practicalswift
Copy link
Contributor

Tested ACK 40316a3

Great fuzzing work @vasild!

@maflcko maflcko changed the title test: add I2P fuzz and unit tests p2p: Refactor sock to add I2P fuzz and unit tests Mar 22, 2021
@maflcko
Copy link
Member

maflcko commented Mar 22, 2021

(Changed title, because this is not test-only)

@maflcko
Copy link
Member

maflcko commented Mar 22, 2021

Concept ACK 40316a3

Copy link
Member

@laanwj laanwj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review ACK 40316a3

I like how this gets rid of a #ifdef USE_POLL in the connect logic.

@laanwj laanwj merged commit f9e86d8 into bitcoin:master Mar 30, 2021
@vasild vasild deleted the i2p_tests branch March 30, 2021 15:43
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Mar 30, 2021
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Feb 15, 2022
Summary:
> net: add connect() and getsockopt() wrappers to Sock
>
> Extend the `Sock` class with wrappers to `connect()` and `getsockopt()`.
>
> This will make it possible to mock code which uses those.
bitcoin/bitcoin@b586110

> net: change ConnectSocketDirectly() to take a Sock argument
>
> Change `ConnectSocketDirectly()` to take a `Sock` argument instead of a
> bare `SOCKET`. With this, use the `Sock`'s (possibly mocked) methods
> `Connect()`, `Wait()` and `GetSockOpt()` instead of calling the OS
> functions directly.
bitcoin/bitcoin@82d360b

> i2p: use pointers to Sock to accommodate mocking
>
> Change the types of `i2p::Connection::sock` and
> `i2p::sam::Session::m_control_sock` from `Sock` to
> `std::unique_ptr<Sock>`.
>
> Using pointers would allow us to sneak `FuzzedSock` instead of `Sock`
> and have the methods of the former called.
>
> After this change a test only needs to replace `CreateSock()` with
> a function that returns `FuzzedSock`.
bitcoin/bitcoin@9947e44

> test: add I2P test for a runaway SAM proxy
>
> Add a regression test for bitcoin/bitcoin#21407.
>
> The test creates a socket that, upon read, returns some data, but never
> the expected terminator `\n`, injects that socket into the I2P code and
> expects `i2p::sam::Session::Connect()` to fail, printing a specific
> error message to the log.
bitcoin/bitcoin@40316a3

This is a partial backport of [[bitcoin/bitcoin#21387 | core#21387]], without the fuzzer changes.
Depends on D11037

Test Plan: `ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Subscribers: Fabien

Differential Revision: https://reviews.bitcoinabc.org/D11042

if (sess.Connect(to, conn, proxy_error)) {
try {
conn.sock->SendComplete("verack\n", 10ms, interrupt);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@vasild vasild Jun 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it would be executed, but for Connect() to return true the fuzzed sock must return some meaningful data, which I guess has a very very low chance of happening.

Edit: now I remember I was considering crafting a custom fuzz-corpus data input which would contain the meaningful data at the right offsets so that Connect() will succeed. I gave up because that would be difficult to maintain because the binary "magic" corpus data would have to be adjusted every time this test is modified to add or remove calls that consume fuzz data before Connect() is called. Also, that would not be fuzzing so much, but rather some kind of unit testing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There'd also be a middle way to teach the fuzz engine a meaningful format or snippets. This can be achieved with a dict, a custom mutator, or with some code in the fuzz target (CallOneOf(...))

kwvg added a commit to kwvg/dash that referenced this pull request Apr 17, 2023
@bitcoin bitcoin locked and limited conversation to collaborators Jun 9, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants