Bug 1121757: Prevent out of bound memory access should AVC data be invalid. r=kinetik
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 16 Jan 2015 20:27:11 +1100
changeset 224149 47b586de56613cd97e2a380a769c41ab155fd4e3
parent 224148 a801540e3d141aafd04b19a627fd2c9b6b10e3f4
child 224150 17e6686b89cf3e4055320a41ce827a0237e6ddae
child 224179 b93bbdaf7980f4b21855dd6c0c5fd74803a94433
push id54140
push userjyavenard@mozilla.com
push dateFri, 16 Jan 2015 09:27:41 +0000
treeherdermozilla-inbound@47b586de5661 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs1121757
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1121757: Prevent out of bound memory access should AVC data be invalid. r=kinetik
media/libstagefright/binding/AnnexB.cpp
--- a/media/libstagefright/binding/AnnexB.cpp
+++ b/media/libstagefright/binding/AnnexB.cpp
@@ -23,24 +23,39 @@ AnnexB::ConvertSampleToAnnexB(MP4Sample*
 
   if (!IsAVCC(aSample)) {
     return;
   }
   MOZ_ASSERT(aSample->data);
 
   ConvertSampleTo4BytesAVCC(aSample);
 
-  uint8_t* d = aSample->data;
-  while (d + 4 < aSample->data + aSample->size) {
-    uint32_t nalLen = mozilla::BigEndian::readUint32(d);
-    // Overwrite the NAL length with the Annex B separator.
-    memcpy(d, kAnnexBDelimiter, ArrayLength(kAnnexBDelimiter));
-    d += 4 + nalLen;
+  if (aSample->size < 4) {
+    // Nothing to do, it's corrupted anyway.
+    return;
   }
 
+  ByteReader reader(aSample->data, aSample->size);
+
+  mozilla::Vector<uint8_t> tmp;
+  ByteWriter writer(tmp);
+
+  while (reader.Remaining() >= 4) {
+    uint32_t nalLen = reader.ReadU32();
+    const uint8_t* p = reader.Read(nalLen);
+
+    writer.Write(kAnnexBDelimiter, ArrayLength(kAnnexBDelimiter));
+    if (!p) {
+      break;
+    }
+    writer.Write(p, nalLen);
+  }
+
+  aSample->Replace(tmp.begin(), tmp.length());
+
   // Prepend the Annex B NAL with SPS and PPS tables to keyframes.
   if (aSample->is_sync_point) {
     nsRefPtr<ByteBuffer> annexB =
       ConvertExtraDataToAnnexB(aSample->extra_data);
     aSample->Prepend(annexB->Elements(), annexB->Length());
   }
 }