<div dir="ltr">On 7 December 2012 18:51, Mark Pupilli <span dir="ltr"><<a href="mailto:mpupilli@gmail.com" target="_blank">mpupilli@gmail.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
I get a double free or corruption problem, should really do a bug<br>
report but don't have time to decipher the FFmpeg bug reporting page.<br>
I'll post it here in case anyone is interested, feel free to ignore.<br>
<br>
When using custom IO for reading involves  something like the<br>
following when creating a context:<br>
<br>
buffer = (uint8_t*)av_malloc( BUFFER_SIZE );<br>
ctxt = avio_alloc_context( buffer, BUFFER_SIZE, 0, this,<br>
read_function, NULL, NULL );<br>
<br>
and then to free it:<br>
<br>
av_free( ctxt );<br>
av_free( buffer );<br>
<br>
However, if BUFFER_SIZE > 32768 bytes then av_free( buffer ) results<br>
in a crash due to invalid free/delete (which can also be detected by<br>
valgrind).<br>
Not calling av_free( buffer ) leads to a memory leak (reported by valgrind).<br>
<br>
In the case of calling av_free() Valgrind reports the buffer as<br>
already being free'd in:<br>
<br>
==5471==  Address 0x9181680 is 0 bytes inside a block of size 32,784 free'd<br>
==5471==    at 0x4C2A82E: free (in<br>
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)<br>
==5471==    by 0x712EC6F: av_free (mem.c:186)<br>
==5471==    by 0x6DBEFC4: ffio_set_buf_size (aviobuf.c:707)<br>
==5471==    by 0x6DBE1E5: fill_buffer (aviobuf.c:408)<br>
==5471==    by 0x6DBE570: avio_read (aviobuf.c:495)<br>
==5471==    by 0x6DE8971: ff_id3v2_read (id3v2.c:748)<br>
==5471==    by 0x6EA4F42: avformat_open_input (utils.c:638)<br>
<br>
which if you follow the call in a debugger leads to the culprit at<br>
aviobuf.c:408:<br>
<br>
    /* make buffer smaller in case it ended up large after probing */<br>
    if (s->read_packet && s->buffer_size > max_buffer_size) {<br>
        ffio_set_buf_size(s, max_buffer_size);<br>
<br>
        s->checksum_ptr = dst = s->buffer;<br>
        len = s->buffer_size;<br>
    }<br>
<br>
This only gets called when we are reading. So in the case of using<br>
custom input libav takes it upon itself to tinker with the user<br>
supplied buffer. The crash only occurs if the buffer size is larger<br>
than 32KB<br>
which in my case it was because I was trying to follow some examples<br>
which show allocating (32768 + FF_INPUT_BUFFER_PADDING_SIZE) bytes.<br>
<br>
I don't know if the bug is that libav is supposed to give an error if<br>
the buffer is larger than 32KB, or not tinker with user supplied<br>
buffers, or avio_alloc_context should take a ** to the buffer so it<br>
can reallocate properly and clients don't have<br>
to choose between a double free or a memory leak, but its definitely<br>
wrong one way or another. I actually do not understand why the user<br>
needs to pass in the buffer at all as it seems avio_alloc_context<br>
could do it internally if it is going to<br>
reallocate it on a whim anyway.<br>
<br>
regards,<br>
Mark<br>
</blockquote></div><br></div><div class="gmail_extra" style>A couple of users have contacted me about this since. One of them has a workaround for the bug (thanks Keith!):</div><div class="gmail_extra" style><br></div><div class="gmail_extra" style>
<span style="font-family:arial,sans-serif;font-size:13px">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 </span>avio_alloc_context(...)<span style="font-family:arial,sans-serif;font-size:13px"> - 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.</span></div>
<div class="gmail_extra" style><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div class="gmail_extra" style><span style="font-family:arial,sans-serif;font-size:13px">Another workaround is to only ever allocate a buffer of size </span>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.</div>
<div class="gmail_extra" style><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div class="gmail_extra" style><span style="font-family:arial,sans-serif;font-size:13px">Mark</span></div><div class="gmail_extra">
<br></div></div>