8178401: Various audio files writers do not close file streams properly

Reviewed-by: prr
This commit is contained in:
Sergey Bylokhov 2017-12-10 00:08:42 -08:00
parent a8fc235f6a
commit 419e35e549
6 changed files with 149 additions and 190 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, 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
@ -113,10 +113,11 @@ public final class AiffFileWriter extends SunFileWriter {
AiffFileFormat aiffFileFormat = (AiffFileFormat)getAudioFileFormat(fileType, stream);
// first write the file without worrying about length fields
FileOutputStream fos = new FileOutputStream( out ); // throws IOException
BufferedOutputStream bos = new BufferedOutputStream( fos, bisBufferSize );
int bytesWritten = writeAiffFile(stream, aiffFileFormat, bos );
bos.close();
final int bytesWritten;
try (final FileOutputStream fos = new FileOutputStream(out);
final BufferedOutputStream bos = new BufferedOutputStream(fos)) {
bytesWritten = writeAiffFile(stream, aiffFileFormat, bos);
}
// now, if length fields were not specified, calculate them,
// open as a random access file, write the appropriate fields,
@ -134,20 +135,19 @@ public final class AiffFileWriter extends SunFileWriter {
long dataSize=ssndChunkSize-16;
//TODO possibly incorrect round
int numFrames = (int) (dataSize / ssndBlockSize);
RandomAccessFile raf=new RandomAccessFile(out, "rw");
// skip FORM magic
raf.skipBytes(4);
raf.writeInt(aiffLength-8);
// skip aiff2 magic, fver chunk, comm magic, comm size, channel count,
raf.skipBytes(4+aiffFileFormat.getFverChunkSize()+4+4+2);
// write frame count
raf.writeInt(numFrames);
// skip sample size, samplerate, SSND magic
raf.skipBytes(2+10+4);
raf.writeInt(ssndChunkSize-8);
// that's all
raf.close();
try (final RandomAccessFile raf = new RandomAccessFile(out, "rw")) {
// skip FORM magic
raf.skipBytes(4);
raf.writeInt(aiffLength - 8);
// skip aiff2 magic, fver chunk, comm magic, comm size, channel count,
raf.skipBytes(4 + aiffFileFormat.getFverChunkSize() + 4 + 4 + 2);
// write frame count
raf.writeInt(numFrames);
// skip sample size, samplerate, SSND magic
raf.skipBytes(2 + 10 + 4);
raf.writeInt(ssndChunkSize - 8);
// that's all
}
}
return bytesWritten;
@ -289,10 +289,6 @@ public final class AiffFileWriter extends SunFileWriter {
int compCode = AiffFileFormat.AIFC_PCM;
byte header[] = null;
ByteArrayInputStream headerStream = null;
ByteArrayOutputStream baos = null;
DataOutputStream dos = null;
SequenceInputStream aiffStream = null;
InputStream codedAudioStream = audioStream;
// if we need to do any format conversion, do it here....
@ -343,52 +339,39 @@ public final class AiffFileWriter extends SunFileWriter {
// Now create an AIFF stream header...
baos = new ByteArrayOutputStream();
dos = new DataOutputStream(baos);
// Write the outer FORM chunk
dos.writeInt(AiffFileFormat.AIFF_MAGIC);
dos.writeInt( (aiffLength-8) );
dos.writeInt(AiffFileFormat.AIFF_MAGIC2);
// Write a FVER chunk - only for AIFC
//dos.writeInt(FVER_MAGIC);
//dos.writeInt( (fverChunkSize-8) );
//dos.writeInt(FVER_TIMESTAMP);
// Write a COMM chunk
dos.writeInt(AiffFileFormat.COMM_MAGIC);
dos.writeInt( (commChunkSize-8) );
dos.writeShort(channels);
dos.writeInt(numFrames);
dos.writeShort(sampleSize);
write_ieee_extended(dos, sampleFramesPerSecond); // 10 bytes
//Only for AIFC
//dos.writeInt(compCode);
//dos.writeInt(compCode);
//dos.writeShort(0);
// Write the SSND chunk header
dos.writeInt(AiffFileFormat.SSND_MAGIC);
dos.writeInt( (ssndChunkSize-8) );
// ssndOffset and ssndBlockSize set to 0 upon
// recommendation in "Sound Manager" chapter in
// "Inside Macintosh Sound", pp 2-87 (from Babu)
dos.writeInt(0); // ssndOffset
dos.writeInt(0); // ssndBlockSize
// Concat this with the audioStream and return it
dos.close();
header = baos.toByteArray();
headerStream = new ByteArrayInputStream( header );
aiffStream = new SequenceInputStream(headerStream,
new NoCloseInputStream(codedAudioStream));
return aiffStream;
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final DataOutputStream dos = new DataOutputStream(baos)) {
// Write the outer FORM chunk
dos.writeInt(AiffFileFormat.AIFF_MAGIC);
dos.writeInt((aiffLength - 8));
dos.writeInt(AiffFileFormat.AIFF_MAGIC2);
// Write a FVER chunk - only for AIFC
//dos.writeInt(FVER_MAGIC);
//dos.writeInt( (fverChunkSize-8) );
//dos.writeInt(FVER_TIMESTAMP);
// Write a COMM chunk
dos.writeInt(AiffFileFormat.COMM_MAGIC);
dos.writeInt((commChunkSize - 8));
dos.writeShort(channels);
dos.writeInt(numFrames);
dos.writeShort(sampleSize);
write_ieee_extended(dos, sampleFramesPerSecond); // 10 bytes
//Only for AIFC
//dos.writeInt(compCode);
//dos.writeInt(compCode);
//dos.writeShort(0);
// Write the SSND chunk header
dos.writeInt(AiffFileFormat.SSND_MAGIC);
dos.writeInt((ssndChunkSize - 8));
// ssndOffset and ssndBlockSize set to 0 upon
// recommendation in "Sound Manager" chapter in
// "Inside Macintosh Sound", pp 2-87 (from Babu)
dos.writeInt(0); // ssndOffset
dos.writeInt(0); // ssndBlockSize
header = baos.toByteArray();
}
return new SequenceInputStream(new ByteArrayInputStream(header),
new NoCloseInputStream(codedAudioStream));
}
// HELPER METHODS

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, 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
@ -111,10 +111,11 @@ public final class AuFileWriter extends SunFileWriter {
AuFileFormat auFileFormat = (AuFileFormat)getAudioFileFormat(fileType, stream);
// first write the file without worrying about length fields
FileOutputStream fos = new FileOutputStream( out ); // throws IOException
BufferedOutputStream bos = new BufferedOutputStream( fos, bisBufferSize );
int bytesWritten = writeAuFile(stream, auFileFormat, bos );
bos.close();
final int bytesWritten;
try (final FileOutputStream fos = new FileOutputStream(out);
final BufferedOutputStream bos = new BufferedOutputStream(fos)) {
bytesWritten = writeAuFile(stream, auFileFormat, bos);
}
// now, if length fields were not specified, calculate them,
// open as a random access file, write the appropriate fields,
@ -123,14 +124,14 @@ public final class AuFileWriter extends SunFileWriter {
// $$kk: 10.22.99: jan: please either implement this or throw an exception!
// $$fb: 2001-07-13: done. Fixes Bug 4479981
RandomAccessFile raf=new RandomAccessFile(out, "rw");
if (raf.length()<=0x7FFFFFFFl) {
// skip AU magic and data offset field
raf.skipBytes(8);
raf.writeInt(bytesWritten-AuFileFormat.AU_HEADERSIZE);
// that's all
try (final RandomAccessFile raf = new RandomAccessFile(out, "rw")) {
if (raf.length() <= 0x7FFFFFFFl) {
// skip AU magic and data offset field
raf.skipBytes(8);
raf.writeInt(bytesWritten - AuFileFormat.AU_HEADERSIZE);
// that's all
}
}
raf.close();
}
return bytesWritten;
@ -191,39 +192,29 @@ public final class AuFileWriter extends SunFileWriter {
int sampleRate = (int)format.getSampleRate();
int channels = format.getChannels();
byte header[] = null;
ByteArrayInputStream headerStream = null;
ByteArrayOutputStream baos = null;
DataOutputStream dos = null;
SequenceInputStream auStream = null;
// if we need to do any format conversion, we do it here.
//$$ fb 2001-07-13: Bug 4391108
audioStream = AudioSystem.getAudioInputStream(format, audioStream);
baos = new ByteArrayOutputStream();
dos = new DataOutputStream(baos);
dos.writeInt(AuFileFormat.AU_SUN_MAGIC);
dos.writeInt(headerSize);
dos.writeInt((int)dataSizeInBytes);
dos.writeInt(auType);
dos.writeInt(sampleRate);
dos.writeInt(channels);
final byte[] header;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos)) {
dos.writeInt(AuFileFormat.AU_SUN_MAGIC);
dos.writeInt(headerSize);
dos.writeInt((int) dataSizeInBytes);
dos.writeInt(auType);
dos.writeInt(sampleRate);
dos.writeInt(channels);
header = baos.toByteArray();
}
// Now create a new InputStream from headerStream and the InputStream
// in audioStream
dos.close();
header = baos.toByteArray();
headerStream = new ByteArrayInputStream( header );
auStream = new SequenceInputStream(headerStream,
new NoCloseInputStream(audioStream));
return auStream;
return new SequenceInputStream(new ByteArrayInputStream(header),
new NoCloseInputStream(audioStream));
}
private int writeAuFile(AudioInputStream in, AuFileFormat auFileFormat, OutputStream out) throws IOException {
private int writeAuFile(AudioInputStream in, AuFileFormat auFileFormat,
OutputStream out) throws IOException {
int bytesRead = 0;
int bytesWritten = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, 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
@ -113,10 +113,11 @@ public final class WaveFileWriter extends SunFileWriter {
WaveFileFormat waveFileFormat = (WaveFileFormat)getAudioFileFormat(fileType, stream);
// first write the file without worrying about length fields
FileOutputStream fos = new FileOutputStream( out ); // throws IOException
BufferedOutputStream bos = new BufferedOutputStream( fos, bisBufferSize );
int bytesWritten = writeWaveFile(stream, waveFileFormat, bos );
bos.close();
final int bytesWritten;
try (final FileOutputStream fos = new FileOutputStream(out);
final BufferedOutputStream bos = new BufferedOutputStream(fos)) {
bytesWritten = writeWaveFile(stream, waveFileFormat, bos);
}
// now, if length fields were not specified, calculate them,
// open as a random access file, write the appropriate fields,
@ -125,16 +126,16 @@ public final class WaveFileWriter extends SunFileWriter {
int dataLength=bytesWritten-waveFileFormat.getHeaderSize();
int riffLength=dataLength + waveFileFormat.getHeaderSize() - 8;
RandomAccessFile raf=new RandomAccessFile(out, "rw");
// skip RIFF magic
raf.skipBytes(4);
raf.writeInt(big2little( riffLength ));
// skip WAVE magic, fmt_ magic, fmt_ length, fmt_ chunk, data magic
raf.skipBytes(4+4+4+WaveFileFormat.getFmtChunkSize(waveFileFormat.getWaveType())+4);
raf.writeInt(big2little( dataLength ));
// that's all
raf.close();
try (final RandomAccessFile raf = new RandomAccessFile(out, "rw")) {
// skip RIFF magic
raf.skipBytes(4);
raf.writeInt(big2little(riffLength));
// skip WAVE magic, fmt_ magic, fmt_ length, fmt_ chunk, data magic
raf.skipBytes(4 + 4 + 4 + WaveFileFormat.getFmtChunkSize(
waveFileFormat.getWaveType()) + 4);
raf.writeInt(big2little(dataLength));
// that's all
}
}
return bytesWritten;
@ -262,12 +263,6 @@ public final class WaveFileWriter extends SunFileWriter {
int length = waveFileFormat.getByteLength();
int riffLength = dataLength + headerLength - 8;
byte header[] = null;
ByteArrayInputStream headerStream = null;
ByteArrayOutputStream baos = null;
DataOutputStream dos = null;
SequenceInputStream waveStream = null;
AudioFormat audioStreamFormat = null;
AudioFormat.Encoding encoding = null;
InputStream codedAudioStream = audioStream;
@ -314,37 +309,31 @@ public final class WaveFileWriter extends SunFileWriter {
// Now push the header into a stream, concat, and return the new SequenceInputStream
baos = new ByteArrayOutputStream();
dos = new DataOutputStream(baos);
// we write in littleendian...
dos.writeInt(riffMagic);
dos.writeInt(big2little( riffLength ));
dos.writeInt(waveMagic);
dos.writeInt(fmtMagic);
dos.writeInt(big2little(fmtLength));
dos.writeShort(big2littleShort(wav_type));
dos.writeShort(big2littleShort(channels));
dos.writeInt(big2little(sampleRate));
dos.writeInt(big2little(avgBytesPerSec));
dos.writeShort(big2littleShort(blockAlign));
dos.writeShort(big2littleShort(sampleSizeInBits));
//$$fb 2002-04-16: Fix for 4636355: RIFF audio headers could be _more_ spec compliant
if (wav_type != WaveFileFormat.WAVE_FORMAT_PCM) {
// add length 0 for "codec specific data length"
dos.writeShort(0);
final byte[] header;
try (final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final DataOutputStream dos = new DataOutputStream(baos)) {
// we write in littleendian...
dos.writeInt(riffMagic);
dos.writeInt(big2little(riffLength));
dos.writeInt(waveMagic);
dos.writeInt(fmtMagic);
dos.writeInt(big2little(fmtLength));
dos.writeShort(big2littleShort(wav_type));
dos.writeShort(big2littleShort(channels));
dos.writeInt(big2little(sampleRate));
dos.writeInt(big2little(avgBytesPerSec));
dos.writeShort(big2littleShort(blockAlign));
dos.writeShort(big2littleShort(sampleSizeInBits));
//$$fb 2002-04-16: Fix for 4636355: RIFF audio headers could be _more_ spec compliant
if (wav_type != WaveFileFormat.WAVE_FORMAT_PCM) {
// add length 0 for "codec specific data length"
dos.writeShort(0);
}
dos.writeInt(dataMagic);
dos.writeInt(big2little(dataLength));
header = baos.toByteArray();
}
dos.writeInt(dataMagic);
dos.writeInt(big2little(dataLength));
dos.close();
header = baos.toByteArray();
headerStream = new ByteArrayInputStream( header );
waveStream = new SequenceInputStream(headerStream,
new NoCloseInputStream(codedAudioStream));
return waveStream;
return new SequenceInputStream(new ByteArrayInputStream(header),
new NoCloseInputStream(codedAudioStream));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2017, 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
@ -69,24 +69,23 @@ public final class WaveFloatFileWriter extends AudioFileWriter {
public void write(AudioInputStream stream, RIFFWriter writer)
throws IOException {
RIFFWriter fmt_chunk = writer.writeChunk("fmt ");
AudioFormat format = stream.getFormat();
fmt_chunk.writeUnsignedShort(3); // WAVE_FORMAT_IEEE_FLOAT
fmt_chunk.writeUnsignedShort(format.getChannels());
fmt_chunk.writeUnsignedInt((int) format.getSampleRate());
fmt_chunk.writeUnsignedInt(((int) format.getFrameRate())
* format.getFrameSize());
fmt_chunk.writeUnsignedShort(format.getFrameSize());
fmt_chunk.writeUnsignedShort(format.getSampleSizeInBits());
fmt_chunk.close();
RIFFWriter data_chunk = writer.writeChunk("data");
byte[] buff = new byte[1024];
int len;
while ((len = stream.read(buff, 0, buff.length)) != -1)
data_chunk.write(buff, 0, len);
data_chunk.close();
try (final RIFFWriter fmt_chunk = writer.writeChunk("fmt ")) {
AudioFormat format = stream.getFormat();
fmt_chunk.writeUnsignedShort(3); // WAVE_FORMAT_IEEE_FLOAT
fmt_chunk.writeUnsignedShort(format.getChannels());
fmt_chunk.writeUnsignedInt((int) format.getSampleRate());
fmt_chunk.writeUnsignedInt(((int) format.getFrameRate())
* format.getFrameSize());
fmt_chunk.writeUnsignedShort(format.getFrameSize());
fmt_chunk.writeUnsignedShort(format.getSampleSizeInBits());
}
try (RIFFWriter data_chunk = writer.writeChunk("data")) {
byte[] buff = new byte[1024];
int len;
while ((len = stream.read(buff, 0, buff.length)) != -1) {
data_chunk.write(buff, 0, len);
}
}
}
private static final class NoCloseOutputStream extends OutputStream {
@ -136,11 +135,11 @@ public final class WaveFloatFileWriter extends AudioFileWriter {
checkFormat(fileType, stream);
if (stream.getFormat().isBigEndian())
stream = toLittleEndian(stream);
RIFFWriter writer = new RIFFWriter(new NoCloseOutputStream(out), "WAVE");
write(stream, writer);
int fpointer = (int) writer.getFilePointer();
writer.close();
return fpointer;
try (final RIFFWriter writer = new RIFFWriter(
new NoCloseOutputStream(out), "WAVE")) {
write(stream, writer);
return (int) writer.getFilePointer();
}
}
@Override
@ -153,10 +152,9 @@ public final class WaveFloatFileWriter extends AudioFileWriter {
checkFormat(fileType, stream);
if (stream.getFormat().isBigEndian())
stream = toLittleEndian(stream);
RIFFWriter writer = new RIFFWriter(out, "WAVE");
write(stream, writer);
int fpointer = (int) writer.getFilePointer();
writer.close();
return fpointer;
try (final RIFFWriter writer = new RIFFWriter(out, "WAVE")) {
write(stream, writer);
return (int) writer.getFilePointer();
}
}
}

View File

@ -273,8 +273,6 @@ sun/security/ssl/X509KeyManager/PreferredKey.java 8176354 generic-
############################################################################
# jdk_sound
javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java 8178401 windows-all
javax/sound/sampled/DirectAudio/bug6372428.java 8055097 generic-all
javax/sound/sampled/Clip/bug5070081.java 8055097 generic-all
javax/sound/sampled/DataLine/LongFramePosition.java 8055097 generic-all

View File

@ -49,7 +49,7 @@ import static javax.sound.sampled.AudioSystem.NOT_SPECIFIED;
/**
* @test
* @bug 8038139
* @bug 8038139 8178401
*/
public final class FrameLengthAfterConversion {