[FFmpeg-devel] [PATCH 1/3] avutil/mem: Fix *realloc() alignment with memalign hack

wm4 nfxjfg at googlemail.com
Mon Nov 21 17:34:54 EET 2016


On Mon, 21 Nov 2016 16:18:56 +0100
Michael Niedermayer <michael at niedermayer.cc> wrote:

> Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
> ---
>  libavutil/mem.c | 44 ++++++++++++++++++++++++++++++++------------
>  1 file changed, 32 insertions(+), 12 deletions(-)
> 

"Fix" is not a good description. Was it broken? What was broken?

Also, I thought the memalign hack was generally not needed anymore.
Which platforms still need it?

> diff --git a/libavutil/mem.c b/libavutil/mem.c
> index 1a8fc21..6273d89 100644
> --- a/libavutil/mem.c
> +++ b/libavutil/mem.c
> @@ -86,12 +86,15 @@ void *av_malloc(size_t size)
>          return NULL;
>  
>  #if CONFIG_MEMALIGN_HACK
> -    ptr = malloc(size + ALIGN);
> +    ptr = malloc(size + ALIGN + 8);
>      if (!ptr)
>          return ptr;
> -    diff              = ((~(long)ptr)&(ALIGN - 1)) + 1;
> +
> +    diff = ((((uintptr_t)ptr) + 9 + ALIGN - 1) & ~(ALIGN - 1)) - (uintptr_t)ptr;
> +    av_assert0(diff>0 && diff<=ALIGN + 8);

Why 9?

>      ptr               = (char *)ptr + diff;
> -    ((char *)ptr)[-1] = diff;
> +    ((char *)ptr)[-9] = diff;
> +    ((int64_t *)ptr)[-1] = size;
>  #elif HAVE_POSIX_MEMALIGN
>      if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
>      if (posix_memalign(&ptr, ALIGN, size))
> @@ -146,6 +149,7 @@ void *av_realloc(void *ptr, size_t size)
>  {
>  #if CONFIG_MEMALIGN_HACK
>      int diff;
> +    void *ptr2;
>  #endif
>  
>      /* let's disallow possibly ambiguous cases */
> @@ -153,15 +157,31 @@ void *av_realloc(void *ptr, size_t size)
>          return NULL;
>  
>  #if CONFIG_MEMALIGN_HACK
> -    //FIXME this isn't aligned correctly, though it probably isn't needed
>      if (!ptr)
>          return av_malloc(size);
> -    diff = ((char *)ptr)[-1];
> -    av_assert0(diff>0 && diff<=ALIGN);  
> -    ptr = realloc((char *)ptr - diff, size + diff);
> -    if (ptr)
> -        ptr = (char *)ptr + diff;
> -    return ptr;
> +    diff = ((char *)ptr)[-9];
> +    av_assert0(diff>0 && diff<=ALIGN + 8);
> +
> +    // Quick path for apparently and likly aligned realloc()
> +    if (diff == ALIGN) {
> +        ptr = realloc((char *)ptr - diff, size + diff);
> +        if (ptr)
> +            ptr = (char *)ptr + diff;
> +        if (!(((uintptr_t)ptr) & (ALIGN - 1))) {
> +            if (ptr)
> +                ((int64_t *)ptr)[-1] = size;
> +            return ptr;
> +        }
> +    }
> +
> +    ptr2 = av_malloc(size);
> +    if (!ptr2)
> +        return NULL;
> +
> +    memcpy(ptr2, ptr, FFMIN(((int64_t *)ptr)[-1], size));
> +    ((int64_t *)ptr2)[-1] = size;
> +    av_free(ptr);
> +    return ptr2;

I thought av_realloc() never keeps alignment. It only needs to be sure
to not choke on the alignment hack, since calling av_realloc() on a
av_malloc() allocated block is still ok, even if it can lose the
alignment.

>  #elif HAVE_ALIGNED_MALLOC
>      return _aligned_realloc(ptr, size + !size, ALIGN);
>  #else
> @@ -229,8 +249,8 @@ void av_free(void *ptr)
>  {
>  #if CONFIG_MEMALIGN_HACK
>      if (ptr) {
> -        int v= ((char *)ptr)[-1];
> -        av_assert0(v>0 && v<=ALIGN);  
> +        int v= ((char *)ptr)[-9];
> +        av_assert0(v>0 && v<=ALIGN + 8);
>          free((char *)ptr - v);
>      }
>  #elif HAVE_ALIGNED_MALLOC



More information about the ffmpeg-devel mailing list