aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michael@niedermayer.cc>2018-04-17 02:13:42 +0200
committerMichael Niedermayer <michael@niedermayer.cc>2018-04-19 22:59:40 +0200
commit2324ef1ff32e5effd6f295bca80580ae4816be0b (patch)
tree4789802b905ddd70e412108862bbb54e40fde0d2
parentc705476c4788ab7c5e4c4ee00aab9bbc038cf700 (diff)
downloadffmpeg-2324ef1ff32e5effd6f295bca80580ae4816be0b.tar.gz
avcodec/cinepak: move some checks prior to frame allocation
Speeds up decoding from 8 to 3 seconds for 6302/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CINEPAK_fuzzer-5626371985375232 Fixes: Timeout Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r--libavcodec/cinepak.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c
index 89e940ae0d..ba0589582f 100644
--- a/libavcodec/cinepak.c
+++ b/libavcodec/cinepak.c
@@ -315,14 +315,11 @@ static int cinepak_decode_strip (CinepakContext *s,
return AVERROR_INVALIDDATA;
}
-static int cinepak_decode (CinepakContext *s)
+static int cinepak_predecode_check (CinepakContext *s)
{
- const uint8_t *eod = (s->data + s->size);
- int i, result, strip_size, frame_flags, num_strips;
- int y0 = 0;
+ int num_strips;
int encoded_buf_size;
- frame_flags = s->data[0];
num_strips = AV_RB16 (&s->data[8]);
encoded_buf_size = AV_RB24(&s->data[1]);
@@ -353,6 +350,21 @@ static int cinepak_decode (CinepakContext *s)
s->sega_film_skip_bytes = 0;
}
+ if (s->size < 10 + s->sega_film_skip_bytes + num_strips * 12)
+ return AVERROR_INVALIDDATA;
+
+ return 0;
+}
+
+static int cinepak_decode (CinepakContext *s)
+{
+ const uint8_t *eod = (s->data + s->size);
+ int i, result, strip_size, frame_flags, num_strips;
+ int y0 = 0;
+
+ frame_flags = s->data[0];
+ num_strips = AV_RB16 (&s->data[8]);
+
s->data += 10 + s->sega_film_skip_bytes;
num_strips = FFMIN(num_strips, MAX_STRIPS);
@@ -439,6 +451,11 @@ static int cinepak_decode_frame(AVCodecContext *avctx,
if (s->size < 10)
return AVERROR_INVALIDDATA;
+ if ((ret = cinepak_predecode_check(s)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "cinepak_predecode_check failed\n");
+ return ret;
+ }
+
if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
return ret;