Fix integer underflow in H264 bitstream parser
num_ref are represented using golomb and may be very large. BitstreamReader is generally resilent to many consenquites fail reads, but not when number of reads comparable to int limit. This change address the issue in two ways, either one is enough, but both are helpful in their own way: H264 parser now fails faster when number of references is too large. BitstreamReader now is resilent to unlimited number of fail reads. Bug: chromium:352402499 Change-Id: I19646bc3f53cd2970393d00bc143400b1fdf5473 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/357100 Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42628}
This commit is contained in:
parent
4643fb7e01
commit
cd8b36bb9f
@ -120,9 +120,15 @@ H264BitstreamParser::Result H264BitstreamParser::ParseNonParameterSetNalu(
|
||||
if (slice_reader.Read<bool>()) {
|
||||
// num_ref_idx_l0_active_minus1: ue(v)
|
||||
num_ref_idx_l0_active_minus1 = slice_reader.ReadExponentialGolomb();
|
||||
if (num_ref_idx_l0_active_minus1 > H264::kMaxReferenceIndex) {
|
||||
return kInvalidStream;
|
||||
}
|
||||
if (slice_type == H264::SliceType::kB) {
|
||||
// num_ref_idx_l1_active_minus1: ue(v)
|
||||
num_ref_idx_l1_active_minus1 = slice_reader.ReadExponentialGolomb();
|
||||
if (num_ref_idx_l1_active_minus1 > H264::kMaxReferenceIndex) {
|
||||
return kInvalidStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -33,6 +33,9 @@ const size_t kNaluShortStartSequenceSize = 3;
|
||||
// The size of the NALU type byte (1).
|
||||
const size_t kNaluTypeSize = 1;
|
||||
|
||||
// Maximum reference index for reference pictures.
|
||||
constexpr int kMaxReferenceIndex = 31;
|
||||
|
||||
enum NaluType : uint8_t {
|
||||
kSlice = 1,
|
||||
kIdr = 5,
|
||||
|
||||
@ -134,6 +134,10 @@ absl::optional<PpsParser::PpsState> PpsParser::ParseInternal(
|
||||
pps.num_ref_idx_l0_default_active_minus1 = reader.ReadExponentialGolomb();
|
||||
// num_ref_idx_l1_default_active_minus1: ue(v)
|
||||
pps.num_ref_idx_l1_default_active_minus1 = reader.ReadExponentialGolomb();
|
||||
if (pps.num_ref_idx_l0_default_active_minus1 > H264::kMaxReferenceIndex ||
|
||||
pps.num_ref_idx_l1_default_active_minus1 > H264::kMaxReferenceIndex) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
// weighted_pred_flag: u(1)
|
||||
pps.weighted_pred_flag = reader.Read<bool>();
|
||||
// weighted_bipred_idc: u(2)
|
||||
|
||||
@ -26,7 +26,7 @@ uint64_t BitstreamReader::ReadBits(int bits) {
|
||||
set_last_read_is_verified(false);
|
||||
|
||||
if (remaining_bits_ < bits) {
|
||||
remaining_bits_ -= bits;
|
||||
Invalidate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -64,10 +64,11 @@ uint64_t BitstreamReader::ReadBits(int bits) {
|
||||
|
||||
int BitstreamReader::ReadBit() {
|
||||
set_last_read_is_verified(false);
|
||||
--remaining_bits_;
|
||||
if (remaining_bits_ < 0) {
|
||||
if (remaining_bits_ <= 0) {
|
||||
Invalidate();
|
||||
return 0;
|
||||
}
|
||||
--remaining_bits_;
|
||||
|
||||
int bit_position = remaining_bits_ % 8;
|
||||
if (bit_position == 0) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user