vorbis_parse: check writes to GstOggStream.vorbis_mode_sizes
authorMathieu Duponchelle <mathieu@centricular.com>
Wed, 2 Oct 2024 13:16:30 +0000 (15:16 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 3 Dec 2024 12:15:24 +0000 (12:15 +0000)
Thanks to Antonio Morales for finding and reporting the issue.

Fixes GHSL-2024-117 Fixes gstreamer#3875

Also perform out-of-bounds check for accesses to op->packet

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8050>

subprojects/gst-plugins-base/ext/ogg/vorbis_parse.c

index 65ef463808e19870ee1c68e0c6a4aa87e7bd24e8..757c7cd82b8db040fa079d6d1509486c7556cb48 100644 (file)
@@ -165,6 +165,10 @@ gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op)
     if (offset == 0) {
       offset = 8;
       current_pos -= 1;
+
+      /* have we underrun? */
+      if (current_pos < op->packet)
+        return -1;
     }
   }
 
@@ -178,6 +182,10 @@ gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op)
     if (offset == 7)
       current_pos -= 1;
 
+    /* have we underrun? */
+    if (current_pos < op->packet + 5)
+      return -1;
+
     if (((current_pos[-5] & ~((1 << (offset + 1)) - 1)) != 0)
         ||
         current_pos[-4] != 0
@@ -199,9 +207,18 @@ gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op)
   /* Give ourselves a chance to recover if we went back too far by using
    * the size check. */
   for (ii = 0; ii < 2; ii++) {
+
     if (offset > 4) {
+      /* have we underrun? */
+      if (current_pos < op->packet)
+        return -1;
+
       size_check = (current_pos[0] >> (offset - 5)) & 0x3F;
     } else {
+      /* have we underrun? */
+      if (current_pos < op->packet + 1)
+        return -1;
+
       /* mask part of byte from current_pos */
       size_check = (current_pos[0] & ((1 << (offset + 1)) - 1));
       /* shift to appropriate position */
@@ -233,6 +250,10 @@ gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op)
 
   mode_size_ptr = pad->vorbis_mode_sizes;
 
+  if (size > G_N_ELEMENTS (pad->vorbis_mode_sizes)) {
+    return -1;
+  }
+
   for (i = 0; i < size; i++) {
     offset = (offset + 1) % 8;
     if (offset == 0)