https://bugs.gentoo.org/974283
https://gstreamer.freedesktop.org/security/sa-2026-0014.html
https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/11245

From 6dfb6e2e8c26477fa3cba0ef439ae0011318319c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Thu, 26 Mar 2026 18:45:57 +0200
Subject: [PATCH 2/8] typefind: Avoid signed 32 bit integer overflow when
 parsing AV1 LEB128 values

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/4994

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/11245>
--- a/gst/typefind/gsttypefindfunctions.c
+++ b/gst/typefind/gsttypefindfunctions.c
@@ -6881,7 +6881,7 @@ av1_leb128 (const guint8 * data, guint32 * retval, gint * read_bytes)
 
   for (i = 0; i < 8; i++) {
     leb128_byte = data[i];
-    value |= (((gint) leb128_byte & 0x7f) << (i * 7));
+    value |= (((guint64) leb128_byte & 0x7f) << (i * 7));
     if (!(leb128_byte & 0x80))
       break;
 
-- 
GitLab


From f7835ad222a176a51c84d81cdee3456dd3dfec52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Thu, 26 Mar 2026 18:59:11 +0200
Subject: [PATCH 4/8] typefind: Use a byte reader for parsing AV1 bitstreams

And make sure to use appropriate bounds checks.

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/4993

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/11245>
--- a/gst/typefind/gsttypefindfunctions.c
+++ b/gst/typefind/gsttypefindfunctions.c
@@ -6870,17 +6870,17 @@ av1_is_valid_obu_type (guint obu_type)
 }
 
 static gboolean
-av1_leb128 (const guint8 * data, guint32 * retval, gint * read_bytes)
+av1_leb128 (GstByteReader * br, guint32 * retval)
 {
   guint8 leb128_byte = 0;
   guint64 value = 0;
   gint i;
 
   *retval = 0;
-  *read_bytes = 0;
 
   for (i = 0; i < 8; i++) {
-    leb128_byte = data[i];
+    if (!gst_byte_reader_get_uint8 (br, &leb128_byte))
+      return FALSE;
     value |= (((guint64) leb128_byte & 0x7f) << (i * 7));
     if (!(leb128_byte & 0x80))
       break;
@@ -6895,7 +6895,6 @@ av1_leb128 (const guint8 * data, guint32 * retval, gint * read_bytes)
   /* check for bitstream conformance see chapter 4.10.5 */
   if (value < G_MAXUINT32) {
     *retval = (guint32) value;
-    *read_bytes = i + 1;
     return TRUE;
   }
 
@@ -6903,44 +6902,44 @@ av1_leb128 (const guint8 * data, guint32 * retval, gint * read_bytes)
 }
 
 static gboolean
-av1_is_valid_obu (const guint8 * data, guint * obu_type, gint * read_bytes)
+av1_is_valid_obu (GstByteReader * br, guint * obu_type)
 {
   gboolean obu_forbidden_bit;
   gboolean obu_extension_flag;
   gboolean obu_has_size_field;
   gboolean obu_reserved_1bit;
-  int offset = 1;
+  guint8 b;
 
   *obu_type = 0;
-  *read_bytes = 0;
+
+  if (!gst_byte_reader_get_uint8 (br, &b))
+    return FALSE;
 
   /* Detect OBU header */
-  obu_forbidden_bit = !!(data[0] & 0x80);
+  obu_forbidden_bit = !!(b & 0x80);
   if (obu_forbidden_bit)
     return FALSE;
 
-  *obu_type = (data[0] & 0x78) >> 3;
-  obu_extension_flag = !!(data[0] & 0x4);
-  obu_has_size_field = !!(data[0] & 0x2);
-  obu_reserved_1bit = !!(data[0] & 0x1);
+  *obu_type = (b & 0x78) >> 3;
+  obu_extension_flag = !!(b & 0x4);
+  obu_has_size_field = !!(b & 0x2);
+  obu_reserved_1bit = !!(b & 0x1);
 
   /* if obu_extension_flag is set temporal_id (3 bits)
    * spatial_id (2 bits) and extension_header_reserved_3bits (3 bits)
    * field are coded in the header so OBU size field is
    * 1 byte after */
-  if (obu_extension_flag)
-    offset++;
-
-  *read_bytes += offset;
+  if (obu_extension_flag) {
+    if (!gst_byte_reader_skip (br, 1))
+      return FALSE;
+  }
 
   if (av1_is_valid_obu_type (*obu_type) && !obu_reserved_1bit) {
     if (obu_has_size_field) {
       guint32 obu_size;
-      gint bytes;
 
-      if (!av1_leb128 (data + offset, &obu_size, &bytes))
+      if (!av1_leb128 (br, &obu_size))
         return FALSE;
-      *read_bytes += bytes;
     }
 
     return TRUE;
@@ -6956,42 +6955,39 @@ av1_type_find (GstTypeFind * tf, gpointer unused)
   guint32 frame_unit_size;
   guint32 obu_length;
   const guint8 *data;
+  GstByteReader br;
   guint obu_type;
-  gint read_bytes;
-  gint offset = 0;
 
   data = gst_type_find_peek (tf, 0, 25);
   if (!data)
     return;
 
-  if (av1_is_valid_obu (data, &obu_type, &read_bytes)) {
+  gst_byte_reader_init (&br, data, 25);
+
+  if (av1_is_valid_obu (&br, &obu_type)) {
     gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MINIMUM, "video/x-av1",
         "stream-format", G_TYPE_STRING, "obu-stream",
         "alignment", G_TYPE_STRING, "none", NULL);
     return;
   }
 
-  if (!av1_leb128 (data, &temporal_unit_size, &read_bytes))
+  if (!av1_leb128 (&br, &temporal_unit_size))
     return;
-  offset += read_bytes;
 
-  if (!av1_leb128 (data + offset, &frame_unit_size, &read_bytes))
+  if (!av1_leb128 (&br, &frame_unit_size))
     return;
-  offset += read_bytes;
 
   if (frame_unit_size > temporal_unit_size)
     return;
 
-  if (!av1_leb128 (data + offset, &obu_length, &read_bytes))
+  if (!av1_leb128 (&br, &obu_length))
     return;
-  offset += read_bytes;
 
   if (obu_length > frame_unit_size)
     return;
 
-  if (!av1_is_valid_obu (data + offset, &obu_type, &read_bytes))
+  if (!av1_is_valid_obu (&br, &obu_type))
     return;
-  offset += read_bytes;
 
   /* The first OBU must be a temporal delimiter */
   if (obu_type == 2)
-- 
GitLab


From 30a18fc8dba3892f168008fe211f7c951465f26a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Thu, 26 Mar 2026 19:19:19 +0200
Subject: [PATCH 6/8] typefind: Allow G_MAXUINT32 as LEB128 encoded value when
 parsing AV1 bitstreams

The spec states that any value less than or equal to (1<<32) - 1 should be
accepted but we were rejecting (1<<32) - 1.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/11245>
--- a/gst/typefind/gsttypefindfunctions.c
+++ b/gst/typefind/gsttypefindfunctions.c
@@ -6893,7 +6893,7 @@ av1_leb128 (GstByteReader * br, guint32 * retval)
     return FALSE;
 
   /* check for bitstream conformance see chapter 4.10.5 */
-  if (value < G_MAXUINT32) {
+  if (value <= G_MAXUINT32) {
     *retval = (guint32) value;
     return TRUE;
   }
-- 
GitLab


From 554e3ee6f2a353c0192b2af10f7b141e8cd32d85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Thu, 26 Mar 2026 19:27:22 +0200
Subject: [PATCH 8/8] typefind: Remove dead code in AV1 LEB128 parser

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/11245>
--- a/gst/typefind/gsttypefindfunctions.c
+++ b/gst/typefind/gsttypefindfunctions.c
@@ -6889,9 +6889,6 @@ av1_leb128 (GstByteReader * br, guint32 * retval)
       return FALSE;
   }
 
-  if (i == 8)
-    return FALSE;
-
   /* check for bitstream conformance see chapter 4.10.5 */
   if (value <= G_MAXUINT32) {
     *retval = (guint32) value;
-- 
GitLab

