An ASAN heap-buffer-overflow in scalable_channel_layout_config was caused by an
unchecked assumption that the channel layout of a scalable audio layer is a
superset of the previous layer's channel layout.
scalable_channel_layout_config constructs a channel layout map by copying
channels from the previous layer and adding new ones. The memory allocation is
based on the target loudspeaker_layout. However, if the target layout doesn't
encompass all previous channels (e.g., Mono to Stereo), copying previous
channels followed by adding current ones could exceed the allocated size,
causing a heap buffer overflow.
This commit adds an exception for the know case of Mono -> Stereo, and a check
to ensure the previous layer's channel layout is a subset of the current
layer's layout by comparing their masks. If the condition isn't met,
an error is returned.
Fixes: https://issues.oss-fuzz.com/issues/464965414
Co-authored-by: Oliver Chang <ochang@google.com>
Signed-off-by: James Almer <jamrial@gmail.com>
The way streams are coded in an IAMF struct follows a scalable model where the
channel layouts for each layer may not match the channel order our API can
represent in a Native order layout.
For example, an audio element may have six coded streams in the form of two
stereo streams, followed by two mono streams, and then by another two stereo
streams, for a total of 10 channels, and define for them four scalable layers
with loudspeaker_layout values "Stereo", "5.1ch", "5.1.2ch", and "5.1.4ch".
The first layer references the first stream, and each following layer will
reference all previous streams plus extra ones.
In this case, the "5.1ch" layer will reference four streams (the first two
stereo and the two mono) to encompass six channels, which does not match out
native layout 5.1(side) given that FC and LFE come after FL+FR but before
SL+SR, and here, they are at the end.
For this reason, we need to build Custom order layouts that properly represent
what we're exporting.
----
Before:
Stream group #0:0[0x12c]: IAMF Audio Element:
Layer 0: stereo
Stream #0:0[0x0]: Audio: opus, 48000 Hz, stereo, fltp (default)
Layer 1: 5.1(side)
Stream #0:0[0x0]: Audio: opus, 48000 Hz, stereo, fltp (default)
Stream #0:1[0x1]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Stream #0:2[0x2]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Stream #0:3[0x3]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Layer 2: 5.1.2
Stream #0:0[0x0]: Audio: opus, 48000 Hz, stereo, fltp (default)
Stream #0:1[0x1]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Stream #0:2[0x2]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Stream #0:3[0x3]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Stream #0:4[0x4]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Layer 3: 5.1.4
Stream #0:0[0x0]: Audio: opus, 48000 Hz, stereo, fltp (default)
Stream #0:1[0x1]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Stream #0:2[0x2]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Stream #0:3[0x3]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Stream #0:4[0x4]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Stream #0:5[0x5]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
----
AFter:
Stream group #0:0[0x12c]: IAMF Audio Element:
Layer 0: stereo
Stream #0:0[0x0]: Audio: opus, 48000 Hz, stereo, fltp (default)
Layer 1: 6 channels (FL+FR+SL+SR+FC+LFE)
Stream #0:0[0x0]: Audio: opus, 48000 Hz, stereo, fltp (default)
Stream #0:1[0x1]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Stream #0:2[0x2]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Stream #0:3[0x3]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Layer 2: 8 channels (FL+FR+SL+SR+FC+LFE+TFL+TFR)
Stream #0:0[0x0]: Audio: opus, 48000 Hz, stereo, fltp (default)
Stream #0:1[0x1]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Stream #0:2[0x2]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Stream #0:3[0x3]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Stream #0:4[0x4]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Layer 3: 10 channels (FL+FR+SL+SR+FC+LFE+TFL+TFR+TBL+TBR)
Stream #0:0[0x0]: Audio: opus, 48000 Hz, stereo, fltp (default)
Stream #0:1[0x1]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Stream #0:2[0x2]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Stream #0:3[0x3]: Audio: opus, 48000 Hz, mono, fltp (dependent)
Stream #0:4[0x4]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Stream #0:5[0x5]: Audio: opus, 48000 Hz, stereo, fltp (dependent)
Signed-off-by: James Almer <jamrial@gmail.com>
In most cases, the channel ids will match the standard Ambisonic Order, saving us the
need to use a custom order layout.
Signed-off-by: James Almer <jamrial@gmail.com>
We may write up to 43 bits, so 5 bytes is not enough.
Fixes: Assertion n>=0 && n<=32 failed at ./libavcodec/get_bits.h:406
Fixes: 398527871/clusterfuzz-testcase-minimized-ffmpeg_dem_IAMF_fuzzer-6602025714647040
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: James Almer <jamrial@gmail.com>
When using a 64bit PutBitContext (i.e. on x64), put_bits_no_assert()
can naturally write up to 63 bits. So one can avoid treating the
cases <32bits, 32 bits and <63 bits differently.
As it turns out, no user actually wants to write 64 bit at once
(maybe except testprograms).
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
When subblock durations are constant, the last block may be smaller and the
value needs to be calculated.
Signed-off-by: James Almer <jamrial@gmail.com>
Section 3.6.1 of the IAMF spec states "When constant_subblock_duration is equal to 0, the summation of all
subblock_duration in this parameter block SHALL be equal to duration.".
Signed-off-by: James Almer <jamrial@gmail.com>
ambisonics mode > 1 does not initialize any layer but layer 0
is unconditionally dereferenced
Fixes: poc-2024-11
Fixes: null pointer dereference
Found-by: 苏童 <220235212@seu.edu.cn>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
The ret value here is not yet intialized so the return would return
uninitialized data. What was probably meant to be checked here was the
return value of ffio_read_size, which can return an error.
Introduced in 38bcb3ba7b
Fixes: CID1618758
Signed-off-by: James Almer <jamrial@gmail.com>
The output of put_bits_left() here can be as big as 27, which is a bit
count not supported by get_bits().
Fixes fate-iamf-stereo-demux when using --assert-level=2
Signed-off-by: James Almer <jamrial@gmail.com>
The semantics for the field are different than the one in AVCodecParameters,
so use the name defined in the IAMF spec to prevent confusion.
Signed-off-by: James Almer <jamrial@gmail.com>
Fixes: member access within null pointer of type 'IAMFSubStream' (aka 'struct IAMFSubStream')
Fixes: 69795/clusterfuzz-testcase-minimized-ffmpeg_dem_IAMF_fuzzer-6216287009701888
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
There are lots of files that don't need it: The number of object
files that actually need it went down from 2011 to 884 here.
Keep it for external users in order to not cause breakages.
Also improve the other headers a bit while just at it.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Some encoders, like flac, propagate updated extradata at the end of encoding
as packet side data. Use it to update the relevant codec_config.
Signed-off-by: James Almer <jamrial@gmail.com>
if there's an audio layer with a single stream that can be rendered alone, mark it
as default. Otherwise, mark every stream as dependent.
Signed-off-by: James Almer <jamrial@gmail.com>
IAMFAudioElement and IAMFMixPresentation currently contain
pointers to independently allocated objects that are sometimes
owned by said structures and sometimes not.
More precisely, upon success the demuxer transfers ownership
of these other objects newly created AVStreamGroups, but it
keeps its pointers. iamf_read_close() therefore always resets
these pointers (because the cleanup code always treats them
as ownership pointers). This leads to memory leaks in case
iamf_read_header() without having attached all of these
objects to stream groups.
The muxer has a similar issue: It also clears these pointers
(pointing to objects owned by stream groups created by the user)
in its deinit function.
This commit fixes this memleak by explicitly adding non-ownership
pointers; this also allows to remove the code to reset the
ownership pointers.
Reviewed-by: James Almer <jamrial@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>