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

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

Issue 2632203002: Packet Loss Tracker - Stream Separation (Closed)
Patch Set: CR response 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
« no previous file with comments | « no previous file | webrtc/voice_engine/transport_feedback_packet_loss_tracker.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 uint16_t base_seq_num = 0; 51 uint16_t base_seq_num = 0;
52 if (!ReadData<uint16_t>(&base_seq_num)) { 52 if (!ReadData<uint16_t>(&base_seq_num)) {
53 return; 53 return false;
54 } 54 }
55 55 constexpr int64_t kBaseTimeUs = 1234; // Irrelevant to this test.
56 const int64_t kBaseTimeUs = 1234; // Irrelevant to this test.
57 feedback->SetBase(base_seq_num, kBaseTimeUs); 56 feedback->SetBase(base_seq_num, kBaseTimeUs);
58 57
59 uint16_t num_statuses = 0; 58 uint16_t remaining_packets = 0;
60 if (!ReadData<uint16_t>(&num_statuses)) 59 if (!ReadData<uint16_t>(&remaining_packets))
61 return; 60 return false;
62 num_statuses = std::max<uint16_t>(num_statuses, 1); 61 // Range is [0x00001 : 0x10000], but we keep it 0x0000 to 0xffff for now,
62 // and add the last status as RECEIVED. That is because of a limitation
63 // that says that the last status cannot be LOST.
63 64
64 uint16_t seq_num = base_seq_num; 65 uint16_t seq_num = base_seq_num;
65 while (true) { 66 while (remaining_packets > 0) {
66 uint8_t status_byte = 0; 67 uint8_t status_byte = 0;
67 if (!ReadData<uint8_t>(&status_byte)) 68 if (!ReadData<uint8_t>(&status_byte)) {
68 return; 69 return false;
70 }
69 // Each status byte contains 8 statuses. 71 // Each status byte contains 8 statuses.
70 for (size_t j = 0; j < 8; ++j) { 72 for (size_t i = 0; i < 8 && remaining_packets > 0; ++i) {
71 if (status_byte & 0x01) { 73 const bool received = (status_byte & (0x01 << i));
74 if (received) {
72 feedback->AddReceivedPacket(seq_num, kBaseTimeUs); 75 feedback->AddReceivedPacket(seq_num, kBaseTimeUs);
73 } 76 }
74 seq_num++; 77 ++seq_num;
75 if (seq_num >= base_seq_num + num_statuses) { 78 --remaining_packets;
76 feedback->AddReceivedPacket(seq_num, kBaseTimeUs);
77 return;
78 }
79 status_byte >>= 1;
80 } 79 }
81 } 80 }
82 } 81
83 82 // As mentioned above, all feedbacks must report with a received packet.
84 bool ended() const { return ended_; } 83 feedback->AddReceivedPacket(seq_num, kBaseTimeUs);
84
85 return true;
86 }
85 87
86 private: 88 private:
87 template <typename T> 89 template <typename T>
88 bool ReadData(T* value) { 90 bool ReadData(T* value) {
89 RTC_CHECK(!ended_); 91 if (*size_ < sizeof(T)) {
90 if (data_idx_ + sizeof(T) > data_.size()) { 92 return false;
91 ended_ = true; 93 } else {
92 return false; 94 *value = FuzzInput<T>(data_, size_);
93 } 95 return true;
94 *value = ByteReader<T>::ReadBigEndian(&data_[data_idx_]); 96 }
95 data_idx_ += sizeof(T); 97 }
96 return true; 98
97 } 99 const uint8_t** data_;
98 100 size_t* size_;
99 const rtc::ArrayView<const uint8_t> data_;
100 bool ended_;
101 size_t data_idx_;
102 }; 101 };
103 102
104 } // namespace 103 bool Setup(const uint8_t** data,
105 104 size_t* size,
106 void FuzzOneInput(const uint8_t* data, size_t size) { 105 std::unique_ptr<TransportFeedbackPacketLossTracker>* tracker) {
107 if (size < 3 * sizeof(uint16_t)) { 106 if (*size < 3 * sizeof(uint16_t)) {
108 return; 107 return false;
109 } 108 }
109
110 constexpr size_t kSeqNumHalf = 0x8000u; 110 constexpr size_t kSeqNumHalf = 0x8000u;
111 111
112 // 0x8000 >= max_window_size >= plr_min_num_packets > rplr_min_num_pairs >= 1 112 // 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.) 113 // (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); 114 const size_t max_window_size = FuzzInRange(data, size, 2, kSeqNumHalf);
115 const size_t plr_min_num_packets = 115 const size_t plr_min_num_packets =
116 FuzzInRange(&data, &size, 2, max_window_size); 116 FuzzInRange(data, size, 2, max_window_size);
117 const size_t rplr_min_num_pairs = 117 const size_t rplr_min_num_pairs =
118 FuzzInRange(&data, &size, 1, plr_min_num_packets - 1); 118 FuzzInRange(data, size, 1, plr_min_num_packets - 1);
119 119
120 TransportFeedbackPacketLossTracker tracker( 120 tracker->reset(new TransportFeedbackPacketLossTracker(
121 max_window_size, plr_min_num_packets, rplr_min_num_pairs); 121 max_window_size, plr_min_num_packets, rplr_min_num_pairs));
122 122
123 TransportFeedbackGenerator feedback_generator( 123 return true;
124 rtc::ArrayView<const uint8_t>(data, size)); 124 }
125 125
126 while (!feedback_generator.ended()) { 126 bool FuzzSequenceNumberDelta(const uint8_t** data,
127 size_t* size,
128 uint16_t* delta) {
129 // Deltas fuzzed so that smaller deltas would be more likely, but even a
130 // complete wrap-around would be possible.
131 // Note: A delta of (x + 0x10000) is indistinguishable from a delta of (x),
132 // so deltas are distributed in the range [0 : 0xffff].
133 // The exact distribution is:
134 // * First seed in range [0 : 24] (~10% chance) -> delta is 1.
135 // * First seed in range [25 : 240] (~85% chance) -> delta in range [2 : 217]
136 // * First seed in range [241 : 255] (~5% chance) -> delta in [1 : 2^16]
minyue-webrtc 2017/02/16 13:19:22 as discussed offline, the outcome of a large delta
elad.alon_webrtc.org 2017/02/16 15:51:40 Done.
137
138 if (*size < sizeof(uint8_t)) {
139 return false;
140 }
141
142 uint8_t first_seed = FuzzInput<uint8_t>(data, size);
143 if (first_seed < 25) {
144 *delta = 1;
145 } else if (first_seed < 241) {
146 *delta = first_seed - 24 + 1;
147 } else if (*size < sizeof(uint16_t)) {
148 return false;
149 } else {
150 *delta = FuzzInput<uint16_t>(data, size); // Note: 2^16 == 0
151 }
152
153 return true;
154 }
155
156 bool FuzzPacketBlock(
minyue-webrtc 2017/02/16 09:51:44 I do not quite like the name. Unlike TransportFeed
elad.alon_webrtc.org 2017/02/16 15:51:40 FuzzPacketSendBlock, then?
minyue-webrtc 2017/02/17 11:09:14 that sounds good, and it is coupled to FuzzTranspo
157 std::unique_ptr<TransportFeedbackPacketLossTracker>& tracker,
158 const uint8_t** data,
159 size_t* size) {
160 // We want to test with block lengths between 0 and 2^16, inclusive(!).
161 // Easiest is to just disregard one potential block size in the middle, and
162 // assign it to be representative of 2^16.
163 if (*size < sizeof(uint16_t)) {
164 return false;
165 }
166 size_t packet_block_len = FuzzInput<uint16_t>(data, size);
167 constexpr size_t sentinel_for_wrap_around = 0x4321;
168 if (packet_block_len == sentinel_for_wrap_around) {
169 packet_block_len = 0xffff + 1;
170 }
171
172 if (packet_block_len == 0) {
173 return true;
174 }
175
176 // First sent sequence number uniformly selected.
177 if (*size < sizeof(uint16_t)) {
178 return false;
179 }
180 uint16_t seq_num = FuzzInput<uint16_t>(data, size);
181 tracker->OnPacketAdded(seq_num);
182 tracker->Validate();
183
184 // Fuzz subsequent sequence numbers according to a non-uniformly
185 // distributed delta (to make sure the fuzzer-test does not end up
186 // spending 99.9% of its time working on a mostly empty window).
187 for (size_t i = 1; i < packet_block_len; i++) {
188 uint16_t delta;
189 bool may_continue = FuzzSequenceNumberDelta(data, size, &delta);
190 if (!may_continue)
191 return false;
192 seq_num += delta;
193 tracker->OnPacketAdded(seq_num);
194 tracker->Validate();
195 }
196
197 return true;
198 }
199
200 bool FuzzTransportFeedbackBlock(
201 std::unique_ptr<TransportFeedbackPacketLossTracker>& tracker,
202 const uint8_t** data,
203 size_t* size) {
204 // Fuzz the number of back-to-back feedbacks. At least one, or this would
205 // be meaningless - we'd go straight back to fuzzing another packet
206 // transmission block.
207 if (*size < sizeof(uint8_t)) {
208 return false;
209 }
210
211 size_t feedbacks_num = 1 + (FuzzInput<uint8_t>(data, size) & 0x3f);
212 TransportFeedbackGenerator feedback_generator(data, size);
213
214 for (size_t i = 0; i < feedbacks_num; i++) {
127 rtcp::TransportFeedback feedback; 215 rtcp::TransportFeedback feedback;
128 feedback_generator.GetNextTransportFeedback(&feedback); 216 bool may_continue = feedback_generator.GetNextTransportFeedback(&feedback);
129 tracker.OnReceivedTransportFeedback(feedback); 217 if (!may_continue) {
130 tracker.Validate(); 218 return false;
131 } 219 }
132 } 220 tracker->OnReceivedTransportFeedback(feedback);
133 221 tracker->Validate();
222 }
223
224 return true;
225 }
226
227 } // namespace
228
229 void FuzzOneInput(const uint8_t* data, size_t size) {
230 std::unique_ptr<TransportFeedbackPacketLossTracker> tracker;
231 bool may_continue;
232
233 may_continue = Setup(&data, &size, &tracker);
234
235 while (may_continue) {
236 may_continue = FuzzPacketBlock(tracker, &data, &size);
237 if (!may_continue) {
238 return;
239 }
240 may_continue = FuzzTransportFeedbackBlock(tracker, &data, &size);
241 }
242 }
243
134 } // namespace webrtc 244 } // namespace webrtc
OLDNEW
« no previous file with comments | « no previous file | webrtc/voice_engine/transport_feedback_packet_loss_tracker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698