Bug 812847 - Validate Opus channel count. r=kinetik, a=akeybl
authorTimothy B. Terriberry <tterribe@vt.edu>
Wed, 21 Nov 2012 17:54:30 -0500
changeset 117049 0996d275581dabdee6f9c37980de2151137055b4
parent 117048 8f0032f484977a74528d3eafe7193f1375e29252
child 117050 03f06a061206c6a5e28cbe7493ac02d983bc3fa0
push id1730
push userryanvm@gmail.com
push dateWed, 21 Nov 2012 23:19:47 +0000
treeherdermozilla-beta@9b66328a0d4e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik, akeybl
bugs812847
milestone18.0
Bug 812847 - Validate Opus channel count. r=kinetik, a=akeybl
content/media/ogg/nsOggCodecState.cpp
--- a/content/media/ogg/nsOggCodecState.cpp
+++ b/content/media/ogg/nsOggCodecState.cpp
@@ -933,29 +933,56 @@ bool nsOpusState::DecodeHeader(ogg_packe
       mGain = static_cast<float>(pow(10,0.05*gain_dB));
 #else
       mGain_Q16 = static_cast<int32_t>(NS_MIN(65536*pow(10,0.05*gain_dB)+0.5,
                                               static_cast<double>(INT32_MAX)));
 #endif
       mChannelMapping = aPacket->packet[18];
 
       if (mChannelMapping == 0) {
+        // Mapping family 0 only allows two channels
+        if (mChannels>2) {
+          LOG(PR_LOG_DEBUG, ("Invalid Opus file: too many channels (%d) for"
+                             " mapping family 0.", mChannels));
+          return false;
+        }
         mStreams = 1;
         mCoupledStreams = mChannels - 1;
         mMappingTable[0] = 0;
         mMappingTable[1] = 1;
-      } else if (aPacket->bytes>20+mChannels) {
-        mStreams = aPacket->packet[19];
-        mCoupledStreams = aPacket->packet[20];
-        int i;
-        for (i=0; i<mChannels; i++)
-          mMappingTable[i] = aPacket->packet[21+i];
+      } else if (mChannelMapping == 1) {
+        // Currently only up to 8 channels are defined for mapping family 1
+        if (mChannels>8) {
+          LOG(PR_LOG_DEBUG, ("Invalid Opus file: too many channels (%d) for"
+                             " mapping family 1.", mChannels));
+          return false;
+        }
+        if (aPacket->bytes>20+mChannels) {
+          mStreams = aPacket->packet[19];
+          mCoupledStreams = aPacket->packet[20];
+          int i;
+          for (i=0; i<mChannels; i++)
+            mMappingTable[i] = aPacket->packet[21+i];
+        } else {
+          LOG(PR_LOG_DEBUG, ("Invalid Opus file: channel mapping %d,"
+                             " but no channel mapping table", mChannelMapping));
+          return false;
+        }
       } else {
-        LOG(PR_LOG_DEBUG, ("Invalid Opus file: channel mapping %d,"
-                           " but no channel mapping table", mChannelMapping));
+        LOG(PR_LOG_DEBUG, ("Invalid Opus file: unsupported channel mapping "
+                           "family %d", mChannelMapping));
+        return false;
+      }
+      if (mStreams < 1) {
+        LOG(PR_LOG_DEBUG, ("Invalid Opus file: no streams"));
+        return false;
+      }
+      if (mCoupledStreams > mStreams) {
+        LOG(PR_LOG_DEBUG, ("Invalid Opus file: more coupled streams (%d) than "
+                           "total streams (%d)", mCoupledStreams, mStreams));
         return false;
       }
 
 #ifdef DEBUG
       LOG(PR_LOG_DEBUG, ("Opus stream header:"));
       LOG(PR_LOG_DEBUG, (" channels: %d", mChannels));
       LOG(PR_LOG_DEBUG, ("  preskip: %d", mPreSkip));
       LOG(PR_LOG_DEBUG, (" original: %d Hz", mNominalRate));