Prevent OOB read on truncated H264 headers.
Prevents OOB reads on truncated FU-A NAL units, StapA headers and past truncation just after StapA headers. BUG=webrtc:4771 R=stefan@webrtc.org Review URL: https://codereview.webrtc.org/1218023003 Cr-Commit-Position: refs/heads/master@{#9522}
This commit is contained in:
parent
7ada923a94
commit
2f1509395b
@ -40,7 +40,7 @@ enum NalDefs { kFBit = 0x80, kNriMask = 0x60, kTypeMask = 0x1F };
|
||||
// Bit masks for FU (A and B) headers.
|
||||
enum FuDefs { kSBit = 0x80, kEBit = 0x40, kRBit = 0x20 };
|
||||
|
||||
void ParseSingleNalu(RtpDepacketizer::ParsedPayload* parsed_payload,
|
||||
bool ParseSingleNalu(RtpDepacketizer::ParsedPayload* parsed_payload,
|
||||
const uint8_t* payload_data,
|
||||
size_t payload_data_length) {
|
||||
parsed_payload->type.Video.width = 0;
|
||||
@ -55,6 +55,10 @@ void ParseSingleNalu(RtpDepacketizer::ParsedPayload* parsed_payload,
|
||||
uint8_t nal_type = payload_data[0] & kTypeMask;
|
||||
if (nal_type == kStapA) {
|
||||
// Skip the StapA header (StapA nal type + length).
|
||||
if (payload_data_length <= kStapAHeaderSize) {
|
||||
LOG(LS_ERROR) << "StapA header truncated.";
|
||||
return false;
|
||||
}
|
||||
nal_type = payload_data[kStapAHeaderSize] & kTypeMask;
|
||||
nalu_start += kStapAHeaderSize;
|
||||
nalu_length -= kStapAHeaderSize;
|
||||
@ -82,12 +86,17 @@ void ParseSingleNalu(RtpDepacketizer::ParsedPayload* parsed_payload,
|
||||
parsed_payload->frame_type = kVideoFrameDelta;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParseFuaNalu(RtpDepacketizer::ParsedPayload* parsed_payload,
|
||||
bool ParseFuaNalu(RtpDepacketizer::ParsedPayload* parsed_payload,
|
||||
const uint8_t* payload_data,
|
||||
size_t payload_data_length,
|
||||
size_t* offset) {
|
||||
if (payload_data_length < kFuAHeaderSize) {
|
||||
LOG(LS_ERROR) << "FU-A NAL units truncated.";
|
||||
return false;
|
||||
}
|
||||
uint8_t fnri = payload_data[0] & (kFBit | kNriMask);
|
||||
uint8_t original_nal_type = payload_data[1] & kTypeMask;
|
||||
bool first_fragment = (payload_data[1] & kSBit) > 0;
|
||||
@ -114,6 +123,7 @@ void ParseFuaNalu(RtpDepacketizer::ParsedPayload* parsed_payload,
|
||||
&parsed_payload->type.Video.codecHeader.H264;
|
||||
h264_header->packetization_type = kH264FuA;
|
||||
h264_header->nalu_type = original_nal_type;
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -326,11 +336,15 @@ bool RtpDepacketizerH264::Parse(ParsedPayload* parsed_payload,
|
||||
size_t offset = 0;
|
||||
if (nal_type == kFuA) {
|
||||
// Fragmented NAL units (FU-A).
|
||||
ParseFuaNalu(parsed_payload, payload_data, payload_data_length, &offset);
|
||||
if (!ParseFuaNalu(
|
||||
parsed_payload, payload_data, payload_data_length, &offset)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// We handle STAP-A and single NALU's the same way here. The jitter buffer
|
||||
// will depacketize the STAP-A into NAL units later.
|
||||
ParseSingleNalu(parsed_payload, payload_data, payload_data_length);
|
||||
if (!ParseSingleNalu(parsed_payload, payload_data, payload_data_length))
|
||||
return false;
|
||||
}
|
||||
|
||||
parsed_payload->payload = payload_data + offset;
|
||||
|
@ -545,4 +545,22 @@ TEST_F(RtpDepacketizerH264Test, TestEmptyPayload) {
|
||||
EXPECT_FALSE(depacketizer_->Parse(&payload, garbage_ptr, 0));
|
||||
}
|
||||
|
||||
TEST_F(RtpDepacketizerH264Test, TestTruncatedFuaNalu) {
|
||||
const uint8_t kPayload[] = {0x9c};
|
||||
RtpDepacketizer::ParsedPayload payload;
|
||||
EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
|
||||
}
|
||||
|
||||
TEST_F(RtpDepacketizerH264Test, TestTruncatedSingleStapANalu) {
|
||||
const uint8_t kPayload[] = {0xd8, 0x27};
|
||||
RtpDepacketizer::ParsedPayload payload;
|
||||
EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
|
||||
}
|
||||
|
||||
TEST_F(RtpDepacketizerH264Test, TestTruncationJustAfterSingleStapANalu) {
|
||||
const uint8_t kPayload[] = {0x38, 0x27, 0x27};
|
||||
RtpDepacketizer::ParsedPayload payload;
|
||||
EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
Loading…
x
Reference in New Issue
Block a user