ffmpeg and mmap

Andriy Gapon avg at freebsd.org
Fri Dec 17 17:01:09 UTC 2010


Martin,

apologies - my report was incomplete.  I really meant to include the following new
information at that time, but somehow I forgot about it and the
_BSD_VISIBLE/POSIX_C_SOURCE discussion that followed distracted me.

on 12/12/2010 22:40 Andriy Gapon said the following:
> 
> I've been getting some crash dumps in libswscale.so code.
> The stack trace is always like this:
> #0  0x000000083a6abf10 in ?? ()
> #1  0x000000080a717dc6 in hyscale_fast_MMX2
> #2  0x000000080a71bd64 in swScale_MMX2
> #3  0x000000080a71ebf9 in sws_scale
> ...
> 
> From disassembling I've identified that the crash happens as soon as inline
> assembly in hyscale_fast_MMX2 calls code pointed to by lumMmx2FilterCode pointer.
> 
> The following code in libswscale/utils.c, function sws_getContext() is of interest:
> 
> #if ARCH_X86 && (HAVE_MMX2 || CONFIG_RUNTIME_CPUDETECT)
> // can't downscale !!!
>         if (c->canMMX2BeUsed && (flags & SWS_FAST_BILINEAR)) {
>             c->lumMmx2FilterCodeSize = initMMX2HScaler(      dstW, c->lumXInc,
> NULL, NULL, NULL, 8);
>             c->chrMmx2FilterCodeSize = initMMX2HScaler(c->chrDstW, c->chrXInc,
> NULL, NULL, NULL, 4);
> 
> #ifdef MAP_ANONYMOUS
>             c->lumMmx2FilterCode = mmap(NULL, c->lumMmx2FilterCodeSize,
> PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>             c->chrMmx2FilterCode = mmap(NULL, c->chrMmx2FilterCodeSize,
> PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

The lines above look differently in the ffmpeg original code - it passes 0, not
-1, as file descriptor parameter and because of that the mmap() calls would fail
on FreeBSD.
Linux is probably more permissive here.
So we need a patch for this.

> #elif HAVE_VIRTUALALLOC
>             c->lumMmx2FilterCode = VirtualAlloc(NULL, c->lumMmx2FilterCodeSize,
> MEM_COMMIT, PAGE_EXECUTE_READWRITE);
>             c->chrMmx2FilterCode = VirtualAlloc(NULL, c->chrMmx2FilterCodeSize,
> MEM_COMMIT, PAGE_EXECUTE_READWRITE);
> #else
>             c->lumMmx2FilterCode = av_malloc(c->lumMmx2FilterCodeSize);
>             c->chrMmx2FilterCode = av_malloc(c->chrMmx2FilterCodeSize);
> #endif
> 
>             if (!c->lumMmx2FilterCode || !c->chrMmx2FilterCode)
>                 goto fail;

The above check should also be fixed for the case when mmap is used.
mmap returns MAP_FAILED in case of failure and on FreeBSD MAP_FAILED != NULL.
Not sure about Linux, but we probably don't care - if only to report to upstream
to make their code cleaner.


Apologies again for not reporting these important issues.

-- 
Andriy Gapon


More information about the freebsd-multimedia mailing list