[Libav-user] Double free/corruption problem.

Mark Pupilli mpupilli at gmail.com
Tue Apr 2 15:31:02 CEST 2013


On 7 December 2012 18:51, Mark Pupilli <mpupilli at gmail.com> wrote:

> I get a double free or corruption problem, should really do a bug
> report but don't have time to decipher the FFmpeg bug reporting page.
> I'll post it here in case anyone is interested, feel free to ignore.
>
> When using custom IO for reading involves  something like the
> following when creating a context:
>
> buffer = (uint8_t*)av_malloc( BUFFER_SIZE );
> ctxt = avio_alloc_context( buffer, BUFFER_SIZE, 0, this,
> read_function, NULL, NULL );
>
> and then to free it:
>
> av_free( ctxt );
> av_free( buffer );
>
> However, if BUFFER_SIZE > 32768 bytes then av_free( buffer ) results
> in a crash due to invalid free/delete (which can also be detected by
> valgrind).
> Not calling av_free( buffer ) leads to a memory leak (reported by
> valgrind).
>
> In the case of calling av_free() Valgrind reports the buffer as
> already being free'd in:
>
> ==5471==  Address 0x9181680 is 0 bytes inside a block of size 32,784 free'd
> ==5471==    at 0x4C2A82E: free (in
> /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==5471==    by 0x712EC6F: av_free (mem.c:186)
> ==5471==    by 0x6DBEFC4: ffio_set_buf_size (aviobuf.c:707)
> ==5471==    by 0x6DBE1E5: fill_buffer (aviobuf.c:408)
> ==5471==    by 0x6DBE570: avio_read (aviobuf.c:495)
> ==5471==    by 0x6DE8971: ff_id3v2_read (id3v2.c:748)
> ==5471==    by 0x6EA4F42: avformat_open_input (utils.c:638)
>
> which if you follow the call in a debugger leads to the culprit at
> aviobuf.c:408:
>
>     /* make buffer smaller in case it ended up large after probing */
>     if (s->read_packet && s->buffer_size > max_buffer_size) {
>         ffio_set_buf_size(s, max_buffer_size);
>
>         s->checksum_ptr = dst = s->buffer;
>         len = s->buffer_size;
>     }
>
> This only gets called when we are reading. So in the case of using
> custom input libav takes it upon itself to tinker with the user
> supplied buffer. The crash only occurs if the buffer size is larger
> than 32KB
> which in my case it was because I was trying to follow some examples
> which show allocating (32768 + FF_INPUT_BUFFER_PADDING_SIZE) bytes.
>
> I don't know if the bug is that libav is supposed to give an error if
> the buffer is larger than 32KB, or not tinker with user supplied
> buffers, or avio_alloc_context should take a ** to the buffer so it
> can reallocate properly and clients don't have
> to choose between a double free or a memory leak, but its definitely
> wrong one way or another. I actually do not understand why the user
> needs to pass in the buffer at all as it seems avio_alloc_context
> could do it internally if it is going to
> reallocate it on a whim anyway.
>
> regards,
> Mark
>

A couple of users have contacted me about this since. One of them has a
workaround for the bug (thanks Keith!):

Before you free the avio buffer: check that the pointer in the AVIOContext
structure is the same as the buffer you allocated yourself and passed to
avio_alloc_context(...) - if it is the same you can safely free it, if it
is not the same then the library has already freed and reallocated the
buffer (and will automatically free the buffer it allocated) so there is no
need to do anything.

Another workaround is to only ever allocate a buffer of size 32768 bytes
because the library does not appear to re-allocate the io buffer in that
case but I think the above workaround is more future proof against any
crazy stuff the library might do with the buffers you give it in future
releases.

Mark
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20130402/519d346c/attachment.html>


More information about the Libav-user mailing list