(The FLAC parser currently ignores the streaminfo block;
therefore some of this is decoder-only. Given that the FLAC
parser should probably use the streaminfo block, this stuff
is moved to flac_parse.h.)
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
FLAC parser currently uses AVFifoBuffer in a highly non-trivial manner,
modifying its "internals" (the whole struct is currently public, but no
other code touches its contents directly). E.g. it does not use any
av_fifo functions for reading the FIFO contents, but implements its own.
Reimplement the needed parts of the AVFifoBuffer API in the FLAC parser,
making it completely self-contained. This will allow us to make
AVFifoBuffer private.
Fixes: out if array read
Fixes: 40109/clusterfuzz-testcase-minimized-ffmpeg_dem_FLAC_fuzzer-4805686811295744
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Reviewed-by: Mattias Wadman <mattias.wadman@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Reduces the risk of finding false frames that happens to have valid values and CRC.
Fixes ticket #9185 ffmpeg flac decoder incorrectly finds junk frame
https://trac.ffmpeg.org/ticket/9185
Possible now that the next pointer no longer exists.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
Signed-off-by: James Almer <jamrial@gmail.com>
Fixes: Timeout
Fixes: out of array access
Fixes: 20274/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_FLAC_fuzzer-5649631988154368
Fixes: 19275/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_FLAC_fuzzer-5757535722405888
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
When flushing, MAX_FRAME_HEADER_SIZE bytes (always zero) are supposed to
be written to the fifo buffer in order to be able to check the rest of
the buffer for frame headers. It was intended to write these by writing
a small buffer of size MAX_FRAME_HEADER_SIZE to the buffer. But the way
it was actually done ensured that this did not happen:
First, it would be checked whether the size of the input buffer was zero,
in which case it buf_size would be set to MAX_FRAME_HEADER_SIZE and
read_end would be set to indicate that MAX_FRAME_HEADER_SIZE bytes need
to be written. Then it would be made sure that there is enough space in
the fifo for the data to be written. Afterwards the data is written. The
check used here is for whether buf_size is zero or not. But if it was
zero initially, it is MAX_FRAME_HEADER_SIZE now, so that not the
designated buffer for writing MAX_FRAME_HEADER_SIZE is written; instead
the padded buffer (from the stack of av_parser_parse2()) is used. This
works because AV_INPUT_BUFFER_PADDING_SIZE >= MAX_FRAME_HEADER_SIZE.
Lateron, buf_size is set to zero again.
Given that since 7edbd536, the actual amount of data read is no longer
automatically equal to buf_size, it is completely unnecessary to modify
buf_size at all. Moreover, modifying it is dangerous: Some allocations
can fail and because buf_size is never reset to zero in this codepath,
the parser might return a value > 0 on flushing.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
For a parser, the input buffer is always != NULL: In case of flushing,
the indicated size of the input buffer will be zero and the input buffer
will point to a zeroed buffer of size 0 + AV_INPUT_BUFFER_PADDING.
Therefore one does not need to check for whether said buffer is NULL or
not.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
The flac parser uses a fifo to buffer its data. Consequently, when
searching for sync codes of flac packets, one needs to take care of
the possibility of wraparound. This is done by using an optimized start
code search that works on each of the continuous buffers separately and
by explicitly checking whether the last pre-wrap byte and the first
post-wrap byte constitute a valid sync code.
Moreover, the last MAX_FRAME_HEADER_SIZE - 1 bytes ought not to be searched
for (the start of) a sync code because a header that might be found in this
region might not be completely available. These bytes ought to be searched
lateron when more data is available or when flushing.
Unfortunately there was an off-by-one error in the calculation of the
length to search of the post-wrap buffer: It was too large, because the
calculation was based on the amount of bytes available in the fifo from
the last pre-wrap byte onwards. This meant that a header might be
parsed twice (once prematurely and once regularly when more data is
available); it could also mean that an invalid header will be treated as
valid (namely if the length of said invalid header is
MAX_FRAME_HEADER_SIZE and the invalid byte that will be treated as the
last byte of this potential header happens to be the right CRC-8).
Should a header be parsed twice, the second instance will be the best child
of the first instance; the first instance's score will be
FLAC_HEADER_BASE_SCORE - FLAC_HEADER_CHANGED_PENALTY ( = 3) higher than
the second instance's score. So the frame belonging to the first
instance will be output and it will be done as a zero length frame (the
difference of the header's offset and the child's offset). This has
serious consequences when flushing, as returning a zero length buffer
signals to the caller that no more data will be output; consequently the
last frames not yet output will be dropped.
Furthermore, a "sample/frame number mismatch in adjacent frames" warning
got output when returning the zero-length frame belonging to the first
header, because the child's sample/frame number of course didn't match
the expected sample frame/number given its parent.
filter/hdcd-mix.flac from the FATE-suite was affected by this (the last
frame was omitted) which is the reason why several FATE-tests needed to
be updated.
Fixes ticket #5937.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
The FLACHeaderMarker structure contained a pointer to an array of int;
said array was always allocated and freed at the same time as its
referencing FLACHeaderMarker; the pointer was never modified to point to
a different array and each FLACHeaderMarker had its own unique array.
Furthermore, all these arrays had a constant size. Therefore include
this array in the FLACHeaderMarker struct.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
FLAC sync codes contain a byte equal to 0xFF and so the function that
searches for sync codes first searched for this byte. It did this by
checking four bytes at once; these bytes have been read via AV_RB32, but
the test works just as well with native endianness.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
Fixes: crbug/827204
Reported-by: Frank Liberato <liberato@google.com>
Reviewed-by: Frank Liberato <liberato@google.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
* qatar/master:
flac: only set channel layout if not previously set or on channel count change
prepare 9_beta3 release
Conflicts:
RELEASE
Merged-by: Michael Niedermayer <michaelni@gmx.at>
* commit '50a65e7a540ce6747f81d6dbf6a602ad35be77ff': (24 commits)
vmdaudio: set channel layout
twinvq: validate sample rate code
twinvq: set channel layout
twinvq: validate that channels is not <= 0
truespeech: set channel layout
sipr: set channel layout
shorten: validate that the channel count in the header is not <= 0
ra288dec: set channel layout
ra144dec: set channel layout
qdm2: remove unneeded checks for channel count
qdm2: make sure channels is not <= 0 and set channel layout
qcelpdec: set channel layout
nellymoserdec: set channels to 1
libopencore-amr: set channel layout for amr-nb or if not set by the user
libilbc: set channel layout
dpcm: use AVCodecContext.channels instead of keeping a private copy
imc: set channels to 1 instead of validating it
gsmdec: always set channel layout and sample rate at initialization
libgsmdec: always set channel layout and sample rate at initialization
g726dec: do not validate sample rate
...
Conflicts:
libavcodec/dpcm.c
libavcodec/qdm2.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>