Sanity check parsed QP values from H264 bitstream

BUG=chromium:663610

Review-Url: https://codereview.webrtc.org/2532973002
Cr-Commit-Position: refs/heads/master@{#15377}
This commit is contained in:
kthelgason 2016-12-02 01:29:48 -08:00 committed by Commit bot
parent 864f58b751
commit b336392562
3 changed files with 30 additions and 3 deletions

View File

@ -19,6 +19,12 @@
#include "webrtc/common_video/h264/h264_common.h"
#include "webrtc/base/logging.h"
namespace {
const int kMaxAbsQpDeltaValue = 51;
const int kMinQpValue = 0;
const int kMaxQpValue = 51;
}
namespace webrtc {
#define RETURN_ON_FAIL(x, res) \
@ -251,6 +257,12 @@ H264BitstreamParser::Result H264BitstreamParser::ParseNonParameterSetNalu(
int32_t last_slice_qp_delta;
RETURN_INV_ON_FAIL(
slice_reader.ReadSignedExponentialGolomb(&last_slice_qp_delta));
if (abs(last_slice_qp_delta) > kMaxAbsQpDeltaValue) {
// Something has gone wrong, and the parsed value is invalid.
LOG(LS_WARNING) << "Parsed QP value out of range.";
return kInvalidStream;
}
last_slice_qp_delta_ = rtc::Optional<int32_t>(last_slice_qp_delta);
return kOk;
}
@ -291,7 +303,12 @@ void H264BitstreamParser::ParseBitstream(const uint8_t* bitstream,
bool H264BitstreamParser::GetLastSliceQp(int* qp) const {
if (!last_slice_qp_delta_ || !pps_)
return false;
*qp = 26 + pps_->pic_init_qp_minus26 + *last_slice_qp_delta_;
const int parsed_qp = 26 + pps_->pic_init_qp_minus26 + *last_slice_qp_delta_;
if (parsed_qp < kMinQpValue || parsed_qp > kMaxQpValue) {
LOG(LS_ERROR) << "Parsed invalid QP from bitstream.";
return false;
}
*qp = parsed_qp;
return true;
}

View File

@ -22,6 +22,11 @@
return rtc::Optional<PpsParser::PpsState>(); \
}
namespace {
const int kMaxPicInitQpDeltaValue = 25;
const int kMinPicInitQpDeltaValue = -26;
}
namespace webrtc {
// General note: this is based off the 02/2014 version of the H.264 standard.
@ -162,6 +167,11 @@ rtc::Optional<PpsParser::PpsState> PpsParser::ParseInternal(
// pic_init_qp_minus26: se(v)
RETURN_EMPTY_ON_FAIL(
bit_buffer->ReadSignedExponentialGolomb(&pps.pic_init_qp_minus26));
// Sanity-check parsed value
if (pps.pic_init_qp_minus26 > kMaxPicInitQpDeltaValue ||
pps.pic_init_qp_minus26 < kMinPicInitQpDeltaValue) {
RETURN_EMPTY_ON_FAIL(false);
}
// pic_init_qs_minus26: se(v)
RETURN_EMPTY_ON_FAIL(bit_buffer->ReadExponentialGolomb(&golomb_ignored));
// chroma_qp_index_offset: se(v)

View File

@ -201,7 +201,7 @@ TEST_F(PpsParserTest, ZeroPps) {
TEST_F(PpsParserTest, MaxPps) {
generated_pps_.bottom_field_pic_order_in_frame_present_flag = true;
generated_pps_.pic_init_qp_minus26 = std::numeric_limits<int32_t>::max();
generated_pps_.pic_init_qp_minus26 = 25;
generated_pps_.redundant_pic_cnt_present_flag = 1; // 1 bit value.
generated_pps_.weighted_bipred_idc = (1 << 2) - 1; // 2 bit value.
generated_pps_.weighted_pred_flag = true;
@ -210,7 +210,7 @@ TEST_F(PpsParserTest, MaxPps) {
generated_pps_.sps_id = 1;
RunTest();
generated_pps_.pic_init_qp_minus26 = std::numeric_limits<int32_t>::min() + 1;
generated_pps_.pic_init_qp_minus26 = -25;
RunTest();
}