aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec
diff options
context:
space:
mode:
authorwm4 <nfxjfg@googlemail.com>2015-01-08 17:19:17 +0100
committerMichael Niedermayer <michaelni@gmx.at>2015-01-09 17:18:41 +0100
commit3b4e9dddcff61eaf01a9a5b63c1abcc4102a313a (patch)
tree9b4eea5a9a08af3464a5dfb551cfc5b473cf2042 /libavcodec
parent2ba1af5791fc405ad648851344fe6dd83d1c92c1 (diff)
downloadffmpeg-3b4e9dddcff61eaf01a9a5b63c1abcc4102a313a.tar.gz
avcodec/dvdsubdec: fix accessing dangling pointers
dvdsub_decode() can call append_to_cached_buf() 2 times, the second time with ctx->buf as argument. If the second append_to_cached_buf() reallocs ctx->buf, the argument will be a pointer to the previous, freed block. This can cause invalid reads at least with some fuzzed files - and possibly with valid files. Since packets can apparently not be larger than 64K (even if packets are combined), just use a fixed size buffer. It will be allocated as part of the DVDSubContext, and although some memory is "wasted", it's relatively minimal by modern standards and should be acceptable. Signed-off-by: Michael Niedermayer <michaelni@gmx.at> (cherry picked from commit 816577716bc6170bccfea3b9e865618b69a4b426) Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/dvdsubdec.c12
1 files changed, 3 insertions, 9 deletions
diff --git a/libavcodec/dvdsubdec.c b/libavcodec/dvdsubdec.c
index 28027c233e..54dd2c4f90 100644
--- a/libavcodec/dvdsubdec.c
+++ b/libavcodec/dvdsubdec.c
@@ -37,7 +37,7 @@ typedef struct DVDSubContext
int has_palette;
uint8_t colormap[4];
uint8_t alpha[256];
- uint8_t *buf;
+ uint8_t buf[0x10000];
int buf_size;
#ifdef DEBUG
int sub_id;
@@ -506,15 +506,11 @@ static int append_to_cached_buf(AVCodecContext *avctx,
{
DVDSubContext *ctx = avctx->priv_data;
- if (ctx->buf_size > 0xffff - buf_size) {
+ if (ctx->buf_size >= sizeof(ctx->buf) - buf_size) {
av_log(avctx, AV_LOG_WARNING, "Attempt to reconstruct "
"too large SPU packets aborted.\n");
- av_freep(&ctx->buf);
return AVERROR_INVALIDDATA;
}
- ctx->buf = av_realloc(ctx->buf, ctx->buf_size + buf_size);
- if (!ctx->buf)
- return AVERROR(ENOMEM);
memcpy(ctx->buf + ctx->buf_size, buf, buf_size);
ctx->buf_size += buf_size;
return 0;
@@ -530,7 +526,7 @@ static int dvdsub_decode(AVCodecContext *avctx,
AVSubtitle *sub = data;
int is_menu;
- if (ctx->buf) {
+ if (ctx->buf_size) {
int ret = append_to_cached_buf(avctx, buf, buf_size);
if (ret < 0) {
*data_size = 0;
@@ -569,7 +565,6 @@ static int dvdsub_decode(AVCodecContext *avctx,
}
#endif
- av_freep(&ctx->buf);
ctx->buf_size = 0;
*data_size = 1;
return buf_size;
@@ -651,7 +646,6 @@ static av_cold int dvdsub_init(AVCodecContext *avctx)
static av_cold int dvdsub_close(AVCodecContext *avctx)
{
DVDSubContext *ctx = avctx->priv_data;
- av_freep(&ctx->buf);
ctx->buf_size = 0;
return 0;
}