Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(604)

Side by Side Diff: webrtc/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc

Issue 2632203002: Packet Loss Tracker - Stream Separation (Closed)
Patch Set: hint Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 26 matching lines...) Expand all
37 RTC_CHECK_LT(upper - lower, 1 << (8 * sizeof(uint16_t))); 37 RTC_CHECK_LT(upper - lower, 1 << (8 * sizeof(uint16_t)));
38 const size_t range = upper - lower; 38 const size_t range = upper - lower;
39 const uint16_t fuzzed = FuzzInput<uint16_t>(data, size); 39 const uint16_t fuzzed = FuzzInput<uint16_t>(data, size);
40 const size_t offset = (static_cast<float>(fuzzed) / 0x10000) * (range + 1); 40 const size_t offset = (static_cast<float>(fuzzed) / 0x10000) * (range + 1);
41 RTC_CHECK_LE(offset, range); // (fuzzed <= 0xffff) -> (offset < range + 1) 41 RTC_CHECK_LE(offset, range); // (fuzzed <= 0xffff) -> (offset < range + 1)
42 return lower + offset; 42 return lower + offset;
43 } 43 }
44 44
45 class TransportFeedbackGenerator { 45 class TransportFeedbackGenerator {
46 public: 46 public:
47 explicit TransportFeedbackGenerator(rtc::ArrayView<const uint8_t> data) 47 explicit TransportFeedbackGenerator(const uint8_t** data, size_t* size)
48 : data_(data), ended_(false), data_idx_(0) {} 48 : data_(data), size_(size) {}
49 49
50 void GetNextTransportFeedback(rtcp::TransportFeedback* feedback) { 50 bool GetNextTransportFeedback(rtcp::TransportFeedback* feedback) {
51 constexpr int64_t kBaseTimeUs = 1234; // Irrelevant to this test.
minyue-webrtc 2017/02/14 16:46:59 the old place is better. Generally, make it as clo
elad.alon_webrtc.org 2017/02/15 16:47:36 Done.
52
51 uint16_t base_seq_num = 0; 53 uint16_t base_seq_num = 0;
52 if (!ReadData<uint16_t>(&base_seq_num)) { 54 if (!ReadData<uint16_t>(&base_seq_num)) {
53 return; 55 return false;
54 } 56 }
55
56 const int64_t kBaseTimeUs = 1234; // Irrelevant to this test.
57 feedback->SetBase(base_seq_num, kBaseTimeUs); 57 feedback->SetBase(base_seq_num, kBaseTimeUs);
58 58
59 uint16_t num_statuses = 0; 59 uint16_t remaining_packets = 0;
60 if (!ReadData<uint16_t>(&num_statuses)) 60 if (!ReadData<uint16_t>(&remaining_packets))
61 return; 61 return false;
62 num_statuses = std::max<uint16_t>(num_statuses, 1); 62 // Range is [0x00001 : 0x10000], but we keep it 0x0000 to 0xffff for now,
63 // and add the last status as RECEIVED. That is because of a limitation
64 // that says that the last status cannot be LOST.
63 65
64 uint16_t seq_num = base_seq_num; 66 uint16_t seq_num = base_seq_num;
65 while (true) { 67 while (remaining_packets > 0) {
minyue-webrtc 2017/02/14 16:46:58 if there any functional changes made in this loop?
elad.alon_webrtc.org 2017/02/15 16:47:36 The previous code was no bad, of course! It's just
66 uint8_t status_byte = 0; 68 uint8_t status_byte = 0;
67 if (!ReadData<uint8_t>(&status_byte)) 69 if (!ReadData<uint8_t>(&status_byte)) {
minyue-webrtc 2017/02/14 16:46:59 nit: remove {}
68 return; 70 return false;
71 }
69 // Each status byte contains 8 statuses. 72 // Each status byte contains 8 statuses.
70 for (size_t j = 0; j < 8; ++j) { 73 for (size_t i = 0; i < 8 && remaining_packets > 0; ++i) {
71 if (status_byte & 0x01) { 74 const bool received = (status_byte & (0x01 << i));
75 if (received) {
minyue-webrtc 2017/02/14 16:46:59 nit: remove {}
72 feedback->AddReceivedPacket(seq_num, kBaseTimeUs); 76 feedback->AddReceivedPacket(seq_num, kBaseTimeUs);
73 } 77 }
74 seq_num++; 78 ++seq_num;
75 if (seq_num >= base_seq_num + num_statuses) { 79 --remaining_packets;
76 feedback->AddReceivedPacket(seq_num, kBaseTimeUs);
77 return;
78 }
79 status_byte >>= 1;
80 } 80 }
81 } 81 }
82 } 82
83 83 // As mentioned above, all feedbacks must report with a received packet.
84 bool ended() const { return ended_; } 84 feedback->AddReceivedPacket(seq_num, kBaseTimeUs);
85
86 return true;
87 }
85 88
86 private: 89 private:
87 template <typename T> 90 template <typename T>
88 bool ReadData(T* value) { 91 bool ReadData(T* value) {
89 RTC_CHECK(!ended_); 92 if (*size_ < sizeof(T)) {
90 if (data_idx_ + sizeof(T) > data_.size()) { 93 return false;
91 ended_ = true; 94 } else {
92 return false; 95 *value = FuzzInput<T>(data_, size_);
93 } 96 return true;
94 *value = ByteReader<T>::ReadBigEndian(&data_[data_idx_]); 97 }
95 data_idx_ += sizeof(T); 98 }
96 return true; 99
97 } 100 const uint8_t** data_;
98 101 size_t* size_;
minyue-webrtc 2017/02/14 16:46:59 size_ -> remaining_bytes_
elad.alon_webrtc.org 2017/02/15 16:47:35 FuzzOneInput() takes on a parameter called "size",
minyue-webrtc 2017/02/16 09:51:44 Acknowledged.
99 const rtc::ArrayView<const uint8_t> data_;
100 bool ended_;
101 size_t data_idx_;
102 }; 102 };
103 103
104 } // namespace 104 bool Setup(const uint8_t** data,
105 105 size_t* size,
106 void FuzzOneInput(const uint8_t* data, size_t size) { 106 std::unique_ptr<TransportFeedbackPacketLossTracker>* tracker) {
107 if (size < 3 * sizeof(uint16_t)) { 107 if (*size < 3 * sizeof(uint16_t)) {
108 return; 108 return false;
109 } 109 }
110
110 constexpr size_t kSeqNumHalf = 0x8000u; 111 constexpr size_t kSeqNumHalf = 0x8000u;
111 112
112 // 0x8000 >= max_window_size >= plr_min_num_packets > rplr_min_num_pairs >= 1 113 // 0x8000 >= max_window_size >= plr_min_num_packets > rplr_min_num_pairs >= 1
113 // (The distribution isn't uniform, but it's enough; more would be overkill.) 114 // (The distribution isn't uniform, but it's enough; more would be overkill.)
114 const size_t max_window_size = FuzzInRange(&data, &size, 2, kSeqNumHalf); 115 const size_t max_window_size = FuzzInRange(data, size, 2, kSeqNumHalf);
115 const size_t plr_min_num_packets = 116 const size_t plr_min_num_packets =
116 FuzzInRange(&data, &size, 2, max_window_size); 117 FuzzInRange(data, size, 2, max_window_size);
117 const size_t rplr_min_num_pairs = 118 const size_t rplr_min_num_pairs =
118 FuzzInRange(&data, &size, 1, plr_min_num_packets - 1); 119 FuzzInRange(data, size, 1, plr_min_num_packets - 1);
119 120
120 TransportFeedbackPacketLossTracker tracker( 121 tracker->reset(new TransportFeedbackPacketLossTracker(
121 max_window_size, plr_min_num_packets, rplr_min_num_pairs); 122 max_window_size, plr_min_num_packets, rplr_min_num_pairs));
122 123
123 TransportFeedbackGenerator feedback_generator( 124 return true;
124 rtc::ArrayView<const uint8_t>(data, size)); 125 }
125 126
126 while (!feedback_generator.ended()) { 127 bool FuzzSequenceNumberDelta(const uint8_t** data,
128 size_t* size,
129 uint16_t* delta) {
130 // Deltas fuzzed so that smaller deltas would be more likely, but even a
131 // complete wrap-around would be possible.
132 // Note: A delta of (x + 0x10000) is indistinguishable from a delta of (x),
133 // so deltas are distributed in the range [0 : 0xffff].
134 // The exact distribution is:
135 // * First seed in range [0 : 24] (~10% chance) -> delta is 1.
136 // * First seed in range [25 : 240] (~85% chance) -> delta in range [2 : 217]
137 // * First seed in range [241 : 255] (~5% chance) -> delta in [1 : 2^16]
138
139 if (*size < sizeof(uint8_t)) {
140 return false;
141 }
142
143 uint8_t first_seed = FuzzInput<uint8_t>(data, size);
144 if (first_seed < 25) {
145 *delta = 1;
146 } else if (first_seed < 241) {
147 *delta = first_seed - 24 + 1;
148 } else if (*size < sizeof(uint16_t)) {
149 return false;
150 } else {
151 *delta = FuzzInput<uint16_t>(data, size); // Note: 2^16 == 0
152 }
153
154 return true;
155 }
156
157 bool FuzzPacketTransmissionBurst(
minyue-webrtc 2017/02/14 16:46:58 And I think this is not "transmission", which may
minyue-webrtc 2017/02/14 16:46:59 I see the "burst" here means burst send instead of
elad.alon_webrtc.org 2017/02/15 16:47:36 Changed to FuzzPacketBlock, to keep it consistent
158 std::unique_ptr<TransportFeedbackPacketLossTracker>& tracker,
159 const uint8_t** data,
160 size_t* size) {
161 // We want to test with bursts lengths between 0 and 2^16, inclusive(!).
162 // Easiest is to just disregard one potential burst size in the middle, and
163 // assign it to be representative of 2^16.
164 if (*size < sizeof(uint16_t)) {
165 return false;
166 }
167 size_t packet_transmission_burst_len = FuzzInput<uint16_t>(data, size);
168 constexpr size_t sentinel_for_wrap_around = 0x4321;
169 if (packet_transmission_burst_len == sentinel_for_wrap_around) {
170 packet_transmission_burst_len = 0xffff + 1;
minyue-webrtc 2017/02/14 16:46:59 a little bit too ad hoc. can we packet_transmissi
elad.alon_webrtc.org 2017/02/15 16:47:35 The problem is that 0 is a valid case which should
minyue-webrtc 2017/02/16 09:51:44 I think 0 case should be included in the unittest,
elad.alon_webrtc.org 2017/02/16 15:51:40 Okay, I'll modify.
171 }
172
173 if (packet_transmission_burst_len == 0) {
174 return true;
175 }
176
177 // First sent sequence number uniformly selected.
178 if (*size < sizeof(uint16_t)) {
179 return false;
180 }
181 uint16_t seq_num = FuzzInput<uint16_t>(data, size);
182 tracker->OnPacketAdded(seq_num);
minyue-webrtc 2017/02/14 16:46:58 try moving 182,183 in to loop.
elad.alon_webrtc.org 2017/02/15 16:47:36 I think it's clearer like this - first packet gets
minyue-webrtc 2017/02/16 09:51:44 Acknowledged.
183 tracker->Validate();
184
185 // Fuzz subsequent sequence numbers according to a non-uniformly
186 // distributed delta (to make sure the fuzzer-test does not end up
187 // spending 99.9% of its time working on a mostly empty window).
188 while (--packet_transmission_burst_len > 0) {
189 uint16_t delta;
190 bool may_continue = FuzzSequenceNumberDelta(data, size, &delta);
191 if (!may_continue)
192 return false;
193 seq_num += delta;
194 tracker->OnPacketAdded(seq_num);
195 tracker->Validate();
196 }
197
198 return true;
199 }
200
201 bool FuzzTransportFeedbackBurst(
minyue-webrtc 2017/02/14 16:46:58 try not calling this Bursts either. FuzzTransport
elad.alon_webrtc.org 2017/02/15 16:47:36 Done (FuzzTransportFeedbackBlock).
202 std::unique_ptr<TransportFeedbackPacketLossTracker>& tracker,
203 const uint8_t** data,
204 size_t* size) {
205 // Fuzz the number of back-to-back feedbacks. At least one, or this would
206 // be meaningless - we'd go straight back to fuzzing another packet
207 // transmission burst.
208 if (*size < sizeof(uint8_t)) {
209 return false;
210 }
211
212 size_t feedbacks_num = 1 + (FuzzInput<uint8_t>(data, size) & 0x3f);
213 TransportFeedbackGenerator feedback_generator(data, size);
214
215 for (size_t i = 0; i < feedbacks_num; i++) {
127 rtcp::TransportFeedback feedback; 216 rtcp::TransportFeedback feedback;
128 feedback_generator.GetNextTransportFeedback(&feedback); 217 bool may_continue = feedback_generator.GetNextTransportFeedback(&feedback);
129 tracker.OnReceivedTransportFeedback(feedback); 218 if (!may_continue) {
130 tracker.Validate(); 219 return false;
131 } 220 }
132 } 221 tracker->OnReceivedTransportFeedback(feedback);
133 222 tracker->Validate();
223 }
224
225 return true;
226 }
227
228 } // namespace
229
230 void FuzzOneInput(const uint8_t* data, size_t size) {
231 std::unique_ptr<TransportFeedbackPacketLossTracker> tracker;
232 bool may_continue;
233
234 may_continue = Setup(&data, &size, &tracker);
235
236 while (may_continue) {
237 may_continue = FuzzPacketTransmissionBurst(tracker, &data, &size);
238 if (!may_continue) {
239 return;
240 }
241 may_continue = FuzzTransportFeedbackBurst(tracker, &data, &size);
minyue-webrtc 2017/02/14 16:46:59 it looks like send and feedback are independent. W
elad.alon_webrtc.org 2017/02/15 16:47:35 When running the fuzzer, we do get them to overlap
minyue-webrtc 2017/02/16 09:51:44 IMO, making the sending and feedback totally indep
minyue-webrtc 2017/02/16 13:19:22 I realized that I was wrong in saying that "feedba
242 }
243 }
244
134 } // namespace webrtc 245 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698