Compare commits

...

4 Commits

Author SHA1 Message Date
Yaowu Xu
669e7b7454 Prevent invalid read
This commit adds a check before reading into RefBuffer to prevent OOB
read.

BUG=https://bugs.chromium.org/p/chromium/issues/detail?id=612023

(cherry picked from commit 4f0e4d6cef827bc452848e126a6bedc47424da88)

Change-Id: I4f0732d4ca92f79b57103bffcff15499073e79a4
2016-07-18 11:29:59 -07:00
Johann
62a57630cc Promote to uint32_t before left shift
This commit change to promote uint8_t explicitly to uint32_t before
left shift operation.

BUG=https://bugs.chromium.org/p/chromium/issues/detail?id=612021

Change-Id: Id7059154efb5bdfa45889dabe72aaafd46d79f23
(cherry picked from commit 2240d83d7882ce2d5d0826b9ce33b86321d7a724)

Change-Id: I392d25c38353f071cf0e8ab242d32098a7d68ecb
2016-07-18 10:58:00 -07:00
Johann
240f8e56e4 vp9: Fix potential SEGV in decoder_peek_si_internal
decoder_peek_si_internal could potentially read more bytes than
what actually exists in the input buffer. We check for the buffer
size to be at least 8, but we try to read up to 10 bytes in the
worst case. A well crafted file could thus cause a segfault.
Likely change that introduced this bug was:
https://chromium-review.googlesource.com/#/c/70439 (git hash:
7c43fb6)

BUG=chromium:621095

(cherry picked from commit aa1c813c43c6b2e43036d5573f361924195d65b7)

Change-Id: Id74880cfdded44caaa45bbdbaac859c09d3db752
2016-06-28 16:40:03 -07:00
Yaowu Xu
3b3ee4a4db Prevent read to invalid RefBuffer
This commit adds check to validate RefBuffer before reading into the
data structure, to prevent invalid read.

BUG=https://bugs.chromium.org/p/chromium/issues/detail?id=614701

(cherry picked from commit 75b6cfe1c50e749a0edb5460a491ca5ac947aff5)

Change-Id: Ie111e95bd18e88fa19d8b25e097cdf52b7139cb6
2016-06-27 17:16:10 +00:00
4 changed files with 70 additions and 21 deletions

View File

@ -146,6 +146,40 @@ TEST(DecodeAPI, Vp9InvalidDecode) {
TestVp9Controls(&dec);
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
}
TEST(DecodeAPI, Vp9PeekSI) {
const vpx_codec_iface_t *const codec = &vpx_codec_vp9_dx_algo;
// The first 9 bytes are valid and the rest of the bytes are made up. Until
// size 10, this should return VPX_CODEC_UNSUP_BITSTREAM and after that it
// should return VPX_CODEC_CORRUPT_FRAME.
const uint8_t data[32] = {
0x85, 0xa4, 0xc1, 0xa1, 0x38, 0x81, 0xa3, 0x49,
0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
for (uint32_t data_sz = 1; data_sz <= 32; ++data_sz) {
// Verify behavior of vpx_codec_decode. vpx_codec_decode doesn't even get
// to decoder_peek_si_internal on frames of size < 8.
if (data_sz >= 8) {
vpx_codec_ctx_t dec;
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, NULL, 0));
EXPECT_EQ((data_sz < 10) ?
VPX_CODEC_UNSUP_BITSTREAM : VPX_CODEC_CORRUPT_FRAME,
vpx_codec_decode(&dec, data, data_sz, NULL, 0));
vpx_codec_iter_t iter = NULL;
EXPECT_EQ(NULL, vpx_codec_get_frame(&dec, &iter));
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
}
// Verify behavior of vpx_codec_peek_stream_info.
vpx_codec_stream_info_t si;
si.sz = sizeof(si);
EXPECT_EQ((data_sz < 10) ? VPX_CODEC_UNSUP_BITSTREAM : VPX_CODEC_OK,
vpx_codec_peek_stream_info(codec, data, data_sz, &si));
}
}
#endif // CONFIG_VP9_DECODER
} // namespace

View File

@ -1315,11 +1315,16 @@ static void setup_frame_size_with_refs(VP9_COMMON *cm,
BufferPool *const pool = cm->buffer_pool;
for (i = 0; i < REFS_PER_FRAME; ++i) {
if (vpx_rb_read_bit(rb)) {
if (cm->frame_refs[i].idx != INVALID_IDX) {
YV12_BUFFER_CONFIG *const buf = cm->frame_refs[i].buf;
width = buf->y_crop_width;
height = buf->y_crop_height;
found = 1;
break;
} else {
vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
"Failed to decode frame size");
}
}
}
@ -1334,17 +1339,18 @@ static void setup_frame_size_with_refs(VP9_COMMON *cm,
// has valid dimensions.
for (i = 0; i < REFS_PER_FRAME; ++i) {
RefBuffer *const ref_frame = &cm->frame_refs[i];
has_valid_ref_frame |= valid_ref_frame_size(ref_frame->buf->y_crop_width,
has_valid_ref_frame |= (ref_frame->idx != INVALID_IDX &&
valid_ref_frame_size(ref_frame->buf->y_crop_width,
ref_frame->buf->y_crop_height,
width, height);
width, height));
}
if (!has_valid_ref_frame)
vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
"Referenced frame has invalid size");
for (i = 0; i < REFS_PER_FRAME; ++i) {
RefBuffer *const ref_frame = &cm->frame_refs[i];
if (!valid_ref_frame_img_fmt(
ref_frame->buf->bit_depth,
if (ref_frame->idx == INVALID_IDX ||
!valid_ref_frame_img_fmt(ref_frame->buf->bit_depth,
ref_frame->buf->subsampling_x,
ref_frame->buf->subsampling_y,
cm->bit_depth,

View File

@ -508,7 +508,7 @@ vpx_codec_err_t vp9_parse_superframe_index(const uint8_t *data,
uint32_t this_sz = 0;
for (j = 0; j < mag; ++j)
this_sz |= (*x++) << (j * 8);
this_sz |= ((uint32_t)(*x++)) << (j * 8);
sizes[i] = this_sz;
}
*count = frames;

View File

@ -127,7 +127,7 @@ static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
vpx_decrypt_cb decrypt_cb,
void *decrypt_state) {
int intra_only_flag = 0;
uint8_t clear_buffer[9];
uint8_t clear_buffer[10];
if (data + data_sz <= data)
return VPX_CODEC_INVALID_PARAM;
@ -141,6 +141,11 @@ static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
data = clear_buffer;
}
// A maximum of 6 bits are needed to read the frame marker, profile and
// show_existing_frame.
if (data_sz < 1)
return VPX_CODEC_UNSUP_BITSTREAM;
{
int show_frame;
int error_resilient;
@ -154,15 +159,19 @@ static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
if (profile >= MAX_PROFILES)
return VPX_CODEC_UNSUP_BITSTREAM;
if ((profile >= 2 && data_sz <= 1) || data_sz < 1)
return VPX_CODEC_UNSUP_BITSTREAM;
if (vpx_rb_read_bit(&rb)) { // show an existing frame
// If profile is > 2 and show_existing_frame is true, then at least 1 more
// byte (6+3=9 bits) is needed.
if (profile > 2 && data_sz < 2)
return VPX_CODEC_UNSUP_BITSTREAM;
vpx_rb_read_literal(&rb, 3); // Frame buffer to show.
return VPX_CODEC_OK;
}
if (data_sz <= 8)
// For the rest of the function, a maximum of 9 more bytes are needed
// (computed by taking the maximum possible bits needed in each case). Note
// that this has to be updated if we read any more bits in this function.
if (data_sz < 10)
return VPX_CODEC_UNSUP_BITSTREAM;
si->is_kf = !vpx_rb_read_bit(&rb);