OpenJDK / bsd-port / jdk9 / jdk
changeset 13649:7b510e98417c
8131974: AudioFileReader incorrectly handle EOFException
Reviewed-by: amenkov
author | serb |
---|---|
date | Fri, 01 Jan 2016 18:33:53 +0300 |
parents | 8625ef32d00c |
children | e3fb45999f71 |
files | src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java src/java.desktop/share/classes/javax/sound/sampled/AudioSystem.java test/javax/sound/sampled/spi/AudioFileReader/ShortHeader.java |
diffstat | 4 files changed, 229 insertions(+), 99 deletions(-) [+] |
line wrap: on
line diff
--- a/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java Wed Jan 20 15:10:25 2016 +0300 +++ b/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java Fri Jan 01 18:33:53 2016 +0300 @@ -25,6 +25,7 @@ package com.sun.media.sound; +import java.io.EOFException; import java.io.IOException; import java.io.InputStream; @@ -131,7 +132,8 @@ stream.mark(200); try { return getAudioInputStream(MidiSystem.getSequence(stream)); - } catch (final InvalidMidiDataException ignored) { + } catch (InvalidMidiDataException | EOFException ignored) { + // stream is unsupported or the header is less than was expected stream.reset(); throw new UnsupportedAudioFileException(); }
--- a/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java Wed Jan 20 15:10:25 2016 +0300 +++ b/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java Fri Jan 01 18:33:53 2016 +0300 @@ -27,6 +27,7 @@ import java.io.BufferedInputStream; import java.io.DataInputStream; +import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -51,6 +52,9 @@ stream.mark(200); // The biggest value which was historically used try { return getAudioFileFormatImpl(stream); + } catch (final EOFException ignored) { + // the header is less than was expected + throw new UnsupportedAudioFileException(); } finally { stream.reset(); } @@ -61,6 +65,9 @@ throws UnsupportedAudioFileException, IOException { try (InputStream is = url.openStream()) { return getAudioFileFormatImpl(new BufferedInputStream(is)); + } catch (final EOFException ignored) { + // the header is less than was expected + throw new UnsupportedAudioFileException(); } } @@ -69,6 +76,9 @@ throws UnsupportedAudioFileException, IOException { try (InputStream is = new FileInputStream(file)) { return getAudioFileFormatImpl(new BufferedInputStream(is)); + } catch (final EOFException ignored) { + // the header is less than was expected + throw new UnsupportedAudioFileException(); } } @@ -82,9 +92,10 @@ // beginning of the audio data, so return an AudioInputStream return new AudioInputStream(stream, fileFormat.getFormat(), fileFormat.getFrameLength()); - } catch (final UnsupportedAudioFileException e) { + } catch (UnsupportedAudioFileException | EOFException ignored) { + // stream is unsupported or the header is less than was expected stream.reset(); - throw e; + throw new UnsupportedAudioFileException(); } } @@ -125,6 +136,9 @@ * @throws UnsupportedAudioFileException if the stream does not point to * valid audio file data recognized by the system * @throws IOException if an I/O exception occurs + * @throws EOFException is used incorrectly by our readers instead of + * UnsupportedAudioFileException if the header is less than was + * expected */ abstract AudioFileFormat getAudioFileFormatImpl(InputStream stream) throws UnsupportedAudioFileException, IOException;
--- a/src/java.desktop/share/classes/javax/sound/sampled/AudioSystem.java Wed Jan 20 15:10:25 2016 +0300 +++ b/src/java.desktop/share/classes/javax/sound/sampled/AudioSystem.java Fri Jan 01 18:33:53 2016 +0300 @@ -25,6 +25,7 @@ package javax.sound.sampled; +import java.io.EOFException; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -919,28 +920,17 @@ * @see InputStream#markSupported * @see InputStream#mark */ - public static AudioFileFormat getAudioFileFormat(InputStream stream) + public static AudioFileFormat getAudioFileFormat(final InputStream stream) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(stream); - List<AudioFileReader> providers = getAudioFileReaders(); - AudioFileFormat format = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - format = reader.getAudioFileFormat( stream ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioFileFormat(stream); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( format==null ) { - throw new UnsupportedAudioFileException("file is not a supported file type"); - } else { - return format; - } + throw new UnsupportedAudioFileException("Stream of unsupported format"); } /** @@ -956,28 +946,17 @@ * @throws IOException if an input/output exception occurs * @throws NullPointerException if {@code url} is {@code null} */ - public static AudioFileFormat getAudioFileFormat(URL url) + public static AudioFileFormat getAudioFileFormat(final URL url) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(url); - List<AudioFileReader> providers = getAudioFileReaders(); - AudioFileFormat format = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - format = reader.getAudioFileFormat( url ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioFileFormat(url); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( format==null ) { - throw new UnsupportedAudioFileException("file is not a supported file type"); - } else { - return format; - } + throw new UnsupportedAudioFileException("URL of unsupported format"); } /** @@ -993,28 +972,17 @@ * @throws IOException if an I/O exception occurs * @throws NullPointerException if {@code file} is {@code null} */ - public static AudioFileFormat getAudioFileFormat(File file) + public static AudioFileFormat getAudioFileFormat(final File file) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(file); - List<AudioFileReader> providers = getAudioFileReaders(); - AudioFileFormat format = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - format = reader.getAudioFileFormat( file ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioFileFormat(file); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( format==null ) { - throw new UnsupportedAudioFileException("file is not a supported file type"); - } else { - return format; - } + throw new UnsupportedAudioFileException("File of unsupported format"); } /** @@ -1038,28 +1006,17 @@ * @see InputStream#markSupported * @see InputStream#mark */ - public static AudioInputStream getAudioInputStream(InputStream stream) + public static AudioInputStream getAudioInputStream(final InputStream stream) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(stream); - List<AudioFileReader> providers = getAudioFileReaders(); - AudioInputStream audioStream = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - audioStream = reader.getAudioInputStream( stream ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioInputStream(stream); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( audioStream==null ) { - throw new UnsupportedAudioFileException("could not get audio input stream from input stream"); - } else { - return audioStream; - } + throw new UnsupportedAudioFileException("Stream of unsupported format"); } /** @@ -1075,28 +1032,17 @@ * @throws IOException if an I/O exception occurs * @throws NullPointerException if {@code url} is {@code null} */ - public static AudioInputStream getAudioInputStream(URL url) + public static AudioInputStream getAudioInputStream(final URL url) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(url); - List<AudioFileReader> providers = getAudioFileReaders(); - AudioInputStream audioStream = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - audioStream = reader.getAudioInputStream( url ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioInputStream(url); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( audioStream==null ) { - throw new UnsupportedAudioFileException("could not get audio input stream from input URL"); - } else { - return audioStream; - } + throw new UnsupportedAudioFileException("URL of unsupported format"); } /** @@ -1112,28 +1058,17 @@ * @throws IOException if an I/O exception occurs * @throws NullPointerException if {@code file} is {@code null} */ - public static AudioInputStream getAudioInputStream(File file) + public static AudioInputStream getAudioInputStream(final File file) throws UnsupportedAudioFileException, IOException { Objects.requireNonNull(file); - List<AudioFileReader> providers = getAudioFileReaders(); - AudioInputStream audioStream = null; - - for(int i = 0; i < providers.size(); i++ ) { - AudioFileReader reader = providers.get(i); + for (final AudioFileReader reader : getAudioFileReaders()) { try { - audioStream = reader.getAudioInputStream( file ); // throws IOException - break; - } catch (UnsupportedAudioFileException e) { - continue; + return reader.getAudioInputStream(file); + } catch (final UnsupportedAudioFileException ignored) { } } - - if( audioStream==null ) { - throw new UnsupportedAudioFileException("could not get audio input stream from input file"); - } else { - return audioStream; - } + throw new UnsupportedAudioFileException("File of unsupported format"); } /**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/sound/sampled/spi/AudioFileReader/ShortHeader.java Fri Jan 01 18:33:53 2016 +0300 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.nio.file.Files; +import java.util.Arrays; + +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.spi.AudioFileReader; + +import static java.util.ServiceLoader.load; + +/** + * @test + * @bug 8131974 + * @summary Short files should be reported as unsupported + */ +public final class ShortHeader { + + private static byte[] W = {-12, 3, 45}; + + private static byte[] R = new byte[3]; + + public static void main(final String[] args) throws Exception { + final File file = Files.createTempFile("audio", "test").toFile(); + file.deleteOnExit(); + try (final OutputStream fos = new FileOutputStream(file)) { + fos.write(W); + } + + testAS(file); + for (final AudioFileReader afr : load(AudioFileReader.class)) { + testAFR(afr, file); + } + } + + /** + * Tests the part of AudioSystem API, which implemented via + * AudioFileReader. + * + * @see AudioSystem#getAudioFileFormat(InputStream) + * @see AudioSystem#getAudioFileFormat(File) + * @see AudioSystem#getAudioFileFormat(URL) + * @see AudioSystem#getAudioInputStream(InputStream) + * @see AudioSystem#getAudioInputStream(File) + * @see AudioSystem#getAudioInputStream(URL) + */ + private static void testAS(final File file) throws IOException { + try { + AudioSystem.getAudioFileFormat(file); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + AudioSystem.getAudioFileFormat(file.toURL()); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + AudioSystem.getAudioInputStream(file); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + AudioSystem.getAudioInputStream(file.toURL()); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + + // AudioSystem.getAudioXXX(stream) should properly reset the stream + + try (FileInputStream fis = new FileInputStream(file); + InputStream stream = new BufferedInputStream(fis)) { + + try { + AudioSystem.getAudioFileFormat(stream); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + AudioSystem.getAudioInputStream(stream); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + stream.read(R, 0, R.length); + } + + if (!Arrays.equals(R, W)) { + System.err.println("Expected = " + Arrays.toString(W)); + System.err.println("Actual = " + Arrays.toString(R)); + throw new RuntimeException(); + } + } + /** + * Tests the AudioFileReader API directly. + * + * @see AudioFileReader#getAudioFileFormat(InputStream) + * @see AudioFileReader#getAudioFileFormat(File) + * @see AudioFileReader#getAudioFileFormat(URL) + * @see AudioFileReader#getAudioInputStream(InputStream) + * @see AudioFileReader#getAudioInputStream(File) + * @see AudioFileReader#getAudioInputStream(URL) + */ + private static void testAFR(final AudioFileReader fcp, final File file) + throws Exception { + try { + fcp.getAudioFileFormat(file); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + fcp.getAudioFileFormat(file.toURL()); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + fcp.getAudioInputStream(file); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + fcp.getAudioInputStream(file.toURL()); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + + // AudioFileReader should properly reset the stream + + try (FileInputStream fis = new FileInputStream(file); + InputStream stream = new BufferedInputStream(fis)) { + + try { + fcp.getAudioFileFormat(stream); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + try { + fcp.getAudioInputStream(stream); + throw new RuntimeException(); + } catch (final UnsupportedAudioFileException ignored) { + } + stream.read(R, 0, R.length); + } + + if (!Arrays.equals(R, W)) { + System.err.println("Expected = " + Arrays.toString(W)); + System.err.println("Actual = " + Arrays.toString(R)); + throw new RuntimeException(); + } + } +}