From ed527437b7ea97bfb20bab719950c84b12a6e2e1 Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Wed, 14 Feb 2018 04:25:44 -0800 Subject: [PATCH] Make ID3 GEOB frames parsing more robust Issue:#3792 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=185668919 --- RELEASENOTES.md | 2 + .../exoplayer2/metadata/id3/Id3Decoder.java | 53 ++++++++++--------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0bec6891fe7..78ea59a6bf9 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -107,6 +107,8 @@ * Release `Extractor`s on the loading thread to avoid potentially leaking resources when the playback thread has quit by the time the loading task has completed. +* ID3: Better handle malformed ID3 data + ([#3792](https://github.com/google/ExoPlayer/issues/3792). ### 2.6.1 ### diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java index 6b2e5c36753..7646af718d6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java @@ -405,14 +405,9 @@ private static TextInformationFrame decodeTxxxFrame(ParsableByteArray id3Data, i int descriptionEndIndex = indexOfEos(data, 0, encoding); String description = new String(data, 0, descriptionEndIndex, charset); - String value; int valueStartIndex = descriptionEndIndex + delimiterLength(encoding); - if (valueStartIndex < data.length) { - int valueEndIndex = indexOfEos(data, valueStartIndex, encoding); - value = new String(data, valueStartIndex, valueEndIndex - valueStartIndex, charset); - } else { - value = ""; - } + int valueEndIndex = indexOfEos(data, valueStartIndex, encoding); + String value = decodeStringIfValid(data, valueStartIndex, valueEndIndex, charset); return new TextInformationFrame("TXXX", description, value); } @@ -452,14 +447,9 @@ private static UrlLinkFrame decodeWxxxFrame(ParsableByteArray id3Data, int frame int descriptionEndIndex = indexOfEos(data, 0, encoding); String description = new String(data, 0, descriptionEndIndex, charset); - String url; int urlStartIndex = descriptionEndIndex + delimiterLength(encoding); - if (urlStartIndex < data.length) { - int urlEndIndex = indexOfZeroByte(data, urlStartIndex); - url = new String(data, urlStartIndex, urlEndIndex - urlStartIndex, "ISO-8859-1"); - } else { - url = ""; - } + int urlEndIndex = indexOfZeroByte(data, urlStartIndex); + String url = decodeStringIfValid(data, urlStartIndex, urlEndIndex, "ISO-8859-1"); return new UrlLinkFrame("WXXX", description, url); } @@ -502,13 +492,12 @@ private static GeobFrame decodeGeobFrame(ParsableByteArray id3Data, int frameSiz int filenameStartIndex = mimeTypeEndIndex + 1; int filenameEndIndex = indexOfEos(data, filenameStartIndex, encoding); - String filename = new String(data, filenameStartIndex, filenameEndIndex - filenameStartIndex, - charset); + String filename = decodeStringIfValid(data, filenameStartIndex, filenameEndIndex, charset); int descriptionStartIndex = filenameEndIndex + delimiterLength(encoding); int descriptionEndIndex = indexOfEos(data, descriptionStartIndex, encoding); - String description = new String(data, descriptionStartIndex, - descriptionEndIndex - descriptionStartIndex, charset); + String description = + decodeStringIfValid(data, descriptionStartIndex, descriptionEndIndex, charset); int objectDataStartIndex = descriptionEndIndex + delimiterLength(encoding); byte[] objectData = copyOfRangeIfValid(data, objectDataStartIndex, data.length); @@ -573,14 +562,9 @@ private static CommentFrame decodeCommentFrame(ParsableByteArray id3Data, int fr int descriptionEndIndex = indexOfEos(data, 0, encoding); String description = new String(data, 0, descriptionEndIndex, charset); - String text; int textStartIndex = descriptionEndIndex + delimiterLength(encoding); - if (textStartIndex < data.length) { - int textEndIndex = indexOfEos(data, textStartIndex, encoding); - text = new String(data, textStartIndex, textEndIndex - textStartIndex, charset); - } else { - text = ""; - } + int textEndIndex = indexOfEos(data, textStartIndex, encoding); + String text = decodeStringIfValid(data, textStartIndex, textEndIndex, charset); return new CommentFrame(language, description, text); } @@ -760,6 +744,25 @@ private static byte[] copyOfRangeIfValid(byte[] data, int from, int to) { return Arrays.copyOfRange(data, from, to); } + /** + * Returns a string obtained by decoding the specified range of {@code data} using the specified + * {@code charsetName}. An empty string is returned if the range is invalid. + * + * @param data The array from which to decode the string. + * @param from The start of the range. + * @param to The end of the range (exclusive). + * @param charsetName The name of the Charset to use. + * @return The decoded string, or an empty string if the range is invalid. + * @throws UnsupportedEncodingException If the Charset is not supported. + */ + private static String decodeStringIfValid(byte[] data, int from, int to, String charsetName) + throws UnsupportedEncodingException { + if (to <= from || to > data.length) { + return ""; + } + return new String(data, from, to - from, charsetName); + } + private static final class Id3Header { private final int majorVersion;