mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 867174 - Part 2: Protect against invalid sample rates a bit harder; r=padenot
This commit is contained in:
parent
765b164af0
commit
f73325c4ae
@ -297,9 +297,16 @@ public:
|
||||
return mStart + mPosition;
|
||||
}
|
||||
|
||||
int32_t ComputeFinalOutSampleRate() const
|
||||
uint32_t ComputeFinalOutSampleRate()
|
||||
{
|
||||
return static_cast<uint32_t>(IdealAudioRate() / (mPlaybackRate * mDopplerShift));
|
||||
if (mPlaybackRate <= 0 || mPlaybackRate != mPlaybackRate) {
|
||||
mPlaybackRate = 1.0f;
|
||||
}
|
||||
if (mDopplerShift <= 0 || mDopplerShift != mDopplerShift) {
|
||||
mDopplerShift = 1.0f;
|
||||
}
|
||||
return WebAudioUtils::TruncateFloatToInt<uint32_t>(IdealAudioRate() /
|
||||
(mPlaybackRate * mDopplerShift));
|
||||
}
|
||||
|
||||
bool ShouldResample() const
|
||||
@ -317,9 +324,11 @@ public:
|
||||
mPlaybackRate = mPlaybackRateTimeline.GetValueAtTime(aStream->GetCurrentPosition());
|
||||
}
|
||||
|
||||
// Make sure the playback rate if something our resampler can work with.
|
||||
if (mPlaybackRate <= 0.0 || mPlaybackRate >= 1024) {
|
||||
// Make sure the playback rate and the doppler shift are something
|
||||
// our resampler can work with.
|
||||
if (ComputeFinalOutSampleRate() == 0) {
|
||||
mPlaybackRate = 1.0;
|
||||
mDopplerShift = 1.0;
|
||||
}
|
||||
|
||||
uint32_t currentOutSampleRate, currentInSampleRate;
|
||||
|
@ -8,6 +8,9 @@
|
||||
#define WebAudioUtils_h_
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "AudioParamTimeline.h"
|
||||
#include "MediaSegment.h"
|
||||
|
||||
@ -95,6 +98,100 @@ struct WebAudioUtils {
|
||||
static double StreamPositionToDestinationTime(TrackTicks aSourcePosition,
|
||||
AudioNodeStream* aSource,
|
||||
AudioNodeStream* aDestination);
|
||||
|
||||
/**
|
||||
* Converts a floating point value to an integral type in a safe and
|
||||
* platform agnostic way. The following program demonstrates the kinds
|
||||
* of ways things can go wrong depending on the CPU architecture you're
|
||||
* compiling for:
|
||||
*
|
||||
* #include <stdio.h>
|
||||
* volatile float r;
|
||||
* int main()
|
||||
* {
|
||||
* unsigned int q;
|
||||
* r = 1e100;
|
||||
* q = r;
|
||||
* printf("%f %d\n", r, q);
|
||||
* r = -1e100;
|
||||
* q = r;
|
||||
* printf("%f %d\n", r, q);
|
||||
* r = 1e15;
|
||||
* q = r;
|
||||
* printf("%f %x\n", r, q);
|
||||
* r = 0/0.;
|
||||
* q = r;
|
||||
* printf("%f %d\n", r, q);
|
||||
* }
|
||||
*
|
||||
* This program, when compiled for unsigned int, generates the following
|
||||
* results depending on the architecture:
|
||||
*
|
||||
* x86 and x86-64
|
||||
* ---
|
||||
* inf 0
|
||||
* -inf 0
|
||||
* 999999995904.000000 -727384064 d4a50000
|
||||
* nan 0
|
||||
*
|
||||
* ARM
|
||||
* ---
|
||||
* inf -1
|
||||
* -inf 0
|
||||
* 999999995904.000000 -1
|
||||
* nan 0
|
||||
*
|
||||
* When compiled for int, this program generates the following results:
|
||||
*
|
||||
* x86 and x86-64
|
||||
* ---
|
||||
* inf -2147483648
|
||||
* -inf -2147483648
|
||||
* 999999995904.000000 -2147483648
|
||||
* nan -2147483648
|
||||
*
|
||||
* ARM
|
||||
* ---
|
||||
* inf 2147483647
|
||||
* -inf -2147483648
|
||||
* 999999995904.000000 2147483647
|
||||
* nan 0
|
||||
*
|
||||
* Note that the caller is responsible to make sure that the value
|
||||
* passed to this function is not a NaN. This function will abort if
|
||||
* it sees a NaN.
|
||||
*/
|
||||
template <typename IntType, typename FloatType>
|
||||
static IntType TruncateFloatToInt(FloatType f)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
MOZ_STATIC_ASSERT((mozilla::IsIntegral<IntType>::value == true),
|
||||
"IntType must be an integral type");
|
||||
MOZ_STATIC_ASSERT((mozilla::IsFloatingPoint<FloatType>::value == true),
|
||||
"FloatType must be a floating point type");
|
||||
|
||||
if (f != f) {
|
||||
// It is the responsibility of the caller to deal with NaN values.
|
||||
// If we ever get to this point, we have a serious bug to fix.
|
||||
NS_RUNTIMEABORT("We should never see a NaN here");
|
||||
}
|
||||
|
||||
if (f > FloatType(numeric_limits<IntType>::max())) {
|
||||
// If the floating point value is outside of the range of maximum
|
||||
// integral value for this type, just clamp to the maximum value.
|
||||
return numeric_limits<IntType>::max();
|
||||
}
|
||||
|
||||
if (f < FloatType(numeric_limits<IntType>::min())) {
|
||||
// If the floating point value is outside of the range of minimum
|
||||
// integral value for this type, just clamp to the minimum value.
|
||||
return numeric_limits<IntType>::min();
|
||||
}
|
||||
|
||||
// Otherwise, this conversion must be well defined.
|
||||
return IntType(f);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ MOCHITEST_FILES := \
|
||||
test_bug866570.html \
|
||||
test_bug866737.html \
|
||||
test_bug867089.html \
|
||||
test_bug867174.html \
|
||||
test_bug867203.html \
|
||||
test_analyserNode.html \
|
||||
test_AudioBuffer.html \
|
||||
|
40
content/media/webaudio/test/test_bug867174.html
Normal file
40
content/media/webaudio/test/test_bug867174.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Crashtest for bug 867174</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
var ctx = new AudioContext();
|
||||
|
||||
var source = ctx.createBufferSource();
|
||||
var buffer = ctx.createBuffer(2, 2048, 8000);
|
||||
source.playbackRate.setTargetValueAtTime(0, 2, 3);
|
||||
var sp = ctx.createScriptProcessor();
|
||||
source.connect(sp);
|
||||
sp.connect(ctx.destination);
|
||||
source.start(0);
|
||||
|
||||
sp.onaudioprocess = function(e) {
|
||||
// Now set the buffer
|
||||
source.buffer = buffer;
|
||||
|
||||
ok(true, "We did not crash.");
|
||||
sp.onaudioprocess = null;
|
||||
SpecialPowers.clearUserPref("media.webaudio.enabled");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user