Chromium Code Reviews| Index: webrtc/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc |
| diff --git a/webrtc/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc b/webrtc/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc |
| index 5c3cfcba289b44103b7326cfc8b09c11f2fa7ead..8ff1c767124a90680e0e58c5885321fdf2a0dd90 100644 |
| --- a/webrtc/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc |
| +++ b/webrtc/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc |
| @@ -13,6 +13,7 @@ |
| #include "webrtc/base/array_view.h" |
| #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" |
| +#include "webrtc/system_wrappers/include/clock.h" |
| #include "webrtc/voice_engine/transport_feedback_packet_loss_tracker.h" |
| namespace webrtc { |
| @@ -109,16 +110,12 @@ bool Setup(const uint8_t** data, |
| constexpr size_t kSeqNumHalf = 0x8000u; |
| - // 0x8000 >= max_window_size >= plr_min_num_packets > rplr_min_num_pairs >= 1 |
| - // (The distribution isn't uniform, but it's enough; more would be overkill.) |
| - const size_t max_window_size = FuzzInRange(data, size, 2, kSeqNumHalf); |
| - const size_t plr_min_num_packets = |
| - FuzzInRange(data, size, 2, max_window_size); |
| - const size_t rplr_min_num_pairs = |
| - FuzzInRange(data, size, 1, plr_min_num_packets - 1); |
| + const int64_t max_window_size_ms = FuzzInRange(data, size, 1, 1 << 16); |
| + const size_t plr_min_num_packets = FuzzInRange(data, size, 1, kSeqNumHalf); |
| + const size_t rplr_min_num_pairs = FuzzInRange(data, size, 1, kSeqNumHalf - 1); |
| tracker->reset(new TransportFeedbackPacketLossTracker( |
| - max_window_size, plr_min_num_packets, rplr_min_num_pairs)); |
| + max_window_size_ms, plr_min_num_packets, rplr_min_num_pairs)); |
| return true; |
| } |
| @@ -140,10 +137,57 @@ bool FuzzSequenceNumberDelta(const uint8_t** data, |
| return true; |
| } |
| +bool FuzzClockAdvancement(const uint8_t** data, |
| + size_t* size, |
| + int64_t* time_ms) { |
| + // Fuzzing 64-bit worth of delta would be extreme overkill, as 32-bit is |
| + // already ~49 days long. We'll fuzz deltas up to a smaller value, and this |
| + // way also guarantee that wrap-around is impossible, as in real life. |
| + |
| + // Higher likelihood for more likely cases: |
| + // 5% chance of delta = 0. |
| + // 20% chance of delta in range [1 : 10] (uniformly distributed) |
| + // 55% chance of delta in range [11 : 500] (uniformly distributed) |
| + // 20% chance of delta in range [501 : 10000] (uniformly distributed) |
| + struct probability_distribution { |
| + float probability; |
| + size_t lower; |
| + size_t higher; |
| + }; |
| + constexpr probability_distribution clock_probability_distribution[] = { |
| + {0.05, 0, 0}, {0.20, 1, 10}, {0.55, 11, 500}, {0.20, 501, 10000} |
| + }; |
| + |
| + if (*size < sizeof(uint8_t)) { |
| + return false; |
| + } |
| + const float fuzzed = FuzzInput<uint8_t>(data, size) / 256.0f; |
| + |
| + float cumulative_probability = 0; |
| + for (const auto& dist : clock_probability_distribution) { |
| + cumulative_probability += dist.probability; |
| + if (fuzzed < cumulative_probability) { |
| + if (dist.lower == dist.higher) { |
| + *time_ms += dist.lower; |
| + return true; |
| + } else if (*size < sizeof(uint16_t)) { |
| + return false; |
| + } else { |
| + *time_ms += FuzzInRange(data, size, dist.lower, dist.higher); |
| + return true; |
| + } |
| + } |
| + } |
| + |
| + RTC_NOTREACHED(); |
| + return false; |
| +} |
| + |
| bool FuzzPacketSendBlock( |
| std::unique_ptr<TransportFeedbackPacketLossTracker>& tracker, |
| const uint8_t** data, |
| - size_t* size) { |
| + size_t* size, |
| + int64_t* time_ms) { |
| // We want to test with block lengths between 1 and 2^16, inclusive. |
| if (*size < sizeof(uint8_t)) { |
| return false; |
| @@ -155,16 +199,24 @@ bool FuzzPacketSendBlock( |
| return false; |
| } |
| uint16_t seq_num = FuzzInput<uint16_t>(data, size); |
| - tracker->OnPacketAdded(seq_num); |
| + tracker->OnPacketAdded(seq_num, *time_ms); |
| tracker->Validate(); |
| + bool may_continue = FuzzClockAdvancement(data, size, time_ms); |
| + if (!may_continue) { |
| + return false; |
| + } |
| + |
| for (size_t i = 1; i < packet_block_len; i++) { |
| uint16_t delta; |
| - bool may_continue = FuzzSequenceNumberDelta(data, size, &delta); |
| + may_continue = FuzzSequenceNumberDelta(data, size, &delta); |
| + if (!may_continue) |
| + return false; |
| + may_continue = FuzzClockAdvancement(data, size, time_ms); |
| if (!may_continue) |
| return false; |
| seq_num += delta; |
| - tracker->OnPacketAdded(seq_num); |
| + tracker->OnPacketAdded(seq_num, *time_ms); |
| tracker->Validate(); |
| } |
| @@ -206,8 +258,12 @@ void FuzzOneInput(const uint8_t* data, size_t size) { |
| may_continue = Setup(&data, &size, &tracker); |
| + // We never expect this to wrap around, so it makes sense to just start with |
| + // a sane value, and keep on incrementing by a fuzzed delta. |
| + int64_t time_ms = Clock::GetRealTimeClock()->TimeInMilliseconds(); |
|
pbos-webrtc
2017/03/03 18:37:34
Read a 32bit value from the fuzzed data instead, i
elad.alon_webrtc.org
2017/03/03 18:38:47
Will do.
|
| + |
| while (may_continue) { |
| - may_continue = FuzzPacketSendBlock(tracker, &data, &size); |
| + may_continue = FuzzPacketSendBlock(tracker, &data, &size, &time_ms); |
| if (!may_continue) { |
| return; |
| } |