Fix potential slice header size off by one byte in H265
In H265Parser::ParseSliceHeader, the parser does not handle byte_alignment() from the spec. byte_alignment() reportedly contains at least one bit, which is not handled right now. See Section 7.3.2.12 Rec. ITU-T H.265 v3 (04/2015). Also added a few size sanity checks in H265Parser to make sure the code does not crash if an invalid input is provided. Fixes #383. Change-Id: I33b31396058fc5ba67a0fc119be5fe56ec9443b0
This commit is contained in:
parent
764c7077a2
commit
8767d20f38
Binary file not shown.
|
@ -236,6 +236,8 @@ H265Parser::Result H265Parser::ParseSliceHeader(const Nalu& nalu,
|
|||
TRUE_OR_RETURN(
|
||||
br->ReadBits(ceil(log2(sps->num_short_term_ref_pic_sets)),
|
||||
&slice_header->short_term_ref_pic_set_idx));
|
||||
TRUE_OR_RETURN(slice_header->short_term_ref_pic_set_idx <
|
||||
sps->num_short_term_ref_pic_sets);
|
||||
}
|
||||
|
||||
if (sps->long_term_ref_pic_present_flag) {
|
||||
|
@ -390,6 +392,8 @@ H265Parser::Result H265Parser::ParseSliceHeader(const Nalu& nalu,
|
|||
TRUE_OR_RETURN(br->SkipBits(extension_length * 8));
|
||||
}
|
||||
|
||||
OK_OR_RETURN(ByteAlignment(br));
|
||||
|
||||
slice_header->header_bit_size = nalu.payload_size() * 8 - br->NumBitsLeft();
|
||||
return kOk;
|
||||
}
|
||||
|
@ -832,7 +836,9 @@ H265Parser::Result H265Parser::ParseReferencePictureSet(
|
|||
}
|
||||
} else {
|
||||
TRUE_OR_RETURN(br->ReadUE(&out_ref_pic_set->num_negative_pics));
|
||||
TRUE_OR_RETURN(out_ref_pic_set->num_negative_pics <= kMaxRefPicSetCount);
|
||||
TRUE_OR_RETURN(br->ReadUE(&out_ref_pic_set->num_positive_pics));
|
||||
TRUE_OR_RETURN(out_ref_pic_set->num_positive_pics <= kMaxRefPicSetCount);
|
||||
|
||||
int prev_poc = 0;
|
||||
for (int i = 0; i < out_ref_pic_set->num_negative_pics; i++) {
|
||||
|
@ -1107,5 +1113,11 @@ H265Parser::Result H265Parser::SkipSubLayerHrdParameters(
|
|||
return kOk;
|
||||
}
|
||||
|
||||
H265Parser::Result H265Parser::ByteAlignment(H26xBitReader* br) {
|
||||
TRUE_OR_RETURN(br->SkipBits(1));
|
||||
TRUE_OR_RETURN(br->SkipBits(br->NumBitsLeft() % 8));
|
||||
return kOk;
|
||||
}
|
||||
|
||||
} // namespace media
|
||||
} // namespace shaka
|
||||
|
|
|
@ -351,6 +351,8 @@ class H265Parser {
|
|||
bool sub_pic_hdr_params_present_flag,
|
||||
H26xBitReader* br);
|
||||
|
||||
Result ByteAlignment(H26xBitReader* br);
|
||||
|
||||
typedef std::map<int, std::unique_ptr<H265Sps>> SpsById;
|
||||
typedef std::map<int, std::unique_ptr<H265Pps>> PpsById;
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ TEST(H265ParserTest, ParseSliceHeader) {
|
|||
EXPECT_EQ(8, header.slice_qp_delta);
|
||||
EXPECT_FALSE(header.cu_chroma_qp_offset_enabled_flag);
|
||||
EXPECT_EQ(5, header.num_entry_point_offsets);
|
||||
EXPECT_EQ(85u, header.header_bit_size);
|
||||
EXPECT_EQ(88u, header.header_bit_size);
|
||||
}
|
||||
|
||||
TEST(H265ParserTest, ParseSliceHeader_NonIDR) {
|
||||
|
@ -81,7 +81,7 @@ TEST(H265ParserTest, ParseSliceHeader_NonIDR) {
|
|||
EXPECT_FALSE(header.dependent_slice_segment_flag);
|
||||
EXPECT_EQ(1, header.slice_type);
|
||||
EXPECT_EQ(5, header.num_entry_point_offsets);
|
||||
EXPECT_EQ(124u, header.header_bit_size);
|
||||
EXPECT_EQ(128u, header.header_bit_size);
|
||||
}
|
||||
|
||||
TEST(H265ParserTest, ParseSps) {
|
||||
|
|
|
@ -95,6 +95,8 @@ TEST(H26xBitReaderTest, SkipBits) {
|
|||
EXPECT_EQ(0x15, dummy);
|
||||
EXPECT_EQ(4, reader.NumBitsLeft());
|
||||
EXPECT_FALSE(reader.SkipBits(5));
|
||||
EXPECT_TRUE(reader.SkipBits(0));
|
||||
EXPECT_EQ(4, reader.NumBitsLeft());
|
||||
}
|
||||
|
||||
TEST(H26xBitReaderTest, StopBitOccupyFullByte) {
|
||||
|
|
Loading…
Reference in New Issue