diff mbox series

[FFmpeg-devel,2/4] avcodec/vp9_superframe_bsf: Check for existence of data before reading it

Message ID AS1PR01MB9564770DE02523319BA8303E8F179@AS1PR01MB9564.eurprd01.prod.exchangelabs.com
State Accepted
Commit c12e8c97b13f33897bd9c6095432c9740504f5c7
Headers show
Series [FFmpeg-devel,1/4] avcodec/vp9_raw_reorder_bsf: Check for existence of data before reading it | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Andreas Rheinhardt March 22, 2022, 11:09 p.m. UTC
Packets without data need to be handled specially in order to avoid
undefined reads. Pass these packets through unchanged in case there
are no cached packets* and error out in case there are cached packets:
Returning the packet would mess with the order of the packets;
if one returned the zero-sized packet before the superframe that will
be created from the packets in the cache, the zero-sized packet would
overtake the packets in the cache; if one returned the packet later,
the packets that complete the superframe will overtake the zero-sized
packet.

*: This case e.g. encompasses the scenario of updated extradata
side-data at the end.

Fixes: Out of array read
Fixes: 45722/clusterfuzz-testcase-minimized-ffmpeg_BSF_VP9_SUPERFRAME_fuzzer-5173378975137792

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
The current way of passthrough has been suggested by James.

 libavcodec/vp9_superframe_bsf.c | 9 +++++++++
 1 file changed, 9 insertions(+)
diff mbox series

Patch

diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c
index 57681e29e4..df9b97fa3c 100644
--- a/libavcodec/vp9_superframe_bsf.c
+++ b/libavcodec/vp9_superframe_bsf.c
@@ -108,6 +108,15 @@  static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *pkt)
     if (res < 0)
         return res;
 
+    if (!pkt->size) {
+        /* In case the cache is empty we can pass side-data-only packets
+         * through unchanged. Otherwise, such a packet makes no sense. */
+        if (!s->n_cache)
+            return 0;
+        res = AVERROR_INVALIDDATA;
+        goto done;
+    }
+
     marker = pkt->data[pkt->size - 1];
     if ((marker & 0xe0) == 0xc0) {
         int nbytes = 1 + ((marker >> 3) & 0x3);