summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVignesh Venkatasubramanian <vigneshv@google.com>2016-06-23 21:33:12 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2016-06-23 21:33:13 +0000
commit692fe74debda99307db9c64fe7d9a4ea2cf7f95c (patch)
treee09868f8e7dbbc3e15aebfbcf0ca146e58f00a76
parentbdeb5febe43f8706a7c440d4ef696849a17ea71e (diff)
parentaa1c813c43c6b2e43036d5573f361924195d65b7 (diff)
downloadlibvpx-692fe74debda99307db9c64fe7d9a4ea2cf7f95c.tar
libvpx-692fe74debda99307db9c64fe7d9a4ea2cf7f95c.tar.gz
libvpx-692fe74debda99307db9c64fe7d9a4ea2cf7f95c.tar.bz2
libvpx-692fe74debda99307db9c64fe7d9a4ea2cf7f95c.zip
Merge "vp9: Fix potential SEGV in decoder_peek_si_internal"
-rw-r--r--test/decode_api_test.cc34
-rw-r--r--vp9/vp9_dx_iface.c19
2 files changed, 48 insertions, 5 deletions
diff --git a/test/decode_api_test.cc b/test/decode_api_test.cc
index c10a44a33..99b4db10f 100644
--- a/test/decode_api_test.cc
+++ b/test/decode_api_test.cc
@@ -143,6 +143,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
diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c
index be5d1600a..6531e2c61 100644
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -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);