PR #23031 opened by mkver
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23031
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23031.patch

This fixes overreads with libdav1d, because it provides
non-padded data in violation to the requirements of
the GetBits API.

Furthermore, using the GetBits API here is wasteful,
as the offsets here are known and the actual data to be copied
is even byte-aligned, allowing to use memcpy.

This is an alternative to #22887.


>From f2e5eff3ff2141479da980fc9474a8f8ecf768a8 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Wed, 6 May 2026 15:23:01 +0200
Subject: [PATCH] avcodec/atsc_a53: Avoid GetBits API to parse A53 CC data

This fixes overreads with libdav1d, because it provides
non-padded data in violation to the requirements of
the GetBits API.

Furthermore, using the GetBits API here is wasteful,
as the offsets here are known and the actual data to be copied
is even byte-aligned, allowing to use memcpy.

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavcodec/atsc_a53.c | 26 +++++++-------------------
 1 file changed, 7 insertions(+), 19 deletions(-)

diff --git a/libavcodec/atsc_a53.c b/libavcodec/atsc_a53.c
index 1e9ea15ae0..7c88263a14 100644
--- a/libavcodec/atsc_a53.c
+++ b/libavcodec/atsc_a53.c
@@ -19,9 +19,9 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
 #include "atsc_a53.h"
-#include "get_bits.h"
 
 int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len,
                      void **data, size_t *sei_size)
@@ -69,33 +69,25 @@ int ff_alloc_a53_sei(const AVFrame *frame, size_t 
prefix_len,
 int ff_parse_a53_cc(AVBufferRef **pbuf, const uint8_t *data, int size)
 {
     AVBufferRef *buf = *pbuf;
-    GetBitContext gb;
     size_t new_size, old_size = buf ? buf->size : 0;
     int ret, cc_count;
 
     if (size < 3)
         return AVERROR_INVALIDDATA;
 
-    ret = init_get_bits8(&gb, data, size);
-    if (ret < 0)
-        return ret;
-
-    if (get_bits(&gb, 8) != 0x3) // user_data_type_code
+    if (data[0] != 0x3) // user_data_type_code
         return 0;
 
-    skip_bits(&gb, 1); // reserved
-    if (!get_bits(&gb, 1)) // process_cc_data_flag
+    if (!(data[1] & 0x40)) // process_cc_data_flag
         return 0;
 
-    skip_bits(&gb, 1); // zero bit
-    cc_count = get_bits(&gb, 5);
+    cc_count = data[1] & 0x1F;
     if (!cc_count)
         return 0;
 
-    skip_bits(&gb, 8); // reserved
-
+    // content of data[2] is reserved
     /* 3 bytes per CC plus one byte marker_bits at the end */
-    if (cc_count * 3 >= (get_bits_left(&gb) >> 3))
+    if (cc_count * 3 >= size - 3)
         return AVERROR_INVALIDDATA;
 
     new_size = (old_size + cc_count * 3);
@@ -110,11 +102,7 @@ int ff_parse_a53_cc(AVBufferRef **pbuf, const uint8_t 
*data, int size)
 
     buf = *pbuf;
     /* Use of av_buffer_realloc assumes buffer is writeable */
-    for (int i = 0; i < cc_count; i++) {
-        buf->data[old_size++] = get_bits(&gb, 8);
-        buf->data[old_size++] = get_bits(&gb, 8);
-        buf->data[old_size++] = get_bits(&gb, 8);
-    }
+    memcpy(buf->data + old_size, data + 3, cc_count * 3);
 
     return cc_count;
 }
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to