From 886fe910a88ec32997472fbec3248d558a52a47c Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Thu, 22 Aug 2019 08:44:39 +0100 Subject: [PATCH] Avoid potential ArrayStoreException with audio processors The app is able to pass a more specialized array type, so the Arrays.copyOf call produces an array into which it's not valid to store arbitrary AudioProcessors. Create a new array and copy into it to avoid this problem. PiperOrigin-RevId: 264779164 --- .../android/exoplayer2/audio/DefaultAudioSink.java | 11 +++++++++-- .../exoplayer2/audio/DefaultAudioSinkTest.java | 7 +++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java index be1b7d3d53..6635ec40ac 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java @@ -37,7 +37,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; /** @@ -122,7 +121,15 @@ public final class DefaultAudioSink implements AudioSink { * audioProcessors} applied before silence skipping and playback parameters. */ public DefaultAudioProcessorChain(AudioProcessor... audioProcessors) { - this.audioProcessors = Arrays.copyOf(audioProcessors, audioProcessors.length + 2); + // The passed-in type may be more specialized than AudioProcessor[], so allocate a new array + // rather than using Arrays.copyOf. + this.audioProcessors = new AudioProcessor[audioProcessors.length + 2]; + System.arraycopy( + /* src= */ audioProcessors, + /* srcPos= */ 0, + /* dest= */ this.audioProcessors, + /* destPos= */ 0, + /* length= */ audioProcessors.length); silenceSkippingAudioProcessor = new SilenceSkippingAudioProcessor(); sonicAudioProcessor = new SonicAudioProcessor(); this.audioProcessors[audioProcessors.length] = silenceSkippingAudioProcessor; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java index d41c99183d..7adf618366 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/DefaultAudioSinkTest.java @@ -67,6 +67,13 @@ public final class DefaultAudioSinkTest { /* enableConvertHighResIntPcmToFloat= */ false); } + @Test + public void handlesSpecializedAudioProcessorArray() { + defaultAudioSink = + new DefaultAudioSink( + AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES, new TeeAudioProcessor[0]); + } + @Test public void handlesBufferAfterReset() throws Exception { configureDefaultAudioSink(CHANNEL_COUNT_STEREO);