8166288: Au file format can be validated better

Reviewed-by: amenkov
This commit is contained in:
Sergey Bylokhov 2016-09-25 02:55:18 +03:00
parent 0ee1f71b81
commit ec6f109b23
4 changed files with 78 additions and 10 deletions

View File

@ -44,7 +44,7 @@ import javax.sound.sampled.UnsupportedAudioFileException;
public final class AuFileReader extends SunFileReader {
@Override
public StandardFileFormat getAudioFileFormatImpl(final InputStream stream)
StandardFileFormat getAudioFileFormatImpl(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
final DataInputStream dis = new DataInputStream(stream);
final int magic = dis.readInt();
@ -55,9 +55,15 @@ public final class AuFileReader extends SunFileReader {
}
final int headerSize = dis.readInt();
if (headerSize < AuFileFormat.AU_HEADERSIZE) {
throw new UnsupportedAudioFileException("Invalid header size");
}
final long /* unsigned int */ dataSize = dis.readInt() & 0xffffffffL;
final int auType = dis.readInt();
final int sampleRate = dis.readInt();
if (sampleRate <= 0) {
throw new UnsupportedAudioFileException("Invalid sample rate");
}
final int channels = dis.readInt();
if (channels <= 0) {
throw new UnsupportedAudioFileException("Invalid number of channels");
@ -119,10 +125,19 @@ public final class AuFileReader extends SunFileReader {
// unsupported filetype, throw exception
throw new UnsupportedAudioFileException("not a valid AU file");
}
// now seek past the header
// Skip the variable-length annotation field. The content of this field
// is currently undefined by AU specification and is unsupported by
// JavaSound, so seek past the header
dis.skipBytes(headerSize - AuFileFormat.AU_HEADERSIZE);
// Even if the sampleSizeInBits and channels are supported we can get an
// unsupported frameSize because of overflow
final int frameSize = calculatePCMFrameSize(sampleSizeInBits, channels);
if (frameSize <= 0) {
throw new UnsupportedAudioFileException("Invalid frame size");
}
//$$fb 2002-11-02: fix for 4629669: AU file reader: problems with empty files
//$$fb 2003-10-20: fix for 4940459: AudioInputStream.getFrameLength() returns 0 instead of NOT_SPECIFIED
long frameLength = AudioSystem.NOT_SPECIFIED;

View File

@ -252,6 +252,10 @@ abstract class SunFileReader extends AudioFileReader {
* @return the size of a PCM frame in bytes.
*/
static final int calculatePCMFrameSize(int sampleSizeInBits, int channels) {
return ((sampleSizeInBits + 7) / 8) * channels;
try {
return Math.multiplyExact((sampleSizeInBits + 7) / 8, channels);
} catch (final ArithmeticException ignored) {
return 0;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2016, 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
@ -74,11 +74,56 @@ public final class ReadersExceptions {
// empty channels
static byte[] wrongAUCh =
{0x2e, 0x73, 0x6e, 0x64,//AiffFileFormat.AU_SUN_MAGIC
0, 0, 0, 0, // headerSize
0, 0, 0, 24, // headerSize
0, 0, 0, 0, // dataSize
0, 0, 0, 1, // encoding_local AuFileFormat.AU_ULAW_8
0, 0, 0, 1, // sampleRate
0, 0, 0, 0 // channels
};
// empty sample rate
static byte[] wrongAUSR =
{0x2e, 0x73, 0x6e, 0x64,//AiffFileFormat.AU_SUN_MAGIC
0, 0, 0, 24, // headerSize
0, 0, 0, 0, // dataSize
0, 0, 0, 1, // encoding_local AuFileFormat.AU_ULAW_8
0, 0, 0, 0, // sampleRate
0, 0, 0, 0 // channels
0, 0, 0, 1 // channels
};
// empty header size
static byte[] wrongAUEmptyHeader =
{0x2e, 0x73, 0x6e, 0x64,//AiffFileFormat.AU_SUN_MAGIC
0, 0, 0, 0, // headerSize
0, 0, 0, 0, // dataSize
0, 0, 0, 1, // encoding_local AuFileFormat.AU_ULAW_8
0, 0, 0, 1, // sampleRate
0, 0, 0, 1 // channels
};
// small header size
static byte[] wrongAUSmallHeader =
{0x2e, 0x73, 0x6e, 0x64,//AiffFileFormat.AU_SUN_MAGIC
0, 0, 0, 7, // headerSize
0, 0, 0, 0, // dataSize
0, 0, 0, 1, // encoding_local AuFileFormat.AU_ULAW_8
0, 0, 0, 1, // sampleRate
0, 0, 0, 1 // channels
};
// frame size overflow, when result negative
static byte[] wrongAUFrameSizeOverflowNegativeResult =
{0x2e, 0x73, 0x6e, 0x64,//AiffFileFormat.AU_SUN_MAGIC
0, 0, 0, 24, // headerSize
0, 0, 0, 0, // dataSize
0, 0, 0, 5, // encoding_local AuFileFormat.AU_LINEAR_32
0, 0, 0, 1, // sampleRate
0x7F, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF // channels
};
// frame size overflow, when result positive
static byte[] wrongAUFrameSizeOverflowPositiveResult =
{0x2e, 0x73, 0x6e, 0x64,//AiffFileFormat.AU_SUN_MAGIC
0, 0, 0, 24, // headerSize
0, 0, 0, 0, // dataSize
0, 0, 0, 4, // encoding_local AuFileFormat.AU_LINEAR_24
0, 0, 0, 1, // sampleRate
0x7F, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF // channels
};
// empty channels
static byte[] wrongWAVCh =
@ -113,8 +158,12 @@ public final class ReadersExceptions {
0, 0, 0, 0, // dataLength
};
static byte[][] data = {wrongAIFFCh, wrongAIFFSSL, wrongAIFFSSH, wrongAUCh,
wrongWAVCh, wrongWAVSSB};
static byte[][] data = {
wrongAIFFCh, wrongAIFFSSL, wrongAIFFSSH, wrongAUCh, wrongAUSR,
wrongAUEmptyHeader, wrongAUSmallHeader,
wrongAUFrameSizeOverflowNegativeResult,
wrongAUFrameSizeOverflowPositiveResult, wrongWAVCh, wrongWAVSSB
};
public static void main(final String[] args) throws IOException {
for (final byte[] bytes : data) {

View File

@ -45,10 +45,10 @@ public final class RepeatedFormatReader {
};
private static byte[] headerAU = {0x2e, 0x73, 0x6e, 0x64, // AU_SUN_MAGIC
0, 0, 0, 0, // headerSize
0, 0, 0, 24, // headerSize
0, 0, 0, 0, // dataSize
0, 0, 0, 1, // encoding
0, 0, 0, 0, // sampleRate
0, 0, 0, 1, // sampleRate
0, 0, 0, 1 // channels
};