[FFmpeg-cvslog] lavf: sanity check size in av_get/append_packet().

Reimar Döffinger Reimar.Doeffinger at gmx.de
Sat Mar 16 18:15:16 CET 2013


Hello,
I don't really like that arbitrary, non-configurable limit at all.
We already have a configurable, user-settable allocation limit for the av_malloc etc. functions in libavutil, isn't that good enough?

Reimar

On 16 Mar 2013, at 15:48, git at videolan.org (Anton Khirnov) wrote:

> ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Tue Feb 19 17:20:35 2013 +0100| [aa3c77998404cc32233cb76e961ca27db8565459] | committer: Anton Khirnov
> 
> lavf: sanity check size in av_get/append_packet().
> 
> To avoid allocating ridiculous amounts of memory for corrupted files,
> read the input in chunks limited to filesize or an arbitrary large
> amount when that is not known (chosen to be 50M).
> 
>> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=aa3c77998404cc32233cb76e961ca27db8565459
> ---
> 
> libavformat/utils.c |   68 +++++++++++++++++++++++++++++++++++++--------------
> 1 file changed, 49 insertions(+), 19 deletions(-)
> 
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> index 75e92ae..284d992 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -214,38 +214,68 @@ AVInputFormat *av_find_input_format(const char *short_name)
>     return NULL;
> }
> 
> +/* an arbitrarily chosen "sane" max packet size -- 50M */
> +#define SANE_CHUNK_SIZE (50000000)
> 
> -int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
> +/*
> + * Read the data in sane-sized chunks and append to pkt.
> + * Return the number of bytes read or an error.
> + */
> +static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
> {
> -    int ret= av_new_packet(pkt, size);
> +    int64_t chunk_size = size;
> +    int orig_pos       = pkt->pos; // av_grow_packet might reset pos
> +    int orig_size      = pkt->size;
> +    int ret = 0;
> 
> -    if(ret<0)
> -        return ret;
> +    do {
> +        int prev_size = pkt->size;
> +        int read_size;
> +
> +        /*
> +         * When the caller requests a lot of data, limit it to the amount left
> +         * in file or SANE_CHUNK_SIZE when it is not known
> +         */
> +        if (size > SANE_CHUNK_SIZE) {
> +            int64_t filesize = avio_size(s) - avio_tell(s);
> +            chunk_size = FFMAX(filesize, SANE_CHUNK_SIZE);
> +        }
> +        read_size = FFMIN(size, chunk_size);
> +
> +        ret = av_grow_packet(pkt, read_size);
> +        if (ret < 0)
> +            break;
> +
> +        ret = avio_read(s, pkt->data + prev_size, read_size);
> +        if (ret != read_size) {
> +            av_shrink_packet(pkt, prev_size + FFMAX(ret, 0));
> +            break;
> +        }
> 
> -    pkt->pos= avio_tell(s);
> +        size -= read_size;
> +    } while (size > 0);
> 
> -    ret= avio_read(s, pkt->data, size);
> -    if(ret<=0)
> +    pkt->pos = orig_pos;
> +    if (!pkt->size)
>         av_free_packet(pkt);
> -    else
> -        av_shrink_packet(pkt, ret);
> +    return pkt->size > orig_size ? pkt->size - orig_size : ret;
> +}
> 
> -    return ret;
> +int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
> +{
> +    av_init_packet(pkt);
> +    pkt->data = NULL;
> +    pkt->size = 0;
> +    pkt->pos  = avio_tell(s);
> +
> +    return append_packet_chunked(s, pkt, size);
> }
> 
> int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)
> {
> -    int ret;
> -    int old_size;
>     if (!pkt->size)
>         return av_get_packet(s, pkt, size);
> -    old_size = pkt->size;
> -    ret = av_grow_packet(pkt, size);
> -    if (ret < 0)
> -        return ret;
> -    ret = avio_read(s, pkt->data + old_size, size);
> -    av_shrink_packet(pkt, old_size + FFMAX(ret, 0));
> -    return ret;
> +    return append_packet_chunked(s, pkt, size);
> }
> 
> 
> 
> _______________________________________________
> ffmpeg-cvslog mailing list
> ffmpeg-cvslog at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog


More information about the ffmpeg-cvslog mailing list