mirror of https://github.com/apache/poi.git
fix potential output resource leaks (LGTM)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1859592 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8784d6d6d7
commit
a59ed12ecf
|
@ -43,10 +43,10 @@ public final class FilePassRecord extends StandardRecord implements Cloneable {
|
|||
public static final short sid = 0x002F;
|
||||
private static final int ENCRYPTION_XOR = 0;
|
||||
private static final int ENCRYPTION_OTHER = 1;
|
||||
|
||||
|
||||
private final int encryptionType;
|
||||
private EncryptionInfo encryptionInfo;
|
||||
|
||||
|
||||
private FilePassRecord(FilePassRecord other) {
|
||||
encryptionType = other.encryptionType;
|
||||
try {
|
||||
|
@ -55,15 +55,15 @@ public final class FilePassRecord extends StandardRecord implements Cloneable {
|
|||
throw new EncryptedDocumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public FilePassRecord(EncryptionMode encryptionMode) {
|
||||
encryptionType = (encryptionMode == EncryptionMode.xor) ? ENCRYPTION_XOR : ENCRYPTION_OTHER;
|
||||
encryptionInfo = new EncryptionInfo(encryptionMode);
|
||||
}
|
||||
|
||||
|
||||
public FilePassRecord(RecordInputStream in) {
|
||||
encryptionType = in.readUShort();
|
||||
|
||||
|
||||
EncryptionMode preferredMode;
|
||||
switch (encryptionType) {
|
||||
case ENCRYPTION_XOR:
|
||||
|
@ -75,7 +75,7 @@ public final class FilePassRecord extends StandardRecord implements Cloneable {
|
|||
default:
|
||||
throw new EncryptedDocumentException("invalid encryption type");
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
encryptionInfo = new EncryptionInfo(in, preferredMode);
|
||||
} catch (IOException e) {
|
||||
|
@ -88,32 +88,37 @@ public final class FilePassRecord extends StandardRecord implements Cloneable {
|
|||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(encryptionType);
|
||||
|
||||
byte[] data = new byte[1024];
|
||||
LittleEndianByteArrayOutputStream bos = new LittleEndianByteArrayOutputStream(data, 0); // NOSONAR
|
||||
byte data[] = new byte[1024];
|
||||
try (LittleEndianByteArrayOutputStream bos =
|
||||
new LittleEndianByteArrayOutputStream(data, 0)) { // NOSONAR
|
||||
|
||||
switch (encryptionInfo.getEncryptionMode()) {
|
||||
case xor:
|
||||
((XOREncryptionHeader)encryptionInfo.getHeader()).write(bos);
|
||||
((XOREncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
|
||||
break;
|
||||
case binaryRC4:
|
||||
out.writeShort(encryptionInfo.getVersionMajor());
|
||||
out.writeShort(encryptionInfo.getVersionMinor());
|
||||
((BinaryRC4EncryptionHeader)encryptionInfo.getHeader()).write(bos);
|
||||
((BinaryRC4EncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
|
||||
break;
|
||||
case cryptoAPI:
|
||||
out.writeShort(encryptionInfo.getVersionMajor());
|
||||
out.writeShort(encryptionInfo.getVersionMinor());
|
||||
out.writeInt(encryptionInfo.getEncryptionFlags());
|
||||
((CryptoAPIEncryptionHeader)encryptionInfo.getHeader()).write(bos);
|
||||
((CryptoAPIEncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
|
||||
break;
|
||||
default:
|
||||
throw new EncryptedDocumentException("not supported");
|
||||
switch (encryptionInfo.getEncryptionMode()) {
|
||||
case xor:
|
||||
((XOREncryptionHeader)encryptionInfo.getHeader()).write(bos);
|
||||
((XOREncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
|
||||
break;
|
||||
case binaryRC4:
|
||||
out.writeShort(encryptionInfo.getVersionMajor());
|
||||
out.writeShort(encryptionInfo.getVersionMinor());
|
||||
((BinaryRC4EncryptionHeader)encryptionInfo.getHeader()).write(bos);
|
||||
((BinaryRC4EncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
|
||||
break;
|
||||
case cryptoAPI:
|
||||
out.writeShort(encryptionInfo.getVersionMajor());
|
||||
out.writeShort(encryptionInfo.getVersionMinor());
|
||||
out.writeInt(encryptionInfo.getEncryptionFlags());
|
||||
((CryptoAPIEncryptionHeader)encryptionInfo.getHeader()).write(bos);
|
||||
((CryptoAPIEncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
|
||||
break;
|
||||
default:
|
||||
throw new EncryptedDocumentException("not supported");
|
||||
}
|
||||
|
||||
out.write(data, 0, bos.getWriteIndex());
|
||||
} catch (IOException ioe) {
|
||||
// should never happen in practice
|
||||
throw new IllegalStateException(ioe);
|
||||
}
|
||||
|
||||
out.write(data, 0, bos.getWriteIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -132,7 +137,7 @@ public final class FilePassRecord extends StandardRecord implements Cloneable {
|
|||
public short getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FilePassRecord clone() {
|
||||
return new FilePassRecord(this);
|
||||
|
|
|
@ -14,9 +14,10 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -28,7 +29,7 @@ import org.apache.poi.util.RecordFormatException;
|
|||
|
||||
/**
|
||||
* OBJRECORD (0x005D)<p>
|
||||
*
|
||||
*
|
||||
* The obj record is used to hold various graphic objects and controls.
|
||||
*/
|
||||
public final class ObjRecord extends Record implements Cloneable {
|
||||
|
@ -36,7 +37,7 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||
|
||||
private static final int NORMAL_PAD_ALIGNMENT = 2;
|
||||
private static int MAX_PAD_ALIGNMENT = 4;
|
||||
|
||||
|
||||
private List<SubRecord> subrecords;
|
||||
/** used when POI has no idea what is going on */
|
||||
private final byte[] _uninterpretedData;
|
||||
|
@ -100,7 +101,7 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||
_isPaddedToQuadByteMultiple = subRecordData.length % MAX_PAD_ALIGNMENT == 0;
|
||||
if (nRemainingBytes >= (_isPaddedToQuadByteMultiple ? MAX_PAD_ALIGNMENT : NORMAL_PAD_ALIGNMENT)) {
|
||||
if (!canPaddingBeDiscarded(subRecordData, nRemainingBytes)) {
|
||||
String msg = "Leftover " + nRemainingBytes
|
||||
String msg = "Leftover " + nRemainingBytes
|
||||
+ " bytes in subrecord data " + HexDump.toHex(subRecordData);
|
||||
throw new RecordFormatException(msg);
|
||||
}
|
||||
|
@ -118,7 +119,7 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||
* written by a version of POI (around 3.1) which incorrectly interpreted the second short of
|
||||
* the ftLbs subrecord (0x1FEE) as a length, and read that many bytes as padding (other bugs
|
||||
* helped allow this to occur).
|
||||
*
|
||||
*
|
||||
* Excel reads files with this excessive padding OK, truncating the over-sized ObjRecord back
|
||||
* to the its proper size. POI does the same.
|
||||
*/
|
||||
|
@ -145,7 +146,7 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||
sb.append("[/OBJ]\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getRecordSize() {
|
||||
if (_uninterpretedData != null) {
|
||||
|
@ -167,31 +168,35 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||
return size + 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int serialize(int offset, byte[] data) {
|
||||
int recSize = getRecordSize();
|
||||
int dataSize = recSize - 4;
|
||||
LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(data, offset, recSize); // NOSONAR
|
||||
@Override
|
||||
public int serialize(int offset, byte[] data) {
|
||||
int recSize = getRecordSize();
|
||||
int dataSize = recSize - 4;
|
||||
|
||||
out.writeShort(sid);
|
||||
out.writeShort(dataSize);
|
||||
try (LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(data, offset, recSize)) { // NOSONAR
|
||||
out.writeShort(sid);
|
||||
out.writeShort(dataSize);
|
||||
|
||||
if (_uninterpretedData == null) {
|
||||
if (_uninterpretedData == null) {
|
||||
|
||||
for (int i = 0; i < subrecords.size(); i++) {
|
||||
SubRecord record = subrecords.get(i);
|
||||
record.serialize(out);
|
||||
}
|
||||
int expectedEndIx = offset+dataSize;
|
||||
// padding
|
||||
while (out.getWriteIndex() < expectedEndIx) {
|
||||
out.writeByte(0);
|
||||
}
|
||||
} else {
|
||||
out.write(_uninterpretedData);
|
||||
}
|
||||
return recSize;
|
||||
}
|
||||
for (int i = 0; i < subrecords.size(); i++) {
|
||||
SubRecord record = subrecords.get(i);
|
||||
record.serialize(out);
|
||||
}
|
||||
int expectedEndIx = offset + dataSize;
|
||||
// padding
|
||||
while (out.getWriteIndex() < expectedEndIx) {
|
||||
out.writeByte(0);
|
||||
}
|
||||
} else {
|
||||
out.write(_uninterpretedData);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
// should never happen in practice
|
||||
throw new IllegalStateException(ioe);
|
||||
}
|
||||
return recSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getSid() {
|
||||
|
|
|
@ -17,51 +17,62 @@
|
|||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Subclasses of this class (the majority of BIFF records) are non-continuable. This allows for
|
||||
* some simplification of serialization logic
|
||||
* Subclasses of this class (the majority of BIFF records) are non-continuable.
|
||||
* This allows for some simplification of serialization logic
|
||||
*/
|
||||
public abstract class StandardRecord extends Record {
|
||||
protected abstract int getDataSize();
|
||||
public final int getRecordSize() {
|
||||
return 4 + getDataSize();
|
||||
}
|
||||
protected abstract int getDataSize();
|
||||
|
||||
@Override
|
||||
public final int getRecordSize() {
|
||||
return 4 + getDataSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the data content of this BIFF record including the sid and record length.
|
||||
* Write the data content of this BIFF record including the sid and record
|
||||
* length.
|
||||
* <p>
|
||||
* The subclass must write the exact number of bytes as reported by
|
||||
* {@link org.apache.poi.hssf.record.Record#getRecordSize()}}
|
||||
* {@link org.apache.poi.hssf.record.Record#getRecordSize()}}
|
||||
*/
|
||||
@Override
|
||||
public final int serialize(int offset, byte[] data) {
|
||||
int dataSize = getDataSize();
|
||||
int recSize = 4 + dataSize;
|
||||
LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(data, offset, recSize);
|
||||
out.writeShort(getSid());
|
||||
out.writeShort(dataSize);
|
||||
serialize(out);
|
||||
if (out.getWriteIndex() - offset != recSize) {
|
||||
throw new IllegalStateException("Error in serialization of (" + getClass().getName() + "): "
|
||||
+ "Incorrect number of bytes written - expected "
|
||||
+ recSize + " but got " + (out.getWriteIndex() - offset));
|
||||
}
|
||||
return recSize;
|
||||
}
|
||||
@Override
|
||||
public final int serialize(int offset, byte[] data) {
|
||||
int dataSize = getDataSize();
|
||||
int recSize = 4 + dataSize;
|
||||
try (LittleEndianByteArrayOutputStream out =
|
||||
new LittleEndianByteArrayOutputStream(data, offset, recSize)) {
|
||||
out.writeShort(getSid());
|
||||
out.writeShort(dataSize);
|
||||
serialize(out);
|
||||
if (out.getWriteIndex() - offset != recSize) {
|
||||
throw new IllegalStateException("Error in serialization of (" + getClass().getName() + "): "
|
||||
+ "Incorrect number of bytes written - expected " + recSize + " but got "
|
||||
+ (out.getWriteIndex() - offset));
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
// should never happen in practice
|
||||
throw new IllegalStateException(ioe);
|
||||
}
|
||||
return recSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the data content of this BIFF record. The 'ushort sid' and 'ushort size' header fields
|
||||
* have already been written by the superclass.
|
||||
* Write the data content of this BIFF record. The 'ushort sid' and 'ushort
|
||||
* size' header fields have already been written by the superclass.
|
||||
* <p>
|
||||
* The number of bytes written must equal the record size reported by
|
||||
* {@link org.apache.poi.hssf.record.Record#getRecordSize()}} minus four
|
||||
* ( record header consisting of a 'ushort sid' and 'ushort reclength' has already been written
|
||||
* by their superclass).
|
||||
*
|
||||
* @param out the output object
|
||||
* {@link org.apache.poi.hssf.record.Record#getRecordSize()}} minus four (
|
||||
* record header consisting of a 'ushort sid' and 'ushort reclength' has
|
||||
* already been written by their superclass).
|
||||
*
|
||||
* @param out
|
||||
* the output object
|
||||
*/
|
||||
protected abstract void serialize(LittleEndianOutput out);
|
||||
protected abstract void serialize(LittleEndianOutput out);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package org.apache.poi.hssf.record.cont;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.hssf.record.ContinueRecord;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
|
@ -49,6 +51,7 @@ public abstract class ContinuableRecord extends Record {
|
|||
* (Note - if any {@link ContinueRecord} is required, this result includes the
|
||||
* size of those too)
|
||||
*/
|
||||
@Override
|
||||
public final int getRecordSize() {
|
||||
ContinuableRecordOutput out = ContinuableRecordOutput.createForCountingOnly();
|
||||
serialize(out);
|
||||
|
@ -56,12 +59,19 @@ public abstract class ContinuableRecord extends Record {
|
|||
return out.getTotalSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int serialize(int offset, byte[] data) {
|
||||
|
||||
LittleEndianOutput leo = new LittleEndianByteArrayOutputStream(data, offset);
|
||||
ContinuableRecordOutput out = new ContinuableRecordOutput(leo, getSid());
|
||||
serialize(out);
|
||||
out.terminate();
|
||||
return out.getTotalSize();
|
||||
int totalSize = 0;
|
||||
try (LittleEndianByteArrayOutputStream leo =
|
||||
new LittleEndianByteArrayOutputStream(data, offset)) {
|
||||
ContinuableRecordOutput out = new ContinuableRecordOutput(leo, getSid());
|
||||
serialize(out);
|
||||
out.terminate();
|
||||
totalSize = out.getTotalSize();
|
||||
} catch (IOException ioe) {
|
||||
// should never happen in practice
|
||||
throw new IllegalStateException(ioe);
|
||||
}
|
||||
return totalSize;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.apache.poi.ss.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -28,13 +29,13 @@ import org.apache.poi.util.LittleEndianOutput;
|
|||
* Implementation of the cell range address lists,like is described
|
||||
* in OpenOffice.org's Excel Documentation: excelfileformat.pdf sec 2.5.14 -
|
||||
* 'Cell Range Address List'
|
||||
*
|
||||
*
|
||||
* In BIFF8 there is a common way to store absolute cell range address lists in
|
||||
* several records (not formulas). A cell range address list consists of a field
|
||||
* with the number of ranges and the list of the range addresses. Each cell
|
||||
* range address (called an ADDR structure) contains 4 16-bit-values.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
|
||||
*/
|
||||
public class CellRangeAddressList {
|
||||
|
@ -48,7 +49,7 @@ public class CellRangeAddressList {
|
|||
_list = new ArrayList<>();
|
||||
}
|
||||
/**
|
||||
* Convenience constructor for creating a <tt>CellRangeAddressList</tt> with a single
|
||||
* Convenience constructor for creating a <tt>CellRangeAddressList</tt> with a single
|
||||
* <tt>CellRangeAddress</tt>. Other <tt>CellRangeAddress</tt>es may be added later.
|
||||
*/
|
||||
public CellRangeAddressList(int firstRow, int lastRow, int firstCol, int lastCol) {
|
||||
|
@ -71,7 +72,7 @@ public class CellRangeAddressList {
|
|||
* structures is automatically set when reading an Excel file and/or
|
||||
* increased when you manually add a new ADDR structure . This is the reason
|
||||
* there isn't a set method for this field .
|
||||
*
|
||||
*
|
||||
* @return number of ADDR structures
|
||||
*/
|
||||
public int countRanges() {
|
||||
|
@ -80,7 +81,7 @@ public class CellRangeAddressList {
|
|||
|
||||
/**
|
||||
* Add a cell range structure.
|
||||
*
|
||||
*
|
||||
* @param firstRow - the upper left hand corner's row
|
||||
* @param firstCol - the upper left hand corner's col
|
||||
* @param lastRow - the lower right hand corner's row
|
||||
|
@ -98,7 +99,7 @@ public class CellRangeAddressList {
|
|||
throw new RuntimeException("List is empty");
|
||||
}
|
||||
if (rangeIndex < 0 || rangeIndex >= _list.size()) {
|
||||
throw new RuntimeException("Range index (" + rangeIndex
|
||||
throw new RuntimeException("Range index (" + rangeIndex
|
||||
+ ") is outside allowable range (0.." + (_list.size()-1) + ")");
|
||||
}
|
||||
return _list.remove(rangeIndex);
|
||||
|
@ -124,9 +125,17 @@ public class CellRangeAddressList {
|
|||
|
||||
public int serialize(int offset, byte[] data) {
|
||||
int totalSize = getSize();
|
||||
serialize(new LittleEndianByteArrayOutputStream(data, offset, totalSize));
|
||||
try (LittleEndianByteArrayOutputStream lebaos =
|
||||
new LittleEndianByteArrayOutputStream(data, offset, totalSize)) {
|
||||
serialize(lebaos);
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
// should never happen in practice
|
||||
throw new IllegalStateException(ioe);
|
||||
}
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
int nItems = _list.size();
|
||||
out.writeShort(nItems);
|
||||
|
@ -135,11 +144,10 @@ public class CellRangeAddressList {
|
|||
region.serialize(out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public CellRangeAddressList copy() {
|
||||
CellRangeAddressList result = new CellRangeAddressList();
|
||||
|
||||
|
||||
int nItems = _list.size();
|
||||
for (int k = 0; k < nItems; k++) {
|
||||
CellRangeAddress region = _list.get(k);
|
||||
|
|
Loading…
Reference in New Issue