[Libav-user] Double free/corruption problem.

Mark Pupilli mpupilli at gmail.com
Fri Dec 7 19:51:08 CET 2012


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


More information about the Libav-user mailing list