shithub: opus

Download patch

ref: a214a46731b1636f8f78582885294145989d60d1
parent: fc96bb9cc7c59f99b03f8d1225cc708451b8bf45
author: Timothy B. Terriberry <tterribe@xiph.org>
date: Wed Jul 24 07:36:08 EDT 2024

Fix overflow and OOB read for large ext lengths.

With an 8+ MB packet it is possible to craft an extension length
 that would overflow, bypassing the checks to ensure the extension
 data remains inside the packet.
This patch fixes that and adds a test for it.

--- a/src/extensions.c
+++ b/src/extensions.c
@@ -69,24 +69,23 @@
          return 0;
       } else {
          opus_int32 bytes=0;
+         opus_int32 lacing;
          *header_size = 1;
          do {
             (*data)++;
             len--;
-            if (len == 0)
+            if (len < 1)
                return -1;
-            bytes += **data;
+            lacing = **data;
+            bytes += lacing;
             (*header_size)++;
-         } while (**data == 255);
+            len -= lacing;
+         } while (lacing == 255);
+         if (len < 1)
+            return -1;
          (*data)++;
          len--;
-         if (bytes <= len)
-         {
-            len -= bytes;
-            *data += bytes;
-         } else {
-            return -1;
-         }
+         *data += bytes;
          return len;
       }
    }
--- a/tests/test_opus_extensions.c
+++ b/tests/test_opus_extensions.c
@@ -303,6 +303,20 @@
    len = opus_packet_extensions_generate(packet, sizeof(packet), ext, 4, 0);
    result = opus_packet_extensions_parse(packet, len, ext_out, &nb_ext);
    expect_true(result == OPUS_BUFFER_TOO_SMALL, "expected OPUS_BUFFER_TOO_SMALL");
+
+   /* overflow for long extension length */
+   {
+      /* about 8 MB */
+#define LENSIZE ((1U<<31)/255 + 1)
+      unsigned char *buf = malloc(LENSIZE+1);
+      len = LENSIZE+1;
+      buf[0] = 33<<1 | 1;
+      memset(buf + 1, 0xFF, LENSIZE - 1);
+      buf[LENSIZE] = 0xFE;
+      result = opus_packet_extensions_parse(buf, len, ext_out, &nb_ext);
+      expect_true(result == OPUS_INVALID_PACKET, "expected OPUS_INVALID_PACKET");
+      free(buf);
+   }
 }
 
 #define NB_RANDOM_EXTENSIONS 100000000
--