1*d9f75844SAndroid Build Coastguard Worker /* 2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. 3*d9f75844SAndroid Build Coastguard Worker * 4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 9*d9f75844SAndroid Build Coastguard Worker */ 10*d9f75844SAndroid Build Coastguard Worker #ifndef NET_DCSCTP_FUZZERS_DCSCTP_FUZZERS_H_ 11*d9f75844SAndroid Build Coastguard Worker #define NET_DCSCTP_FUZZERS_DCSCTP_FUZZERS_H_ 12*d9f75844SAndroid Build Coastguard Worker 13*d9f75844SAndroid Build Coastguard Worker #include <deque> 14*d9f75844SAndroid Build Coastguard Worker #include <memory> 15*d9f75844SAndroid Build Coastguard Worker #include <set> 16*d9f75844SAndroid Build Coastguard Worker #include <vector> 17*d9f75844SAndroid Build Coastguard Worker 18*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h" 19*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/task_queue_base.h" 20*d9f75844SAndroid Build Coastguard Worker #include "net/dcsctp/public/dcsctp_socket.h" 21*d9f75844SAndroid Build Coastguard Worker 22*d9f75844SAndroid Build Coastguard Worker namespace dcsctp { 23*d9f75844SAndroid Build Coastguard Worker namespace dcsctp_fuzzers { 24*d9f75844SAndroid Build Coastguard Worker 25*d9f75844SAndroid Build Coastguard Worker // A fake timeout used during fuzzing. 26*d9f75844SAndroid Build Coastguard Worker class FuzzerTimeout : public Timeout { 27*d9f75844SAndroid Build Coastguard Worker public: FuzzerTimeout(std::set<TimeoutID> & active_timeouts)28*d9f75844SAndroid Build Coastguard Worker explicit FuzzerTimeout(std::set<TimeoutID>& active_timeouts) 29*d9f75844SAndroid Build Coastguard Worker : active_timeouts_(active_timeouts) {} 30*d9f75844SAndroid Build Coastguard Worker Start(DurationMs duration_ms,TimeoutID timeout_id)31*d9f75844SAndroid Build Coastguard Worker void Start(DurationMs duration_ms, TimeoutID timeout_id) override { 32*d9f75844SAndroid Build Coastguard Worker // Start is only allowed to be called on stopped or expired timeouts. 33*d9f75844SAndroid Build Coastguard Worker if (timeout_id_.has_value()) { 34*d9f75844SAndroid Build Coastguard Worker // It has been started before, but maybe it expired. Ensure that it's not 35*d9f75844SAndroid Build Coastguard Worker // running at least. 36*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(active_timeouts_.find(*timeout_id_) == active_timeouts_.end()); 37*d9f75844SAndroid Build Coastguard Worker } 38*d9f75844SAndroid Build Coastguard Worker timeout_id_ = timeout_id; 39*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(active_timeouts_.insert(timeout_id).second); 40*d9f75844SAndroid Build Coastguard Worker } 41*d9f75844SAndroid Build Coastguard Worker Stop()42*d9f75844SAndroid Build Coastguard Worker void Stop() override { 43*d9f75844SAndroid Build Coastguard Worker // Stop is only allowed to be called on active timeouts. Not stopped or 44*d9f75844SAndroid Build Coastguard Worker // expired. 45*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(timeout_id_.has_value()); 46*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(active_timeouts_.erase(*timeout_id_) == 1); 47*d9f75844SAndroid Build Coastguard Worker timeout_id_ = absl::nullopt; 48*d9f75844SAndroid Build Coastguard Worker } 49*d9f75844SAndroid Build Coastguard Worker 50*d9f75844SAndroid Build Coastguard Worker // A set of all active timeouts, managed by `FuzzerCallbacks`. 51*d9f75844SAndroid Build Coastguard Worker std::set<TimeoutID>& active_timeouts_; 52*d9f75844SAndroid Build Coastguard Worker // If present, the timout is active and will expire reported as `timeout_id`. 53*d9f75844SAndroid Build Coastguard Worker absl::optional<TimeoutID> timeout_id_; 54*d9f75844SAndroid Build Coastguard Worker }; 55*d9f75844SAndroid Build Coastguard Worker 56*d9f75844SAndroid Build Coastguard Worker class FuzzerCallbacks : public DcSctpSocketCallbacks { 57*d9f75844SAndroid Build Coastguard Worker public: 58*d9f75844SAndroid Build Coastguard Worker static constexpr int kRandomValue = 42; SendPacket(rtc::ArrayView<const uint8_t> data)59*d9f75844SAndroid Build Coastguard Worker void SendPacket(rtc::ArrayView<const uint8_t> data) override { 60*d9f75844SAndroid Build Coastguard Worker sent_packets_.emplace_back(std::vector<uint8_t>(data.begin(), data.end())); 61*d9f75844SAndroid Build Coastguard Worker } CreateTimeout(webrtc::TaskQueueBase::DelayPrecision precision)62*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<Timeout> CreateTimeout( 63*d9f75844SAndroid Build Coastguard Worker webrtc::TaskQueueBase::DelayPrecision precision) override { 64*d9f75844SAndroid Build Coastguard Worker // The fuzzer timeouts don't implement |precision|. 65*d9f75844SAndroid Build Coastguard Worker return std::make_unique<FuzzerTimeout>(active_timeouts_); 66*d9f75844SAndroid Build Coastguard Worker } TimeMillis()67*d9f75844SAndroid Build Coastguard Worker TimeMs TimeMillis() override { return TimeMs(42); } GetRandomInt(uint32_t low,uint32_t high)68*d9f75844SAndroid Build Coastguard Worker uint32_t GetRandomInt(uint32_t low, uint32_t high) override { 69*d9f75844SAndroid Build Coastguard Worker return kRandomValue; 70*d9f75844SAndroid Build Coastguard Worker } OnMessageReceived(DcSctpMessage message)71*d9f75844SAndroid Build Coastguard Worker void OnMessageReceived(DcSctpMessage message) override {} OnError(ErrorKind error,absl::string_view message)72*d9f75844SAndroid Build Coastguard Worker void OnError(ErrorKind error, absl::string_view message) override {} OnAborted(ErrorKind error,absl::string_view message)73*d9f75844SAndroid Build Coastguard Worker void OnAborted(ErrorKind error, absl::string_view message) override {} OnConnected()74*d9f75844SAndroid Build Coastguard Worker void OnConnected() override {} OnClosed()75*d9f75844SAndroid Build Coastguard Worker void OnClosed() override {} OnConnectionRestarted()76*d9f75844SAndroid Build Coastguard Worker void OnConnectionRestarted() override {} OnStreamsResetFailed(rtc::ArrayView<const StreamID> outgoing_streams,absl::string_view reason)77*d9f75844SAndroid Build Coastguard Worker void OnStreamsResetFailed(rtc::ArrayView<const StreamID> outgoing_streams, 78*d9f75844SAndroid Build Coastguard Worker absl::string_view reason) override {} OnStreamsResetPerformed(rtc::ArrayView<const StreamID> outgoing_streams)79*d9f75844SAndroid Build Coastguard Worker void OnStreamsResetPerformed( 80*d9f75844SAndroid Build Coastguard Worker rtc::ArrayView<const StreamID> outgoing_streams) override {} OnIncomingStreamsReset(rtc::ArrayView<const StreamID> incoming_streams)81*d9f75844SAndroid Build Coastguard Worker void OnIncomingStreamsReset( 82*d9f75844SAndroid Build Coastguard Worker rtc::ArrayView<const StreamID> incoming_streams) override {} 83*d9f75844SAndroid Build Coastguard Worker ConsumeSentPacket()84*d9f75844SAndroid Build Coastguard Worker std::vector<uint8_t> ConsumeSentPacket() { 85*d9f75844SAndroid Build Coastguard Worker if (sent_packets_.empty()) { 86*d9f75844SAndroid Build Coastguard Worker return {}; 87*d9f75844SAndroid Build Coastguard Worker } 88*d9f75844SAndroid Build Coastguard Worker std::vector<uint8_t> ret = sent_packets_.front(); 89*d9f75844SAndroid Build Coastguard Worker sent_packets_.pop_front(); 90*d9f75844SAndroid Build Coastguard Worker return ret; 91*d9f75844SAndroid Build Coastguard Worker } 92*d9f75844SAndroid Build Coastguard Worker 93*d9f75844SAndroid Build Coastguard Worker // Given an index among the active timeouts, will expire that one. ExpireTimeout(size_t index)94*d9f75844SAndroid Build Coastguard Worker absl::optional<TimeoutID> ExpireTimeout(size_t index) { 95*d9f75844SAndroid Build Coastguard Worker if (index < active_timeouts_.size()) { 96*d9f75844SAndroid Build Coastguard Worker auto it = active_timeouts_.begin(); 97*d9f75844SAndroid Build Coastguard Worker std::advance(it, index); 98*d9f75844SAndroid Build Coastguard Worker TimeoutID timeout_id = *it; 99*d9f75844SAndroid Build Coastguard Worker active_timeouts_.erase(it); 100*d9f75844SAndroid Build Coastguard Worker return timeout_id; 101*d9f75844SAndroid Build Coastguard Worker } 102*d9f75844SAndroid Build Coastguard Worker return absl::nullopt; 103*d9f75844SAndroid Build Coastguard Worker } 104*d9f75844SAndroid Build Coastguard Worker 105*d9f75844SAndroid Build Coastguard Worker private: 106*d9f75844SAndroid Build Coastguard Worker // Needs to be ordered, to allow fuzzers to expire timers. 107*d9f75844SAndroid Build Coastguard Worker std::set<TimeoutID> active_timeouts_; 108*d9f75844SAndroid Build Coastguard Worker std::deque<std::vector<uint8_t>> sent_packets_; 109*d9f75844SAndroid Build Coastguard Worker }; 110*d9f75844SAndroid Build Coastguard Worker 111*d9f75844SAndroid Build Coastguard Worker // Given some fuzzing `data` will send packets to the socket as well as calling 112*d9f75844SAndroid Build Coastguard Worker // API methods. 113*d9f75844SAndroid Build Coastguard Worker void FuzzSocket(DcSctpSocketInterface& socket, 114*d9f75844SAndroid Build Coastguard Worker FuzzerCallbacks& cb, 115*d9f75844SAndroid Build Coastguard Worker rtc::ArrayView<const uint8_t> data); 116*d9f75844SAndroid Build Coastguard Worker 117*d9f75844SAndroid Build Coastguard Worker } // namespace dcsctp_fuzzers 118*d9f75844SAndroid Build Coastguard Worker } // namespace dcsctp 119*d9f75844SAndroid Build Coastguard Worker #endif // NET_DCSCTP_FUZZERS_DCSCTP_FUZZERS_H_ 120