summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-09-06 12:52:58 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-09-12 07:43:37 +0000
commit5adda98099d631166395b9f3fe6fed39a79edf75 (patch)
tree7023e606ac24b8d23dc1eb8ebd43981a8942e1ac
parent38b701b44f54ff5e5b8b772d5cabe0e59569d032 (diff)
[Backport] CVE-2018-16071
Unwrap TL0 pic index to avoid having to work with a wrapped number. This is to avoid clearing the |gof_info_| map when there are jumps in the tl0 pic index. Bug: chromium:855211 Change-Id: I762557070d65b3c535cb9a49498975bcd9c2c485 Reviewed-on: https://webrtc-review.googlesource.com/86943 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
-rw-r--r--chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder.cc59
-rw-r--r--chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder.h18
-rw-r--r--chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc10
3 files changed, 48 insertions, 39 deletions
diff --git a/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder.cc b/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder.cc
index b2511351f5f..09bb1d8b51b 100644
--- a/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder.cc
+++ b/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder.cc
@@ -276,8 +276,10 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp8(
} while (last_picture_id_ != frame->picture_id);
}
+ int64_t unwrapped_tl0 = tl0_unwrapper_.Unwrap(codec_header.tl0PicIdx);
+
// Clean up info for base layers that are too old.
- uint8_t old_tl0_pic_idx = codec_header.tl0PicIdx - kMaxLayerInfo;
+ int64_t old_tl0_pic_idx = unwrapped_tl0 - kMaxLayerInfo;
auto clean_layer_info_to = layer_info_.lower_bound(old_tl0_pic_idx);
layer_info_.erase(layer_info_.begin(), clean_layer_info_to);
@@ -290,14 +292,13 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp8(
if (frame->frame_type() == kVideoFrameKey) {
frame->num_references = 0;
- layer_info_[codec_header.tl0PicIdx].fill(-1);
- UpdateLayerInfoVp8(frame, codec_header);
+ layer_info_[unwrapped_tl0].fill(-1);
+ UpdateLayerInfoVp8(frame, unwrapped_tl0, codec_header.temporalIdx);
return kHandOff;
}
- auto layer_info_it = layer_info_.find(codec_header.temporalIdx == 0
- ? codec_header.tl0PicIdx - 1
- : codec_header.tl0PicIdx);
+ auto layer_info_it = layer_info_.find(
+ codec_header.temporalIdx == 0 ? unwrapped_tl0 - 1 : unwrapped_tl0);
// If we don't have the base layer frame yet, stash this frame.
if (layer_info_it == layer_info_.end())
@@ -308,12 +309,10 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp8(
// base layer frame.
if (codec_header.temporalIdx == 0) {
layer_info_it =
- layer_info_
- .insert(make_pair(codec_header.tl0PicIdx, layer_info_it->second))
- .first;
+ layer_info_.emplace(unwrapped_tl0, layer_info_it->second).first;
frame->num_references = 1;
frame->references[0] = layer_info_it->second[0];
- UpdateLayerInfoVp8(frame, codec_header);
+ UpdateLayerInfoVp8(frame, unwrapped_tl0, codec_header.temporalIdx);
return kHandOff;
}
@@ -322,7 +321,7 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp8(
frame->num_references = 1;
frame->references[0] = layer_info_it->second[0];
- UpdateLayerInfoVp8(frame, codec_header);
+ UpdateLayerInfoVp8(frame, unwrapped_tl0, codec_header.temporalIdx);
return kHandOff;
}
@@ -366,30 +365,28 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp8(
frame->references[layer] = layer_info_it->second[layer];
}
- UpdateLayerInfoVp8(frame, codec_header);
+ UpdateLayerInfoVp8(frame, unwrapped_tl0, codec_header.temporalIdx);
return kHandOff;
}
-void RtpFrameReferenceFinder::UpdateLayerInfoVp8(
- RtpFrameObject* frame,
- const RTPVideoHeaderVP8& codec_header) {
- uint8_t tl0_pic_idx = codec_header.tl0PicIdx;
- uint8_t temporal_index = codec_header.temporalIdx;
- auto layer_info_it = layer_info_.find(tl0_pic_idx);
+void RtpFrameReferenceFinder::UpdateLayerInfoVp8(RtpFrameObject* frame,
+ int64_t unwrapped_tl0,
+ uint8_t temporal_idx) {
+ auto layer_info_it = layer_info_.find(unwrapped_tl0);
// Update this layer info and newer.
while (layer_info_it != layer_info_.end()) {
- if (layer_info_it->second[temporal_index] != -1 &&
- AheadOf<uint16_t, kPicIdLength>(layer_info_it->second[temporal_index],
+ if (layer_info_it->second[temporal_idx] != -1 &&
+ AheadOf<uint16_t, kPicIdLength>(layer_info_it->second[temporal_idx],
frame->picture_id)) {
// The frame was not newer, then no subsequent layer info have to be
// update.
break;
}
- layer_info_it->second[codec_header.temporalIdx] = frame->picture_id;
- ++tl0_pic_idx;
- layer_info_it = layer_info_.find(tl0_pic_idx);
+ layer_info_it->second[temporal_idx] = frame->picture_id;
+ ++unwrapped_tl0;
+ layer_info_it = layer_info_.find(unwrapped_tl0);
}
not_yet_received_frames_.erase(frame->picture_id);
@@ -408,7 +405,8 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9(
const RTPVideoHeaderVP9& codec_header = rtp_codec_header->VP9;
if (codec_header.picture_id == kNoPictureId ||
- codec_header.temporal_idx == kNoTemporalIdx) {
+ codec_header.temporal_idx == kNoTemporalIdx ||
+ codec_header.tl0_pic_idx == kNoTl0PicIdx) {
return ManageFrameGeneric(std::move(frame), codec_header.picture_id);
}
@@ -433,6 +431,7 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9(
return kHandOff;
}
+ int64_t unwrapped_tl0 = tl0_unwrapper_.Unwrap(codec_header.tl0_pic_idx);
if (codec_header.ss_data_available) {
// Scalability structures can only be sent with tl0 frames.
if (codec_header.temporal_idx != 0) {
@@ -446,12 +445,12 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9(
GofInfo info(&scalability_structures_[current_ss_idx_],
frame->picture_id);
- gof_info_.insert(std::make_pair(codec_header.tl0_pic_idx, info));
+ gof_info_.insert(std::make_pair(unwrapped_tl0, info));
}
}
// Clean up info for base layers that are too old.
- uint8_t old_tl0_pic_idx = codec_header.tl0_pic_idx - kMaxGofSaved;
+ uint8_t old_tl0_pic_idx = unwrapped_tl0 - kMaxGofSaved;
auto clean_gof_info_to = gof_info_.lower_bound(old_tl0_pic_idx);
gof_info_.erase(gof_info_.begin(), clean_gof_info_to);
@@ -461,7 +460,7 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9(
RTC_LOG(LS_WARNING) << "Received keyframe without scalability structure";
frame->num_references = 0;
- auto gof_info_it = gof_info_.find(codec_header.tl0_pic_idx);
+ auto gof_info_it = gof_info_.find(unwrapped_tl0);
if (gof_info_it == gof_info_.end())
return kDrop;
@@ -473,8 +472,8 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9(
auto gof_info_it = gof_info_.find(
(codec_header.temporal_idx == 0 && !codec_header.ss_data_available)
- ? codec_header.tl0_pic_idx - 1
- : codec_header.tl0_pic_idx);
+ ? unwrapped_tl0 - 1
+ : unwrapped_tl0);
// Gof info for this frame is not available yet, stash this frame.
if (gof_info_it == gof_info_.end())
@@ -499,7 +498,7 @@ RtpFrameReferenceFinder::FrameDecision RtpFrameReferenceFinder::ManageFrameVp9(
// insert if we haven't done so already.
if (codec_header.temporal_idx == 0 && !codec_header.ss_data_available) {
GofInfo new_info(info->gof, frame->picture_id);
- gof_info_.insert(std::make_pair(codec_header.tl0_pic_idx, new_info));
+ gof_info_.insert(std::make_pair(unwrapped_tl0, new_info));
}
// Clean out old info about up switch frames.
diff --git a/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder.h b/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder.h
index 95da4f327e6..01c50544b22 100644
--- a/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder.h
+++ b/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder.h
@@ -100,7 +100,8 @@ class RtpFrameReferenceFinder {
// Updates necessary layer info state used to determine frame references for
// Vp8.
void UpdateLayerInfoVp8(RtpFrameObject* frame,
- const RTPVideoHeaderVP8& codec_header)
+ int64_t unwrapped_tl0,
+ uint8_t temporal_idx)
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
// Find references for Vp9 frames
@@ -181,11 +182,9 @@ class RtpFrameReferenceFinder {
RTC_GUARDED_BY(crit_);
// Holds the information about the last completed frame for a given temporal
- // layer given a Tl0 picture index.
- std::map<uint8_t,
- std::array<int16_t, kMaxTemporalLayers>,
- DescendingSeqNumComp<uint8_t>>
- layer_info_ RTC_GUARDED_BY(crit_);
+ // layer given an unwrapped Tl0 picture index.
+ std::map<int64_t, std::array<int16_t, kMaxTemporalLayers>> layer_info_
+ RTC_GUARDED_BY(crit_);
// Where the current scalability structure is in the
// |scalability_structures_| array.
@@ -195,9 +194,8 @@ class RtpFrameReferenceFinder {
std::array<GofInfoVP9, kMaxGofSaved> scalability_structures_
RTC_GUARDED_BY(crit_);
- // Holds the the Gof information for a given TL0 picture index.
- std::map<uint8_t, GofInfo, DescendingSeqNumComp<uint8_t>> gof_info_
- RTC_GUARDED_BY(crit_);
+ // Holds the the Gof information for a given unwrapped TL0 picture index.
+ std::map<int64_t, GofInfo> gof_info_ RTC_GUARDED_BY(crit_);
// Keep track of which picture id and which temporal layer that had the
// up switch flag set.
@@ -223,6 +221,8 @@ class RtpFrameReferenceFinder {
// Unwrapper used to unwrap VP8/VP9 streams which have their picture id
// specified.
SeqNumUnwrapper<uint16_t, kPicIdLength> unwrapper_ RTC_GUARDED_BY(crit_);
+
+ SeqNumUnwrapper<uint8_t> tl0_unwrapper_ RTC_GUARDED_BY(crit_);
};
} // namespace video_coding
diff --git a/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc b/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc
index 1eeb6cf88ec..c96a9f73dd9 100644
--- a/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc
+++ b/chromium/third_party/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc
@@ -1330,6 +1330,16 @@ TEST_F(TestRtpFrameReferenceFinder, Vp9GofPidJump) {
InsertVp9Gof(sn + 1, sn + 1, false, pid + 1000, 0, 0, 1);
}
+TEST_F(TestRtpFrameReferenceFinder, Vp9GofTl0Jump) {
+ uint16_t pid = Rand();
+ uint16_t sn = Rand();
+ GofInfoVP9 ss;
+ ss.SetGofInfoVP9(kTemporalStructureMode3);
+
+ InsertVp9Gof(sn, sn, true, pid + 0, 0, 0, 125, true, &ss);
+ InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 0, 0, false, &ss);
+}
+
TEST_F(TestRtpFrameReferenceFinder, Vp9GofTidTooHigh) {
// Same as RtpFrameReferenceFinder::kMaxTemporalLayers.
const int kMaxTemporalLayers = 5;