Bug 1200148 - Sanity check header lengths in Vorbis CodecData. r=derf, a=ritu
authorMatthew Gregan <kinetik@flim.org>
Tue, 08 Sep 2015 11:44:45 +1200
changeset 289267 b1c8608314d6a3e547a97e0adf19914cbdd31035
parent 289266 505a069e601828414e93fabe696291a1e578f504
child 289268 c5cd3b4b145c3bccc8682e07d48046a66688d6cf
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersderf, ritu
bugs1200148
milestone42.0a2
Bug 1200148 - Sanity check header lengths in Vorbis CodecData. r=derf, a=ritu
media/libnestegg/README_MOZILLA
media/libnestegg/src/nestegg.c
--- a/media/libnestegg/README_MOZILLA
+++ b/media/libnestegg/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the nestegg
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The nestegg git repository is: git://github.com/kinetiknz/nestegg.git
 
-The git commit ID used was d90e2ccac66e90c4a6f25318f8092b8596c97a67.
+The git commit ID used was c84eed87f214e2a551a971b7e9fffd9a0223d6c2.
--- a/media/libnestegg/src/nestegg.c
+++ b/media/libnestegg/src/nestegg.c
@@ -1112,35 +1112,16 @@ ne_parse(nestegg * ctx, struct ebml_elem
 
   if (r != 1)
     while (ctx->ancestor)
       ne_ctx_pop(ctx);
 
   return r;
 }
 
-static uint64_t
-ne_xiph_lace_value(unsigned char ** np)
-{
-  uint64_t lace;
-  uint64_t value;
-  unsigned char * p = *np;
-
-  lace = *p++;
-  value = lace;
-  while (lace == 255) {
-    lace = *p++;
-    value += lace;
-  }
-
-  *np = p;
-
-  return value;
-}
-
 static int
 ne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
 {
   int r;
   uint64_t lace;
 
   r = ne_read_uint(io, &lace, 1);
   if (r != 1)
@@ -2259,58 +2240,73 @@ nestegg_track_codec_data_count(nestegg *
 }
 
 int
 nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
                          unsigned char ** data, size_t * length)
 {
   struct track_entry * entry;
   struct ebml_binary codec_private;
-  uint64_t sizes[3], total;
+  uint64_t sizes[3], size, total, avail;
   unsigned char * p;
   unsigned int count, i;
 
   *data = NULL;
   *length = 0;
+  count = 1;
 
   entry = ne_find_track_entry(ctx, track);
   if (!entry)
     return -1;
 
   if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS
       && nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
     return -1;
 
   if (ne_get_binary(entry->codec_private, &codec_private) != 0)
     return -1;
 
   if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS) {
     p = codec_private.data;
+    avail = codec_private.length;
+    if (avail < 1)
+      return -1;
+
     count = *p++ + 1;
-
-    if (count > 3)
+    avail -= 1;
+
+    if (count > 3 || item >= count)
       return -1;
 
-    i = 0;
     total = 0;
-    while (--count) {
-      sizes[i] = ne_xiph_lace_value(&p);
-      total += sizes[i];
-      i += 1;
+    for (i = 0; i < count - 1; ++i) {
+      size = 0;
+      do {
+        if (avail - total <= size) {
+          return -1;
+        }
+        size += *p;
+        avail -= 1;
+      } while (*p++ == 255);
+      if (avail - total < size)
+        return -1;
+      sizes[i] = size;
+      total += size;
     }
-    sizes[i] = codec_private.length - total - (p - codec_private.data);
+    sizes[i] = avail - total;
 
     for (i = 0; i < item; ++i) {
-      if (sizes[i] > LIMIT_FRAME)
-        return -1;
       p += sizes[i];
     }
     *data = p;
     *length = sizes[item];
   } else {
+    if (item >= count)
+      return -1;
+
     *data = codec_private.data;
     *length = codec_private.length;
   }
 
   return 0;
 }
 
 int