bug 1201855 use unsigned integers for buffer positions so that negative buffer positions are impossible r=padenot
authorKarl Tomlinson <karlt+@karlt.net>
Tue, 25 Aug 2015 13:01:15 +1200
changeset 294153 358256d1f999d6472a94c6bf5e863646e224736d
parent 294152 626165ab9f6c8c0a7415505a7f7181ffa85a3195
child 294154 32d92b96e8922e6d7c78cfcd3ac2c958dc37aa75
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1201855
milestone43.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 1201855 use unsigned integers for buffer positions so that negative buffer positions are impossible r=padenot I think the limits on sample rates already ensure that mBufferPosition will not overflow, but this makes sure that there are no out of bounds reads. The node checks the parameters are > 0 before sending to the engine.
dom/media/webaudio/AudioBufferSourceNode.cpp
--- a/dom/media/webaudio/AudioBufferSourceNode.cpp
+++ b/dom/media/webaudio/AudioBufferSourceNode.cpp
@@ -108,24 +108,34 @@ public:
       NS_ERROR("Bad AudioBufferSourceNodeEngine double parameter.");
     };
   }
   virtual void SetInt32Parameter(uint32_t aIndex, int32_t aParam) override
   {
     switch (aIndex) {
     case AudioBufferSourceNode::SAMPLE_RATE: mBufferSampleRate = aParam; break;
     case AudioBufferSourceNode::BUFFERSTART:
+      MOZ_ASSERT(aParam >= 0);
       if (mBufferPosition == 0) {
         mBufferPosition = aParam;
       }
       break;
-    case AudioBufferSourceNode::BUFFEREND: mBufferEnd = aParam; break;
+    case AudioBufferSourceNode::BUFFEREND:
+      MOZ_ASSERT(aParam >= 0);
+      mBufferEnd = aParam;
+      break;
     case AudioBufferSourceNode::LOOP: mLoop = !!aParam; break;
-    case AudioBufferSourceNode::LOOPSTART: mLoopStart = aParam; break;
-    case AudioBufferSourceNode::LOOPEND: mLoopEnd = aParam; break;
+    case AudioBufferSourceNode::LOOPSTART:
+      MOZ_ASSERT(aParam >= 0);
+      mLoopStart = aParam;
+      break;
+    case AudioBufferSourceNode::LOOPEND:
+      MOZ_ASSERT(aParam >= 0);
+      mLoopEnd = aParam;
+      break;
     default:
       NS_ERROR("Bad AudioBufferSourceNodeEngine Int32Parameter");
     }
   }
   virtual void SetBuffer(already_AddRefed<ThreadSharedFloatArrayBufferList> aBuffer) override
   {
     mBuffer = aBuffer;
   }
@@ -222,17 +232,17 @@ public:
   // remaining in both the input and output buffer, and the playback rate (that
   // is, the ratio between the output samplerate and the input samplerate).
   void CopyFromInputBufferWithResampling(AudioNodeStream* aStream,
                                          AudioBlock* aOutput,
                                          uint32_t aChannels,
                                          uint32_t* aOffsetWithinBlock,
                                          uint32_t aAvailableInOutput,
                                          StreamTime* aCurrentPosition,
-                                         int32_t aBufferMax)
+                                         uint32_t aBufferMax)
   {
     if (*aOffsetWithinBlock == 0) {
       aOutput->AllocateChannels(aChannels);
     }
     SpeexResamplerState* resampler = mResampler;
     MOZ_ASSERT(aChannels > 0);
 
     if (mBufferPosition < aBufferMax) {
@@ -300,18 +310,18 @@ public:
           aOutput->ChannelFloatsForWrite(i) + *aOffsetWithinBlock;
 
         // AudioDataValue* for aIn selects the function that does not try to
         // copy and format-convert input data.
         WebAudioUtils::SpeexResamplerProcess(resampler, i,
                          static_cast<AudioDataValue*>(nullptr), &inSamples,
                          outputData, &outSamples);
         if (++i == aChannels) {
+          MOZ_ASSERT(inSamples <= mRemainingResamplerTail);
           mRemainingResamplerTail -= inSamples;
-          MOZ_ASSERT(mRemainingResamplerTail >= 0);
           *aOffsetWithinBlock += outSamples;
           *aCurrentPosition += outSamples;
           break;
         }
       }
     }
   }
 
@@ -354,17 +364,17 @@ public:
    * This function knows when it needs to allocate the output buffer, and also
    * optimizes the case where it can avoid memory allocations.
    */
   void CopyFromBuffer(AudioNodeStream* aStream,
                       AudioBlock* aOutput,
                       uint32_t aChannels,
                       uint32_t* aOffsetWithinBlock,
                       StreamTime* aCurrentPosition,
-                      int32_t aBufferMax)
+                      uint32_t aBufferMax)
   {
     MOZ_ASSERT(*aCurrentPosition < mStop);
     uint32_t availableInOutput =
       std::min<StreamTime>(WEBAUDIO_BLOCK_SIZE - *aOffsetWithinBlock,
                            mStop - *aCurrentPosition);
     if (mResampler) {
       CopyFromInputBufferWithResampling(aStream, aOutput, aChannels,
                                         aOffsetWithinBlock, availableInOutput,
@@ -387,18 +397,18 @@ public:
       TrackTicks start = *aCurrentPosition *
         mBufferSampleRate / mResamplerOutRate;
       TrackTicks end = (*aCurrentPosition + availableInOutput) *
         mBufferSampleRate / mResamplerOutRate;
       mBufferPosition += end - start;
       return;
     }
 
-    uint32_t numFrames = std::min<uint32_t>(aBufferMax - mBufferPosition,
-                                            availableInOutput);
+    uint32_t numFrames = std::min(aBufferMax - mBufferPosition,
+                                  availableInOutput);
     if (numFrames == WEBAUDIO_BLOCK_SIZE) {
       MOZ_ASSERT(mBufferPosition < aBufferMax);
       BorrowFromInputBuffer(aOutput, aChannels);
     } else {
       if (*aOffsetWithinBlock == 0) {
         aOutput->AllocateChannels(aChannels);
       }
       MOZ_ASSERT(mBufferPosition < aBufferMax);
@@ -529,21 +539,21 @@ public:
   // includes the extent of this filter.  The special value of -STREAM_TIME_MAX
   // indicates that the resampler has begun processing.
   StreamTime mBeginProcessing;
   StreamTime mStop;
   nsRefPtr<ThreadSharedFloatArrayBufferList> mBuffer;
   SpeexResamplerState* mResampler;
   // mRemainingResamplerTail, like mBufferPosition, and
   // mBufferEnd, is measured in input buffer samples.
-  int mRemainingResamplerTail;
-  int32_t mBufferEnd;
-  int32_t mLoopStart;
-  int32_t mLoopEnd;
-  int32_t mBufferPosition;
+  uint32_t mRemainingResamplerTail;
+  uint32_t mBufferEnd;
+  uint32_t mLoopStart;
+  uint32_t mLoopEnd;
+  uint32_t mBufferPosition;
   int32_t mBufferSampleRate;
   int32_t mResamplerOutRate;
   uint32_t mChannels;
   float mDopplerShift;
   AudioNodeStream* mDestination;
   AudioNodeStream* mSource;
   AudioParamTimeline mPlaybackRateTimeline;
   AudioParamTimeline mDetuneTimeline;