Remove ByteBufferBackingArray suppression from metadata decoders

PiperOrigin-RevId: 298312222
This commit is contained in:
ibaker 2020-03-02 11:11:06 +00:00 committed by Oliver Woodman
parent ea51e6ee8e
commit 2f4e88d5af
13 changed files with 174 additions and 29 deletions

View file

@ -27,7 +27,8 @@ public interface MetadataDecoder {
* Decodes a {@link Metadata} element from the provided input buffer.
*
* <p>Respects {@link ByteBuffer#limit()} of {@code inputBuffer.data}, but assumes {@link
* ByteBuffer#position()} and {@link ByteBuffer#arrayOffset()} are both zero.
* ByteBuffer#position()} and {@link ByteBuffer#arrayOffset()} are both zero and {@link
* ByteBuffer#hasArray()} is true.
*
* @param inputBuffer The input buffer to decode.
* @return The decoded metadata object, or null if the metadata could not be decoded.

View file

@ -26,13 +26,12 @@ import java.util.Arrays;
/** Decodes data encoded by {@link EventMessageEncoder}. */
public final class EventMessageDecoder implements MetadataDecoder {
@SuppressWarnings("ByteBufferBackingArray")
@Override
public Metadata decode(MetadataInputBuffer inputBuffer) {
ByteBuffer buffer = Assertions.checkNotNull(inputBuffer.data);
byte[] data = buffer.array();
int size = buffer.limit();
return new Metadata(decode(new ParsableByteArray(data, size)));
Assertions.checkArgument(
buffer.position() == 0 && buffer.hasArray() && buffer.arrayOffset() == 0);
return new Metadata(decode(new ParsableByteArray(buffer.array(), buffer.limit())));
}
public EventMessage decode(ParsableByteArray emsgData) {

View file

@ -96,11 +96,12 @@ public final class Id3Decoder implements MetadataDecoder {
this.framePredicate = framePredicate;
}
@SuppressWarnings("ByteBufferBackingArray")
@Override
@Nullable
public Metadata decode(MetadataInputBuffer inputBuffer) {
ByteBuffer buffer = Assertions.checkNotNull(inputBuffer.data);
Assertions.checkArgument(
buffer.position() == 0 && buffer.hasArray() && buffer.arrayOffset() == 0);
return decode(buffer.array(), buffer.limit());
}

View file

@ -16,13 +16,14 @@
package com.google.android.exoplayer2.metadata.emsg;
import static com.google.android.exoplayer2.testutil.TestUtil.createByteArray;
import static com.google.android.exoplayer2.testutil.TestUtil.createMetadataInputBuffer;
import static com.google.android.exoplayer2.testutil.TestUtil.joinByteArrays;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import java.nio.ByteBuffer;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -40,10 +41,8 @@ public final class EventMessageDecoderTest {
createByteArray(0, 15, 67, 211), // id = 1000403
createByteArray(0, 1, 2, 3, 4)); // message_data = {0, 1, 2, 3, 4}
EventMessageDecoder decoder = new EventMessageDecoder();
MetadataInputBuffer buffer = new MetadataInputBuffer();
buffer.data = ByteBuffer.allocate(rawEmsgBody.length).put(rawEmsgBody);
Metadata metadata = decoder.decode(buffer);
Metadata metadata = decoder.decode(createMetadataInputBuffer(rawEmsgBody));
assertThat(metadata.length()).isEqualTo(1);
EventMessage eventMessage = (EventMessage) metadata.get(0);
@ -54,4 +53,31 @@ public final class EventMessageDecoderTest {
assertThat(eventMessage.messageData).isEqualTo(new byte[]{0, 1, 2, 3, 4});
}
@Test
public void testDecodeEventMessage_failsIfPositionNonZero() {
EventMessageDecoder decoder = new EventMessageDecoder();
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data.position(1);
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
@Test
public void testDecodeEventMessage_failsIfBufferHasNoArray() {
EventMessageDecoder decoder = new EventMessageDecoder();
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data = buffer.data.asReadOnlyBuffer();
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
@Test
public void testDecodeEventMessage_failsIfArrayOffsetNonZero() {
EventMessageDecoder decoder = new EventMessageDecoder();
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data.position(1);
buffer.data = buffer.data.slice();
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
}

View file

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.metadata.emsg;
import static com.google.android.exoplayer2.testutil.TestUtil.createByteArray;
import static com.google.android.exoplayer2.testutil.TestUtil.createMetadataInputBuffer;
import static com.google.android.exoplayer2.testutil.TestUtil.joinByteArrays;
import static com.google.common.truth.Truth.assertThat;
@ -23,7 +24,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -51,8 +51,7 @@ public final class EventMessageEncoderTest {
@Test
public void encodeDecodeEventStream() throws IOException {
byte[] encodedByteArray = new EventMessageEncoder().encode(DECODED_MESSAGE);
MetadataInputBuffer buffer = new MetadataInputBuffer();
buffer.data = ByteBuffer.allocate(encodedByteArray.length).put(encodedByteArray);
MetadataInputBuffer buffer = createMetadataInputBuffer(encodedByteArray);
EventMessageDecoder decoder = new EventMessageDecoder();
Metadata metadata = decoder.decode(buffer);

View file

@ -15,11 +15,15 @@
*/
package com.google.android.exoplayer2.metadata.id3;
import static com.google.android.exoplayer2.testutil.TestUtil.createByteArray;
import static com.google.android.exoplayer2.testutil.TestUtil.createMetadataInputBuffer;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import com.google.android.exoplayer2.util.Assertions;
import java.nio.charset.Charset;
import java.util.Arrays;
@ -233,6 +237,34 @@ public final class Id3DecoderTest {
assertThat(apicFrame.pictureData).isEqualTo(new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0});
}
@Test
public void decodeFailsIfPositionNonZero() {
Id3Decoder decoder = new Id3Decoder();
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data.position(1);
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
@Test
public void decodeFailsIfBufferHasNoArray() {
Id3Decoder decoder = new Id3Decoder();
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data = buffer.data.asReadOnlyBuffer();
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
@Test
public void decodeFailsIfArrayOffsetNonZero() {
Id3Decoder decoder = new Id3Decoder();
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data.position(1);
buffer.data = buffer.data.slice();
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
public static byte[] buildSingleFrameTag(String frameId, byte[] frameData) {
return buildMultiFramesTag(new FrameSpec(frameId, frameData));
}

View file

@ -48,9 +48,10 @@ public final class AppInfoTableDecoder implements MetadataDecoder {
@Override
@Nullable
@SuppressWarnings("ByteBufferBackingArray")
public Metadata decode(MetadataInputBuffer inputBuffer) {
ByteBuffer buffer = Assertions.checkNotNull(inputBuffer.data);
Assertions.checkArgument(
buffer.position() == 0 && buffer.hasArray() && buffer.arrayOffset() == 0);
int tableId = buffer.get();
return tableId == APPLICATION_INFORMATION_TABLE_ID
? parseAit(new ParsableBitArray(buffer.array(), buffer.limit()))

View file

@ -45,9 +45,10 @@ public final class IcyDecoder implements MetadataDecoder {
}
@Override
@SuppressWarnings("ByteBufferBackingArray")
public Metadata decode(MetadataInputBuffer inputBuffer) {
ByteBuffer buffer = Assertions.checkNotNull(inputBuffer.data);
Assertions.checkArgument(
buffer.position() == 0 && buffer.hasArray() && buffer.arrayOffset() == 0);
@Nullable String icyString = decodeToString(buffer);
byte[] icyBytes = new byte[buffer.limit()];
buffer.get(icyBytes);

View file

@ -47,10 +47,11 @@ public final class SpliceInfoDecoder implements MetadataDecoder {
sectionHeader = new ParsableBitArray();
}
@SuppressWarnings("ByteBufferBackingArray")
@Override
public Metadata decode(MetadataInputBuffer inputBuffer) {
ByteBuffer buffer = Assertions.checkNotNull(inputBuffer.data);
Assertions.checkArgument(
buffer.position() == 0 && buffer.hasArray() && buffer.arrayOffset() == 0);
// Internal timestamps adjustment.
if (timestampAdjuster == null

View file

@ -15,7 +15,10 @@
*/
package com.google.android.exoplayer2.metadata.dvbsi;
import static com.google.android.exoplayer2.testutil.TestUtil.createByteArray;
import static com.google.android.exoplayer2.testutil.TestUtil.createMetadataInputBuffer;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@ -23,7 +26,6 @@ import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import com.google.android.exoplayer2.testutil.TestUtil;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -69,12 +71,32 @@ public final class AppInfoTableDecoderTest {
assertThat(metadata).isNull();
}
private static MetadataInputBuffer createMetadataInputBuffer(byte[] data) {
MetadataInputBuffer inputBuffer = new MetadataInputBuffer();
inputBuffer.data = ByteBuffer.allocate(data.length);
inputBuffer.data.put(data);
inputBuffer.data.flip();
return inputBuffer;
@Test
public void decode_failsIfPositionNonZero() {
AppInfoTableDecoder decoder = new AppInfoTableDecoder();
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data.position(1);
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
@Test
public void decode_failsIfBufferHasNoArray() {
AppInfoTableDecoder decoder = new AppInfoTableDecoder();
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data = buffer.data.asReadOnlyBuffer();
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
@Test
public void decode_failsIfArrayOffsetNonZero() {
AppInfoTableDecoder decoder = new AppInfoTableDecoder();
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data.position(1);
buffer.data = buffer.data.slice();
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
private static byte[] readTestFile(String name) throws IOException {

View file

@ -15,16 +15,18 @@
*/
package com.google.android.exoplayer2.metadata.icy;
import static com.google.android.exoplayer2.testutil.TestUtil.createByteArray;
import static com.google.android.exoplayer2.testutil.TestUtil.createMetadataInputBuffer;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.UTF_16;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertThrows;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import com.google.android.exoplayer2.testutil.TestUtil;
import java.nio.ByteBuffer;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -186,10 +188,28 @@ public final class IcyDecoderTest {
assertThat(streamInfo.url).isNull();
}
private static MetadataInputBuffer createMetadataInputBuffer(byte[] data) {
MetadataInputBuffer metadataInputBuffer = new MetadataInputBuffer();
metadataInputBuffer.data = ByteBuffer.allocate(data.length).put(data);
metadataInputBuffer.data.flip();
return metadataInputBuffer;
@Test
public void decode_failsIfPositionNonZero() {
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data.position(1);
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
@Test
public void decode_failsIfBufferHasNoArray() {
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data = buffer.data.asReadOnlyBuffer();
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
@Test
public void decode_failsIfArrayOffsetNonZero() {
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data.position(1);
buffer.data = buffer.data.slice();
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
}

View file

@ -16,7 +16,10 @@
package com.google.android.exoplayer2.metadata.scte35;
import static com.google.android.exoplayer2.C.TIME_UNSET;
import static com.google.android.exoplayer2.testutil.TestUtil.createByteArray;
import static com.google.android.exoplayer2.testutil.TestUtil.createMetadataInputBuffer;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.metadata.Metadata;
@ -162,9 +165,35 @@ public final class SpliceInfoDecoderTest {
assertThat(command.availsExpected).isEqualTo(2);
}
@Test
public void decodeFailsIfPositionNonZero() {
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data.position(1);
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
@Test
public void decodeFailsIfBufferHasNoArray() {
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data = buffer.data.asReadOnlyBuffer();
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
@Test
public void decodeFailsIfArrayOffsetNonZero() {
MetadataInputBuffer buffer = createMetadataInputBuffer(createByteArray(1, 2, 3));
buffer.data.position(1);
buffer.data = buffer.data.slice();
assertThrows(IllegalArgumentException.class, () -> decoder.decode(buffer));
}
private Metadata feedInputBuffer(byte[] data, long timeUs, long subsampleOffset) {
inputBuffer.clear();
inputBuffer.data = ByteBuffer.allocate(data.length).put(data);
inputBuffer.data.flip();
inputBuffer.timeUs = timeUs;
inputBuffer.subsampleOffsetUs = subsampleOffset;
return decoder.decode(inputBuffer);

View file

@ -34,6 +34,7 @@ import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Assertions;
@ -42,6 +43,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Random;
@ -473,4 +475,15 @@ public class TestUtil {
}
return new DefaultExtractorInput(dataSource, position, length);
}
/**
* Create a new {@link MetadataInputBuffer} and copy {@code data} into the backing {@link
* ByteBuffer}.
*/
public static MetadataInputBuffer createMetadataInputBuffer(byte[] data) {
MetadataInputBuffer buffer = new MetadataInputBuffer();
buffer.data = ByteBuffer.allocate(data.length).put(data);
buffer.data.flip();
return buffer;
}
}