Commit 7b2c6127 authored by Raymond Toy's avatar Raymond Toy Committed by Commit Bot

Do not throw errors in copyFromChannel/copyToChannel

If the buffer offset lies outside the boundaries of the AudioBuffer , silently
do nothing instead of throwing an error.

This is a change in behavior where we used to throw an error if the offset was greater
than or equal to the size of the AudioBuffer.

Spec issue: https://github.com/WebAudio/web-audio-api/issues/1884

Bug: 987295
Change-Id: I61955108af0fa3072a2c7174889827781c06747e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1717185Reviewed-by: default avatarHongchan Choi <hongchan@chromium.org>
Commit-Queue: Raymond Toy <rtoy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#682321}
parent b69eeff8
...@@ -236,7 +236,7 @@ void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination, ...@@ -236,7 +236,7 @@ void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination,
void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination, void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination,
int32_t channel_number, int32_t channel_number,
uint32_t start_in_channel, uint32_t buffer_offset,
ExceptionState& exception_state) { ExceptionState& exception_state) {
if (channel_number < 0 || if (channel_number < 0 ||
static_cast<uint32_t>(channel_number) >= channels_.size()) { static_cast<uint32_t>(channel_number) >= channels_.size()) {
...@@ -253,18 +253,13 @@ void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination, ...@@ -253,18 +253,13 @@ void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination,
DOMFloat32Array* channel_data = channels_[channel_number].Get(); DOMFloat32Array* channel_data = channels_[channel_number].Get();
if (start_in_channel >= channel_data->length()) { if (buffer_offset >= channel_data->length()) {
exception_state.ThrowDOMException( // Nothing to copy if the buffer offset is past the end of the AudioBuffer.
DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange(
"startInChannel", start_in_channel, 0U,
ExceptionMessages::kInclusiveBound, channel_data->length(),
ExceptionMessages::kExclusiveBound));
return; return;
} }
unsigned count = channel_data->length() - start_in_channel; unsigned int count = channel_data->length() - buffer_offset;
count = std::min(destination.View()->length(), count); count = std::min(destination.View()->length(), count);
const float* src = channel_data->Data(); const float* src = channel_data->Data();
...@@ -272,8 +267,10 @@ void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination, ...@@ -272,8 +267,10 @@ void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination,
DCHECK(src); DCHECK(src);
DCHECK(dst); DCHECK(dst);
DCHECK_LE(count, channel_data->length());
DCHECK_LE(buffer_offset + count, channel_data->length());
memcpy(dst, src + start_in_channel, count * sizeof(*src)); memcpy(dst, src + buffer_offset, count * sizeof(*src));
} }
void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source, void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source,
...@@ -284,7 +281,7 @@ void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source, ...@@ -284,7 +281,7 @@ void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source,
void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source, void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source,
int32_t channel_number, int32_t channel_number,
uint32_t start_in_channel, uint32_t buffer_offset,
ExceptionState& exception_state) { ExceptionState& exception_state) {
if (channel_number < 0 || if (channel_number < 0 ||
static_cast<uint32_t>(channel_number) >= channels_.size()) { static_cast<uint32_t>(channel_number) >= channels_.size()) {
...@@ -300,27 +297,23 @@ void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source, ...@@ -300,27 +297,23 @@ void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source,
DOMFloat32Array* channel_data = channels_[channel_number].Get(); DOMFloat32Array* channel_data = channels_[channel_number].Get();
if (start_in_channel >= channel_data->length()) { if (buffer_offset >= channel_data->length()) {
exception_state.ThrowDOMException( // Nothing to copy if the buffer offset is past the end of the AudioBuffer.
DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange(
"startInChannel", start_in_channel, 0U,
ExceptionMessages::kInclusiveBound, channel_data->length(),
ExceptionMessages::kExclusiveBound));
return; return;
} }
unsigned count = channel_data->length() - start_in_channel; unsigned int count = channel_data->length() - buffer_offset;
count = std::min(source.View()->length(), count);
count = std::min(source.View()->length(), count);
const float* src = source.View()->Data(); const float* src = source.View()->Data();
float* dst = channel_data->Data(); float* dst = channel_data->Data();
DCHECK(src); DCHECK(src);
DCHECK(dst); DCHECK(dst);
DCHECK_LE(buffer_offset + count, channel_data->length());
DCHECK_LE(count, source.View()->length());
memcpy(dst + start_in_channel, src, count * sizeof(*dst)); memcpy(dst + buffer_offset, src, count * sizeof(*dst));
} }
void AudioBuffer::Zero() { void AudioBuffer::Zero() {
......
...@@ -95,14 +95,14 @@ class MODULES_EXPORT AudioBuffer final : public ScriptWrappable { ...@@ -95,14 +95,14 @@ class MODULES_EXPORT AudioBuffer final : public ScriptWrappable {
ExceptionState&); ExceptionState&);
void copyFromChannel(NotShared<DOMFloat32Array>, void copyFromChannel(NotShared<DOMFloat32Array>,
int32_t channel_number, int32_t channel_number,
uint32_t start_in_channel, uint32_t buffer_offset,
ExceptionState&); ExceptionState&);
void copyToChannel(NotShared<DOMFloat32Array>, void copyToChannel(NotShared<DOMFloat32Array>,
int32_t channel_number, int32_t channel_number,
ExceptionState&); ExceptionState&);
void copyToChannel(NotShared<DOMFloat32Array>, void copyToChannel(NotShared<DOMFloat32Array>,
int32_t channel_number, int32_t channel_number,
uint32_t start_in_channel, uint32_t buffer_offset,
ExceptionState&); ExceptionState&);
void Zero(); void Zero();
......
...@@ -40,6 +40,6 @@ ...@@ -40,6 +40,6 @@
// Channel access // Channel access
readonly attribute unsigned long numberOfChannels; readonly attribute unsigned long numberOfChannels;
[HighEntropy, Measure, RaisesException] Float32Array getChannelData(unsigned long channelIndex); [HighEntropy, Measure, RaisesException] Float32Array getChannelData(unsigned long channelIndex);
[HighEntropy, Measure, RaisesException] void copyFromChannel(Float32Array destination, long channelNumber, optional unsigned long startInChannel = 0); [HighEntropy, Measure, RaisesException] void copyFromChannel(Float32Array destination, long channelNumber, optional unsigned long bufferOffset = 0);
[RaisesException] void copyToChannel(Float32Array source, long channelNumber, optional unsigned long startInChannel = 0); [RaisesException] void copyToChannel(Float32Array source, long channelNumber, optional unsigned long bufferOffset = 0);
}; };
This is a testharness.js-based test.
Found 56 tests; 51 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS # AUDIT TASK RUNNER STARTED.
PASS > [initialize]
PASS Initialized values contains only the constant -1.
PASS < [initialize] All assertions passed. (total 1 assertions)
PASS > [copyFrom-exceptions]
PASS AudioBuffer.prototype.copyFromChannel does exist.
PASS 0: buffer = context.createBuffer(3, 16, context.sampleRate) did not throw an exception.
PASS 1: buffer.copyFromChannel(null, 0) threw TypeError: "Failed to execute 'copyFromChannel' on 'AudioBuffer': parameter 1 is not of type 'Float32Array'.".
PASS 2: buffer.copyFromChannel(context, 0) threw TypeError: "Failed to execute 'copyFromChannel' on 'AudioBuffer': parameter 1 is not of type 'Float32Array'.".
PASS 3: buffer.copyFromChannel(x, -1) threw IndexSizeError: "Failed to execute 'copyFromChannel' on 'AudioBuffer': The channelNumber provided (-1) is outside the range [0, 2].".
PASS 4: buffer.copyFromChannel(x, 3) threw IndexSizeError: "Failed to execute 'copyFromChannel' on 'AudioBuffer': The channelNumber provided (3) is outside the range [0, 2].".
PASS 5: buffer.copyFromChannel(x, 0, -1) threw IndexSizeError: "Failed to execute 'copyFromChannel' on 'AudioBuffer': The startInChannel provided (4294967295) is outside the range [0, 16).".
FAIL X 6: buffer.copyFromChannel(x, 0, 16) incorrectly threw IndexSizeError: "Failed to execute 'copyFromChannel' on 'AudioBuffer': The startInChannel provided (16) is outside the range [0, 16).". assert_true: expected true got false
PASS 7: buffer.copyFromChannel(x, 3) threw IndexSizeError: "Failed to execute 'copyFromChannel' on 'AudioBuffer': The channelNumber provided (3) is outside the range [0, 2].".
PASS 8: buffer.copyFromChannel(SharedArrayBuffer view, 0) threw TypeError: "Failed to execute 'copyFromChannel' on 'AudioBuffer': The provided ArrayBufferView value must not be shared.".
PASS 9: buffer.copyFromChannel(SharedArrayBuffer view, 0, 0) threw TypeError: "Failed to execute 'copyFromChannel' on 'AudioBuffer': The provided ArrayBufferView value must not be shared.".
FAIL < [copyFrom-exceptions] 1 out of 11 assertions were failed. assert_true: expected true got false
PASS > [copyTo-exceptions]
PASS AudioBuffer.prototype.copyToChannel does exist.
PASS 0: buffer.copyToChannel(null, 0) threw TypeError: "Failed to execute 'copyToChannel' on 'AudioBuffer': parameter 1 is not of type 'Float32Array'.".
PASS 1: buffer.copyToChannel(context, 0) threw TypeError: "Failed to execute 'copyToChannel' on 'AudioBuffer': parameter 1 is not of type 'Float32Array'.".
PASS 2: buffer.copyToChannel(x, -1) threw IndexSizeError: "Failed to execute 'copyToChannel' on 'AudioBuffer': The channelNumber provided (-1) is outside the range [0, 2].".
PASS 3: buffer.copyToChannel(x, 3) threw IndexSizeError: "Failed to execute 'copyToChannel' on 'AudioBuffer': The channelNumber provided (3) is outside the range [0, 2].".
PASS 4: buffer.copyToChannel(x, 0, -1) threw IndexSizeError: "Failed to execute 'copyToChannel' on 'AudioBuffer': The startInChannel provided (4294967295) is outside the range [0, 16).".
FAIL X 5: buffer.copyToChannel(x, 0, 16) incorrectly threw IndexSizeError: "Failed to execute 'copyToChannel' on 'AudioBuffer': The startInChannel provided (16) is outside the range [0, 16).". assert_true: expected true got false
PASS 6: buffer.copyToChannel(x, 3) threw IndexSizeError: "Failed to execute 'copyToChannel' on 'AudioBuffer': The channelNumber provided (3) is outside the range [0, 2].".
PASS 7: buffer.copyToChannel(SharedArrayBuffer view, 0) threw TypeError: "Failed to execute 'copyToChannel' on 'AudioBuffer': The provided ArrayBufferView value must not be shared.".
PASS 8: buffer.copyToChannel(SharedArrayBuffer view, 0, 0) threw TypeError: "Failed to execute 'copyToChannel' on 'AudioBuffer': The provided ArrayBufferView value must not be shared.".
FAIL < [copyTo-exceptions] 1 out of 10 assertions were failed. assert_true: expected true got false
PASS > [copyFrom-validate]
PASS buffer.copyFromChannel(dst8, 0) is identical to the array [1,2,3,4,5,6,7,8].
PASS buffer.copyFromChannel(dst8, 1) is identical to the array [2,3,4,5,6,7,8,9].
PASS buffer.copyFromChannel(dst8, 2) is identical to the array [3,4,5,6,7,8,9,10].
PASS buffer.copyFromChannel(dst8, 0, 1) is identical to the array [2,3,4,5,6,7,8,9].
PASS buffer.copyFromChannel(dst8, 1, 1) is identical to the array [3,4,5,6,7,8,9,10].
PASS buffer.copyFromChannel(dst8, 2, 1) is identical to the array [4,5,6,7,8,9,10,11].
PASS buffer.copyFromChannel(dst8, 0, 11) is identical to the array [12,13,14,15,16,-1,-1,-1].
PASS buffer.copyFromChannel(dst8, 1, 11) is identical to the array [13,14,15,16,17,-1,-1,-1].
PASS buffer.copyFromChannel(dst8, 2, 11) is identical to the array [14,15,16,17,18,-1,-1,-1].
PASS buffer.copyFromChannel(dst26, 0) is identical to the array [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16...].
PASS buffer.copyFromChannel(dst26, 1) is identical to the array [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17...].
PASS buffer.copyFromChannel(dst26, 2) is identical to the array [3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18...].
PASS < [copyFrom-validate] All assertions passed. (total 12 assertions)
PASS > [copyTo-validate]
PASS buffer = createConstantBuffer(context, 16, [-1,-1,-1]) did not throw an exception.
PASS buffer.copyToChannel(src, 0) is identical to the array [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16...].
PASS buffer.copyToChannel(src, 1) is identical to the array [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16...].
PASS buffer.copyToChannel(src, 2) is identical to the array [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16...].
PASS buffer.copyToChannel(src10, 0) is identical to the array [1,2,3,4,5,6,7,8,9,10,-1,-1,-1,-1,-1,-1...].
PASS buffer.copyToChannel(src10, 1) is identical to the array [1,2,3,4,5,6,7,8,9,10,-1,-1,-1,-1,-1,-1...].
PASS buffer.copyToChannel(src10, 2) is identical to the array [1,2,3,4,5,6,7,8,9,10,-1,-1,-1,-1,-1,-1...].
PASS buffer.copyToChannel(src10, 0, 5) is identical to the array [-1,-1,-1,-1,-1,1,2,3,4,5,6,7,8,9,10,-1...].
PASS buffer.copyToChannel(src10, 1, 5) is identical to the array [-1,-1,-1,-1,-1,1,2,3,4,5,6,7,8,9,10,-1...].
PASS buffer.copyToChannel(src10, 2, 5) is identical to the array [-1,-1,-1,-1,-1,1,2,3,4,5,6,7,8,9,10,-1...].
PASS < [copyTo-validate] All assertions passed. (total 10 assertions)
FAIL # AUDIT TASK RUNNER FINISHED: 2 out of 5 tasks were failed. assert_true: expected true got false
Harness: the test ran to completion.
...@@ -137,7 +137,7 @@ ...@@ -137,7 +137,7 @@
; ;
should(() => { should(() => {
buffer.copyFromChannel(x, 0, -1); buffer.copyFromChannel(x, 0, -1);
}, '5: buffer.copyFromChannel(x, 0, -1)').throw(DOMException, 'IndexSizeError'); }, '5: buffer.copyFromChannel(x, 0, -1)').notThrow();
should( should(
() => { () => {
buffer.copyFromChannel(x, 0, bufferLength); buffer.copyFromChannel(x, 0, bufferLength);
...@@ -192,7 +192,7 @@ ...@@ -192,7 +192,7 @@
.throw(DOMException, 'IndexSizeError'); .throw(DOMException, 'IndexSizeError');
should(() => { should(() => {
buffer.copyToChannel(x, 0, -1); buffer.copyToChannel(x, 0, -1);
}, '4: buffer.copyToChannel(x, 0, -1)').throw(DOMException, 'IndexSizeError'); }, '4: buffer.copyToChannel(x, 0, -1)').notThrow();
should( should(
() => { () => {
buffer.copyToChannel(x, 0, bufferLength); buffer.copyToChannel(x, 0, bufferLength);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment