@@ -575,179 +575,25 @@ class FuzzedSock : public Sock
575575 mutable std::optional<uint8_t > m_peek_data;
576576
577577public:
578- explicit FuzzedSock (FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_data_provider{fuzzed_data_provider}
579- {
580- m_socket = fuzzed_data_provider.ConsumeIntegralInRange <SOCKET>(INVALID_SOCKET - 1 , INVALID_SOCKET);
581- }
578+ explicit FuzzedSock (FuzzedDataProvider& fuzzed_data_provider);
582579
583- ~FuzzedSock () override
584- {
585- // Sock::~Sock() will be called after FuzzedSock::~FuzzedSock() and it will call
586- // Sock::Reset() (not FuzzedSock::Reset()!) which will call CloseSocket(m_socket).
587- // Avoid closing an arbitrary file descriptor (m_socket is just a random very high number which
588- // theoretically may concide with a real opened file descriptor).
589- Reset ();
590- }
580+ ~FuzzedSock () override ;
591581
592- FuzzedSock& operator =(Sock&& other) override
593- {
594- assert (false && " Move of Sock into FuzzedSock not allowed." );
595- return *this ;
596- }
582+ FuzzedSock& operator =(Sock&& other) override ;
597583
598- void Reset () override
599- {
600- m_socket = INVALID_SOCKET;
601- }
584+ void Reset () override ;
602585
603- ssize_t Send (const void * data, size_t len, int flags) const override
604- {
605- constexpr std::array send_errnos{
606- EACCES,
607- EAGAIN,
608- EALREADY,
609- EBADF,
610- ECONNRESET,
611- EDESTADDRREQ,
612- EFAULT,
613- EINTR,
614- EINVAL,
615- EISCONN,
616- EMSGSIZE,
617- ENOBUFS,
618- ENOMEM,
619- ENOTCONN,
620- ENOTSOCK,
621- EOPNOTSUPP,
622- EPIPE,
623- EWOULDBLOCK,
624- };
625- if (m_fuzzed_data_provider.ConsumeBool ()) {
626- return len;
627- }
628- const ssize_t r = m_fuzzed_data_provider.ConsumeIntegralInRange <ssize_t >(-1 , len);
629- if (r == -1 ) {
630- SetFuzzedErrNo (m_fuzzed_data_provider, send_errnos);
631- }
632- return r;
633- }
586+ ssize_t Send (const void * data, size_t len, int flags) const override ;
634587
635- ssize_t Recv (void * buf, size_t len, int flags) const override
636- {
637- // Have a permanent error at recv_errnos[0] because when the fuzzed data is exhausted
638- // SetFuzzedErrNo() will always return the first element and we want to avoid Recv()
639- // returning -1 and setting errno to EAGAIN repeatedly.
640- constexpr std::array recv_errnos{
641- ECONNREFUSED,
642- EAGAIN,
643- EBADF,
644- EFAULT,
645- EINTR,
646- EINVAL,
647- ENOMEM,
648- ENOTCONN,
649- ENOTSOCK,
650- EWOULDBLOCK,
651- };
652- assert (buf != nullptr || len == 0 );
653- if (len == 0 || m_fuzzed_data_provider.ConsumeBool ()) {
654- const ssize_t r = m_fuzzed_data_provider.ConsumeBool () ? 0 : -1 ;
655- if (r == -1 ) {
656- SetFuzzedErrNo (m_fuzzed_data_provider, recv_errnos);
657- }
658- return r;
659- }
660- std::vector<uint8_t > random_bytes;
661- bool pad_to_len_bytes{m_fuzzed_data_provider.ConsumeBool ()};
662- if (m_peek_data.has_value ()) {
663- // `MSG_PEEK` was used in the preceding `Recv()` call, return `m_peek_data`.
664- random_bytes.assign ({m_peek_data.value ()});
665- if ((flags & MSG_PEEK) == 0 ) {
666- m_peek_data.reset ();
667- }
668- pad_to_len_bytes = false ;
669- } else if ((flags & MSG_PEEK) != 0 ) {
670- // New call with `MSG_PEEK`.
671- random_bytes = m_fuzzed_data_provider.ConsumeBytes <uint8_t >(1 );
672- if (!random_bytes.empty ()) {
673- m_peek_data = random_bytes[0 ];
674- pad_to_len_bytes = false ;
675- }
676- } else {
677- random_bytes = m_fuzzed_data_provider.ConsumeBytes <uint8_t >(
678- m_fuzzed_data_provider.ConsumeIntegralInRange <size_t >(0 , len));
679- }
680- if (random_bytes.empty ()) {
681- const ssize_t r = m_fuzzed_data_provider.ConsumeBool () ? 0 : -1 ;
682- if (r == -1 ) {
683- SetFuzzedErrNo (m_fuzzed_data_provider, recv_errnos);
684- }
685- return r;
686- }
687- std::memcpy (buf, random_bytes.data (), random_bytes.size ());
688- if (pad_to_len_bytes) {
689- if (len > random_bytes.size ()) {
690- std::memset ((char *)buf + random_bytes.size (), 0 , len - random_bytes.size ());
691- }
692- return len;
693- }
694- if (m_fuzzed_data_provider.ConsumeBool () && std::getenv (" FUZZED_SOCKET_FAKE_LATENCY" ) != nullptr ) {
695- std::this_thread::sleep_for (std::chrono::milliseconds{2 });
696- }
697- return random_bytes.size ();
698- }
588+ ssize_t Recv (void * buf, size_t len, int flags) const override ;
699589
700- int Connect (const sockaddr*, socklen_t ) const override
701- {
702- // Have a permanent error at connect_errnos[0] because when the fuzzed data is exhausted
703- // SetFuzzedErrNo() will always return the first element and we want to avoid Connect()
704- // returning -1 and setting errno to EAGAIN repeatedly.
705- constexpr std::array connect_errnos{
706- ECONNREFUSED,
707- EAGAIN,
708- ECONNRESET,
709- EHOSTUNREACH,
710- EINPROGRESS,
711- EINTR,
712- ENETUNREACH,
713- ETIMEDOUT,
714- };
715- if (m_fuzzed_data_provider.ConsumeBool ()) {
716- SetFuzzedErrNo (m_fuzzed_data_provider, connect_errnos);
717- return -1 ;
718- }
719- return 0 ;
720- }
590+ int Connect (const sockaddr*, socklen_t ) const override ;
721591
722- int GetSockOpt (int level, int opt_name, void * opt_val, socklen_t * opt_len) const override
723- {
724- constexpr std::array getsockopt_errnos{
725- ENOMEM,
726- ENOBUFS,
727- };
728- if (m_fuzzed_data_provider.ConsumeBool ()) {
729- SetFuzzedErrNo (m_fuzzed_data_provider, getsockopt_errnos);
730- return -1 ;
731- }
732- if (opt_val == nullptr ) {
733- return 0 ;
734- }
735- std::memcpy (opt_val,
736- ConsumeFixedLengthByteVector (m_fuzzed_data_provider, *opt_len).data (),
737- *opt_len);
738- return 0 ;
739- }
592+ int GetSockOpt (int level, int opt_name, void * opt_val, socklen_t * opt_len) const override ;
740593
741594 bool Wait (std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr ) const override ;
742595
743- bool IsConnected (std::string& errmsg) const override
744- {
745- if (m_fuzzed_data_provider.ConsumeBool ()) {
746- return true ;
747- }
748- errmsg = " disconnected at random by the fuzzer" ;
749- return false ;
750- }
596+ bool IsConnected (std::string& errmsg) const override ;
751597};
752598
753599[[nodiscard]] inline FuzzedSock ConsumeSock (FuzzedDataProvider& fuzzed_data_provider)
0 commit comments