Update the current RTP parser fuzzer to handle header extensions.
This changes the corpus semantics, but libfuzzer should be smart enough to figure it out, and if not then we can add a seed_corpus to help.
BUG=webrtc:4771
NOTRY=true
Review-Url: https://codereview.webrtc.org/2072473002
Cr-Original-Commit-Position: refs/heads/master@{#13384}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 36a321d2e32bd9d823329958a71d4eba8356522a
diff --git a/test/fuzzers/rtp_header_fuzzer.cc b/test/fuzzers/rtp_header_fuzzer.cc
index fcc7377..914a8fb 100644
--- a/test/fuzzers/rtp_header_fuzzer.cc
+++ b/test/fuzzers/rtp_header_fuzzer.cc
@@ -10,29 +10,35 @@
#include <bitset>
-#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
namespace webrtc {
+// We decide which header extensions to register by reading one byte
+// from the beginning of |data| and interpreting it as a bitmask over
+// the RTPExtensionType enum. This assert ensures one byte is enough.
+static_assert(kRtpExtensionNumberOfExtensions <= 8,
+ "Insufficient bits read to configure all header extensions. Add "
+ "an extra byte and update the switches.");
+
void FuzzOneInput(const uint8_t* data, size_t size) {
if (size <= 1)
return;
- // We decide which header extensions to register by reading one byte
- // from the beginning of |data| and interpreting it as a bitmask
- // over the RTPExtensionType enum. That byte shouldn't also be part
- // of the packet, so we adjust |data| and |size| to remove it.
+ // Don't use the configuration byte as part of the packet.
std::bitset<8> extensionMask(data[0]);
data++;
size--;
RtpPacketReceived::ExtensionManager extensions;
- for (int i = 1; i <= kRtpExtensionNumberOfExtensions; i++) {
- // Skip i=0 which is kRtpExtensionNone i.e. not an actual extension.
- if (extensionMask[i]) {
- // We use i as the ID; it's used in negotiation so not relevant.
- extensions.Register(static_cast<RTPExtensionType>(i), i);
+ for (int i = 0; i < kRtpExtensionNumberOfExtensions; i++) {
+ RTPExtensionType extension_type = static_cast<RTPExtensionType>(i);
+ if (extensionMask[i] && extension_type != kRtpExtensionNone) {
+ // Extensions are registered with an ID, which you signal to the
+ // peer so they know what to expect. This code only cares about
+ // parsing so the value of the ID isn't relevant; we use i.
+ extensions.Register(extension_type, i);
}
}
diff --git a/test/fuzzers/rtp_packet_fuzzer.cc b/test/fuzzers/rtp_packet_fuzzer.cc
index a9efdb9..2a67a8b 100644
--- a/test/fuzzers/rtp_packet_fuzzer.cc
+++ b/test/fuzzers/rtp_packet_fuzzer.cc
@@ -7,13 +7,41 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
+
+#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
namespace webrtc {
-void FuzzOneInput(const uint8_t* data, size_t size) {
- RtpPacketReceived packet;
+// We decide which header extensions to register by reading one byte
+// from the beginning of |data| and interpreting it as a bitmask over
+// the RTPExtensionType enum. This assert ensures one byte is enough.
+static_assert(kRtpExtensionNumberOfExtensions <= 8,
+ "Insufficient bits read to configure all header extensions. Add "
+ "an extra byte and update the switches.");
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ if (size <= 1)
+ return;
+
+ // Don't use the configuration byte as part of the packet.
+ std::bitset<8> extensionMask(data[0]);
+ data++;
+ size--;
+
+ RtpPacketReceived::ExtensionManager extensions;
+ for (int i = 0; i < kRtpExtensionNumberOfExtensions; i++) {
+ RTPExtensionType extension_type = static_cast<RTPExtensionType>(i);
+ if (extensionMask[i] && extension_type != kRtpExtensionNone) {
+ // Extensions are registered with an ID, which you signal to the
+ // peer so they know what to expect. This code only cares about
+ // parsing so the value of the ID isn't relevant; we use i.
+ extensions.Register(extension_type, i);
+ }
+ }
+
+ RtpPacketReceived packet(&extensions);
packet.Parse(data, size);
// Call packet accessors because they have extra checks.
@@ -23,7 +51,40 @@
packet.Timestamp();
packet.Ssrc();
packet.Csrcs();
+
+ // Each extension has its own getter. It is supported behaviour to
+ // call GetExtension on an extension which was not registered, so we
+ // don't check the bitmask here.
+ for (int i = 0; i < kRtpExtensionNumberOfExtensions; i++) {
+ switch (static_cast<RTPExtensionType>(i)) {
+ case kRtpExtensionNone:
+ case kRtpExtensionNumberOfExtensions:
+ break;
+ case kRtpExtensionTransmissionTimeOffset:
+ int32_t offset;
+ packet.GetExtension<TransmissionOffset>(&offset);
+ break;
+ case kRtpExtensionAudioLevel:
+ bool voice_activity;
+ uint8_t audio_level;
+ packet.GetExtension<AudioLevel>(&voice_activity, &audio_level);
+ break;
+ case kRtpExtensionAbsoluteSendTime:
+ uint32_t sendtime;
+ packet.GetExtension<AbsoluteSendTime>(&sendtime);
+ break;
+ case kRtpExtensionVideoRotation:
+ uint8_t rotation;
+ packet.GetExtension<VideoOrientation>(&rotation);
+ break;
+ case kRtpExtensionTransportSequenceNumber:
+ uint16_t seqnum;
+ packet.GetExtension<TransportSequenceNumber>(&seqnum);
+ break;
+ case kRtpExtensionPlayoutDelay:
+ // TODO(katrielc) Add this once it's written.
+ break;
+ }
+ }
}
-
} // namespace webrtc
-