diff options
author | Michael Niedermayer <michael@niedermayer.cc> | 2019-04-24 21:14:19 +0200 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2019-04-27 22:36:46 +0200 |
commit | 9fc1031ac2e8691e0140854d727b58cb62431b2b (patch) | |
tree | 703d7632f7574c11da630ed8f92e21acdb3cf296 /libavcodec | |
parent | 938cb783d40ad5ee40f4e2be8617fdfb493dbe4d (diff) | |
download | ffmpeg-9fc1031ac2e8691e0140854d727b58cb62431b2b.tar.gz |
avcodec/pnm_parser: Remember the size of the image and do not reparse the header
Fixes: Timeout (11sec -> 60ms)
Fixes: 14270/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_PAM_fuzzer-5734809634078720
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/pnm_parser.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/libavcodec/pnm_parser.c b/libavcodec/pnm_parser.c index 95241c30b3..210a8a048e 100644 --- a/libavcodec/pnm_parser.c +++ b/libavcodec/pnm_parser.c @@ -24,19 +24,35 @@ #include "parser.h" //for ParseContext #include "pnm.h" +typedef struct PNMParseContext { + ParseContext pc; + int remaining_bytes; +}PNMParseContext; static int pnm_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size) { - ParseContext *pc = s->priv_data; + PNMParseContext *pnmpc = s->priv_data; + ParseContext *pc = &pnmpc->pc; PNMContext pnmctx; - int next; + int next = END_NOT_FOUND; int skip = 0; for (; pc->overread > 0; pc->overread--) { pc->buffer[pc->index++]= pc->buffer[pc->overread_index++]; } + + if (pnmpc->remaining_bytes) { + int inc = FFMIN(pnmpc->remaining_bytes, buf_size); + skip += inc; + pnmpc->remaining_bytes -= inc; + + if (!pnmpc->remaining_bytes) + next = skip; + goto end; + } + retry: if (pc->index) { pnmctx.bytestream_start = @@ -47,7 +63,6 @@ retry: pnmctx.bytestream = (uint8_t *) buf + skip; /* casts avoid warnings */ pnmctx.bytestream_end = (uint8_t *) buf + buf_size - skip; } - next = END_NOT_FOUND; if (ff_pnm_decode_header(avctx, &pnmctx) < 0) { if (pnmctx.bytestream < pnmctx.bytestream_end) { if (pc->index) { @@ -79,9 +94,11 @@ retry: } if (next != END_NOT_FOUND && pnmctx.bytestream_start != buf + skip) next -= pc->index; - if (next > buf_size) + if (next > buf_size) { + pnmpc->remaining_bytes = next - buf_size; next = END_NOT_FOUND; - + } +end: if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { *poutbuf = NULL; *poutbuf_size = 0; @@ -95,7 +112,7 @@ retry: AVCodecParser ff_pnm_parser = { .codec_ids = { AV_CODEC_ID_PGM, AV_CODEC_ID_PGMYUV, AV_CODEC_ID_PPM, AV_CODEC_ID_PBM, AV_CODEC_ID_PAM }, - .priv_data_size = sizeof(ParseContext), + .priv_data_size = sizeof(PNMParseContext), .parser_parse = pnm_parse, .parser_close = ff_parse_close, }; |