From 7d9da93a973d53c65db8f174b2a70297a9d2a49f Mon Sep 17 00:00:00 2001 From: James Zern <jzern@google.com> Date: Sat, 9 Aug 2014 18:47:58 -0700 Subject: [PATCH] VP8D_GET_FRAME_CORRUPTED: check frame pointer if the decode of the first frame fails, frame_to_show may not be set. fixes a crash in vpxdec with corrupt data. Change-Id: I5ab9476d005778a13fd42a39d05876bb6c90a93c --- test/decode_api_test.cc | 49 +++++++++++++++++++++++++++++++++++++++++ vp8/vp8_dx_iface.c | 5 +++-- vp9/vp9_dx_iface.c | 9 ++++---- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/test/decode_api_test.cc b/test/decode_api_test.cc index 86097cd2ad..06790645f8 100644 --- a/test/decode_api_test.cc +++ b/test/decode_api_test.cc @@ -9,6 +9,7 @@ */ #include "third_party/googletest/src/include/gtest/gtest.h" +#include "test/ivf_video_source.h" #include "./vpx_config.h" #include "vpx/vp8dx.h" #include "vpx/vpx_decoder.h" @@ -56,4 +57,52 @@ TEST(DecodeAPI, InvalidParams) { } } +#if CONFIG_VP9_DECODER +// Test VP9 codec controls after a decode error to ensure the code doesn't +// misbehave. +void TestVp9Controls(vpx_codec_ctx_t *dec) { + static const int kControls[] = { + VP8D_GET_LAST_REF_UPDATES, + VP8D_GET_FRAME_CORRUPTED, + VP9D_GET_DISPLAY_SIZE, + }; + int val[2]; + + for (int i = 0; i < NELEMENTS(kControls); ++i) { + const vpx_codec_err_t res = vpx_codec_control_(dec, kControls[i], val); + switch (kControls[i]) { + case VP8D_GET_FRAME_CORRUPTED: + EXPECT_EQ(VPX_CODEC_ERROR, res) << kControls[i]; + break; + default: + EXPECT_EQ(VPX_CODEC_OK, res) << kControls[i]; + break; + } + EXPECT_EQ(VPX_CODEC_INVALID_PARAM, + vpx_codec_control_(dec, kControls[i], NULL)); + } +} + +TEST(DecodeAPI, Vp9InvalidDecode) { + const vpx_codec_iface_t *const codec = &vpx_codec_vp9_dx_algo; + const char filename[] = + "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf"; + libvpx_test::IVFVideoSource video(filename); + video.Init(); + video.Begin(); + ASSERT_TRUE(!HasFailure()); + + vpx_codec_ctx_t dec; + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, NULL, 0)); + EXPECT_EQ(VPX_CODEC_MEM_ERROR, + vpx_codec_decode(&dec, video.cxdata(), video.frame_size(), NULL, + 0)); + vpx_codec_iter_t iter = NULL; + EXPECT_EQ(NULL, vpx_codec_get_frame(&dec, &iter)); + + TestVp9Controls(&dec); + EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec)); +} +#endif // CONFIG_VP9_DECODER + } // namespace diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c index 0fe0c921fd..9a0cdb79a6 100644 --- a/vp8/vp8_dx_iface.c +++ b/vp8/vp8_dx_iface.c @@ -746,8 +746,9 @@ static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, if (corrupted && pbi) { - *corrupted = pbi->common.frame_to_show->corrupted; - + const YV12_BUFFER_CONFIG *const frame = pbi->common.frame_to_show; + if (frame == NULL) return VPX_CODEC_ERROR; + *corrupted = frame->corrupted; return VPX_CODEC_OK; } else diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index bc7801152e..4372ac9e5e 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -639,11 +639,10 @@ static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, va_list args) { int *corrupted = va_arg(args, int *); - if (corrupted) { - if (ctx->pbi) - *corrupted = ctx->pbi->common.frame_to_show->corrupted; - else - return VPX_CODEC_ERROR; + if (corrupted != NULL && ctx->pbi != NULL) { + const YV12_BUFFER_CONFIG *const frame = ctx->pbi->common.frame_to_show; + if (frame == NULL) return VPX_CODEC_ERROR; + *corrupted = frame->corrupted; return VPX_CODEC_OK; } else { return VPX_CODEC_INVALID_PARAM; -- GitLab