[FFmpeg-devel] [PATCH 212/217] avcodec/snow: Fix race in ff_snow_common_init()

Andreas Rheinhardt andreas.rheinhardt at gmail.com
Thu Dec 3 00:45:10 EET 2020


Michael Niedermayer:
> On Wed, Dec 02, 2020 at 05:22:39AM +0100, Andreas Rheinhardt wrote:
>> Commits d49210788b0836d56dd872d517fe73f83b080101 and
>> ee8ce211ead04c8684da0c9c143814e57e9b9eda set the
>> FF_CODEC_CAP_INIT_THREADSAFE flag for the Snow encoder resp. decoder;
>> yet these codecs init functions aren't threadsafe at all:
>> ff_snow_common_init() initializes static data, but there is no check
>> at all that it is only done once by one thread.
> 
> These commits originated from long ago when it was felt that writing
> the same value in the same location by 2 threads and always writing that
> value in a thread before the same thread read it would not qualify
> as undefined behavior or a race.
> The current C standard makes it UB (to the best of my knowledge) 

Indeed: "Two expression evaluations conflict if one of them modifies a
memory location and the other one reads or modifies the same memory
location." Notice that there is no exception in case the newly written
value coincides with the old value (or if both are write operations and
both write the same value). And lateron: "The execution of a program
contains a data race if it contains two conflicting actions in
different threads, at least one of which is not atomic, and neither
happens before the other. Any such data race results in undefined behavior."

> so your change is correct but i think your commit message:
> "aren't threadsafe at all" is suggesting a major issue which i think
> this is not.

Ok. Then how about something like:

avcodec/snow: Use ff_thread_once() in ff_snow_common_init()

ff_snow_common_init() currently initializes static data every time it is
invoked; given that both the Snow encoder and decoder have the
FF_CODEC_CAP_INIT_THREADSAFE flag set, this can lead to data races (and
therefore undefined behaviour) even though all threads write the same
values. This commit fixes this by using ff_thread_once() for the
initializations.

> That said, is there any case known where code like this produces unexpected
> behavior on any real platform with any real compiler ? (not counting
> thread saftey check tools detecting / aborting)

If the underlying writes are atomic, no; these are int and uint8_t,
respectively, so the writes will likely be atomic. [1] contains a nice
summary for how real the danger of this is.

> For most undefined behavior cases i can think of some optimization
> messing up or something but in this case everything i could think of
> requires some rather odd hypothetical hardware ...
> 
So do I, but it is nevertheless UB. And using a sanitizer without a lot
of false positives is also a nice benefit.
(Also notice that the very same has been said about signed integer
overflow.)

- Andreas

[1]: https://lwn.net/Articles/793253/


More information about the ffmpeg-devel mailing list