diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-10-13 02:08:59 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-10-13 02:08:59 +0200 |
commit | 120b38b966b92a50dd36542190d35daba6730eb3 (patch) | |
tree | fb15eec67c53a41ae42e2b6bbd15a3f18932e64a | |
parent | 54b2d317ed99622efa07b10aca217e1a083105d9 (diff) | |
download | ffmpeg-120b38b966b92a50dd36542190d35daba6730eb3.tar.gz |
avio: redesign ffio_rewind_with_probe_data()
This prevents a double free
Fixes CID718285
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavformat/avio_internal.h | 2 | ||||
-rw-r--r-- | libavformat/aviobuf.c | 13 | ||||
-rw-r--r-- | libavformat/utils.c | 3 |
3 files changed, 11 insertions, 7 deletions
diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index df614b22d9..3c0fc93b3c 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -64,7 +64,7 @@ static av_always_inline void ffio_wfourcc(AVIOContext *pb, const uint8_t *s) * @return 0 in case of success, a negative value corresponding to an * AVERROR code in case of failure */ -int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size); +int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char **buf, int buf_size); uint64_t ffio_read_varlen(AVIOContext *bc); diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index dc09a071fc..6e060ba27c 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -726,27 +726,32 @@ static int url_resetbuf(AVIOContext *s, int flags) return 0; } -int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char *buf, int buf_size) +int ffio_rewind_with_probe_data(AVIOContext *s, unsigned char **bufp, int buf_size) { int64_t buffer_start; int buffer_size; int overlap, new_size, alloc_size; + uint8_t *buf = *bufp; - if (s->write_flag) + if (s->write_flag) { + av_freep(bufp); return AVERROR(EINVAL); + } buffer_size = s->buf_end - s->buffer; /* the buffers must touch or overlap */ - if ((buffer_start = s->pos - buffer_size) > buf_size) + if ((buffer_start = s->pos - buffer_size) > buf_size) { + av_freep(bufp); return AVERROR(EINVAL); + } overlap = buf_size - buffer_start; new_size = buf_size + buffer_size - overlap; alloc_size = FFMAX(s->buffer_size, new_size); if (alloc_size > buf_size) - if (!(buf = av_realloc_f(buf, 1, alloc_size))) + if (!(buf = (*bufp) = av_realloc_f(buf, 1, alloc_size))) return AVERROR(ENOMEM); if (new_size > buf_size) { diff --git a/libavformat/utils.c b/libavformat/utils.c index 13a2f2b839..745dcaa8d0 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -470,8 +470,7 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, } /* rewind. reuse probe buffer to avoid seeking */ - if ((ret = ffio_rewind_with_probe_data(pb, buf, pd.buf_size)) < 0) - av_free(buf); + ret = ffio_rewind_with_probe_data(pb, &buf, pd.buf_size); return ret; } |