bug 59893: commit the changes from attachment 34068 that were unrelated to available()

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1783347 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Javen O'Neal 2017-02-17 08:39:05 +00:00
parent 3aae3f0a5f
commit 9330f2ac74
16 changed files with 167 additions and 99 deletions

View File

@ -126,9 +126,10 @@ public class TreeReaderListener implements POIFSReaderListener
{
DocumentDescriptor d;
final DocumentInputStream is = event.getStream();
if (!is.markSupported())
if (!is.markSupported()) {
throw new UnsupportedOperationException(is.getClass().getName() +
" does not support mark().");
}
/* Try do handle this document as a property set. We receive
* an exception if is no property set and handle it as a
@ -146,11 +147,7 @@ public class TreeReaderListener implements POIFSReaderListener
}
catch (Exception t)
{
System.err.println
("Unexpected exception while processing " +
event.getName() + " in " + event.getPath().toString());
t.printStackTrace(System.err);
throw new RuntimeException(t.getMessage());
throw new RuntimeException("Unexpected exception while processing " + event.getName() + " in " + event.getPath(), t);
}
is.close();
@ -181,9 +178,10 @@ public class TreeReaderListener implements POIFSReaderListener
final MutableTreeNode root)
{
MutableTreeNode n = pathToNode.get(path);
if (n != null)
if (n != null) {
/* Node found in map, just return it. */
return n;
}
if (path.length() == 0)
{
/* This is the root path of the POI filesystem. Its tree

View File

@ -37,6 +37,7 @@ import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.NotImplemented;
/**
* Represents a property set in the Horrible Property Set Format
@ -419,17 +420,17 @@ public class PropertySet {
*/
int o = offset;
final int byteOrder = LittleEndian.getUShort(src, o);
o += LittleEndian.SHORT_SIZE;
o += LittleEndianConsts.SHORT_SIZE;
if (byteOrder != BYTE_ORDER_ASSERTION) {
return false;
}
final int format = LittleEndian.getUShort(src, o);
o += LittleEndian.SHORT_SIZE;
o += LittleEndianConsts.SHORT_SIZE;
if (format != FORMAT_ASSERTION) {
return false;
}
// final long osVersion = LittleEndian.getUInt(src, offset);
o += LittleEndian.INT_SIZE;
o += LittleEndianConsts.INT_SIZE;
// final ClassID classID = new ClassID(src, offset);
o += ClassID.LENGTH;
final long sectionCount = LittleEndian.getUInt(src, o);
@ -460,15 +461,15 @@ public class PropertySet {
*/
int o = offset;
byteOrder = LittleEndian.getUShort(src, o);
o += LittleEndian.SHORT_SIZE;
o += LittleEndianConsts.SHORT_SIZE;
format = LittleEndian.getUShort(src, o);
o += LittleEndian.SHORT_SIZE;
o += LittleEndianConsts.SHORT_SIZE;
osVersion = (int) LittleEndian.getUInt(src, o);
o += LittleEndian.INT_SIZE;
o += LittleEndianConsts.INT_SIZE;
classID = new ClassID(src, o);
o += ClassID.LENGTH;
final int sectionCount = LittleEndian.getInt(src, o);
o += LittleEndian.INT_SIZE;
o += LittleEndianConsts.INT_SIZE;
if (sectionCount < 0) {
throw new HPSFRuntimeException("Section count " + sectionCount + " is negative.");
}
@ -492,7 +493,7 @@ public class PropertySet {
*/
for (int i = 0; i < sectionCount; i++) {
final Section s = new MutableSection(src, o);
o += ClassID.LENGTH + LittleEndian.INT_SIZE;
o += ClassID.LENGTH + LittleEndianConsts.INT_SIZE;
sections.add(s);
}
}
@ -835,6 +836,8 @@ public class PropertySet {
/**
* @see Object#hashCode()
*/
@NotImplemented
@Override
public int hashCode() {
throw new UnsupportedOperationException("FIXME: Not yet implemented.");
}
@ -844,6 +847,7 @@ public class PropertySet {
/**
* @see Object#toString()
*/
@Override
public String toString() {
final StringBuilder b = new StringBuilder();
final int sectionCount = getSectionCount();

View File

@ -199,6 +199,7 @@ import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.StringUtil;
import org.apache.poi.util.SuppressForbidden;
/**
* Utility for reading in BIFF8 records and displaying data from them.
@ -612,7 +613,9 @@ public final class BiffViewer {
public void processRecord(int globalOffset, int recordCounter, int sid, int dataSize,
byte[] data) {
String header = formatRecordDetails(globalOffset, sid, dataSize, recordCounter);
if(!_noHeader) _headers.add(header);
if(!_noHeader) {
_headers.add(header);
}
Writer w = _hexDumpWriter;
if (w != null) {
try {
@ -708,6 +711,7 @@ public final class BiffViewer {
}
@Override
@SuppressForbidden("just delegating the call")
public int available() throws IOException {
return _currentSize - _currentPos + _is.available();
}

View File

@ -58,12 +58,10 @@ public final class ObjRecord extends Record implements Cloneable {
public ObjRecord(RecordInputStream in) {
// TODO - problems with OBJ sub-records stream
// MS spec says first sub-record is always CommonObjectDataSubRecord,
// and last is
// always EndSubRecord. OOO spec does not mention ObjRecord(0x005D).
// and last is always EndSubRecord. OOO spec does not mention ObjRecord(0x005D).
// Existing POI test data seems to violate that rule. Some test data
// seems to contain
// garbage, and a crash is only averted by stopping at what looks like
// the 'EndSubRecord'
// seems to contain garbage, and a crash is only averted by stopping at
// what looks like the 'EndSubRecord'
// Check if this can be continued, if so then the
// following wont work properly
@ -141,10 +139,9 @@ public final class ObjRecord extends Record implements Cloneable {
sb.append("[OBJ]\n");
if(subrecords != null) { // there are special cases where this can be, see comments in constructor above
for (int i = 0; i < subrecords.size(); i++) {
SubRecord record = subrecords.get(i);
sb.append("SUBRECORD: ").append(record.toString());
}
for (final SubRecord record : subrecords) {
sb.append("SUBRECORD: ").append(record.toString());
}
}
sb.append("[/OBJ]\n");
return sb.toString();
@ -156,8 +153,7 @@ public final class ObjRecord extends Record implements Cloneable {
return _uninterpretedData.length + 4;
}
int size = 0;
for (int i=subrecords.size()-1; i>=0; i--) {
SubRecord record = subrecords.get(i);
for (SubRecord record : subrecords) {
size += record.getDataSize()+4;
}
if (_isPaddedToQuadByteMultiple) {
@ -203,6 +199,7 @@ public final class ObjRecord extends Record implements Cloneable {
return sid;
}
// FIXME: return Collections.unmodifiableList?
public List<SubRecord> getSubRecords() {
return subrecords;
}
@ -223,9 +220,8 @@ public final class ObjRecord extends Record implements Cloneable {
public ObjRecord clone() {
ObjRecord rec = new ObjRecord();
for (int i = 0; i < subrecords.size(); i++) {
SubRecord record = subrecords.get(i);
rec.addSubRecord((SubRecord) record.clone());
for (SubRecord record : subrecords) {
rec.addSubRecord(record.clone());
}
return rec;
}

View File

@ -84,10 +84,12 @@ public abstract class SubRecord {
}
public abstract void serialize(LittleEndianOutput out);
public abstract Object clone();
@Override
public abstract SubRecord clone();
/**
* Wether this record terminates the sub-record stream.
* Whether this record terminates the sub-record stream.
* There are two cases when this method must be overridden and return <code>true</code>
* - EndSubRecord (sid = 0x00)
* - LbsDataSubRecord (sid = 0x12)
@ -109,19 +111,23 @@ public abstract class SubRecord {
in.readFully(buf);
_data = buf;
}
@Override
protected int getDataSize() {
return _data.length;
}
@Override
public void serialize(LittleEndianOutput out) {
out.writeShort(_sid);
out.writeShort(_data.length);
out.write(_data);
}
public Object clone() {
@Override
public UnknownSubRecord clone() {
return this;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer(64);
StringBuilder sb = new StringBuilder(64);
sb.append(getClass().getName()).append(" [");
sb.append("sid=").append(HexDump.shortToHex(_sid));
sb.append(" size=").append(_data.length);

View File

@ -76,11 +76,9 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
@Override
public int read() throws IOException {
byte[] b = new byte[1];
if (read(b) == 1) {
return b[0];
}
return -1;
byte[] b = { 0 };
// FIXME: compare against -1 or 1?
return (read(b) == -1) ? -1 : b[0];
}
// do not implement! -> recursion

View File

@ -64,6 +64,7 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
// the cipher can't be final, because for the last chunk we change the padding
// and therefore need to change the cipher too
private Cipher cipher;
private boolean isClosed = false;
public ChunkedCipherOutputStream(DirectoryNode dir, int chunkSize) throws IOException, GeneralSecurityException {
super(null);
@ -224,6 +225,13 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
@Override
public void close() throws IOException {
if (isClosed) {
LOG.log(POILogger.DEBUG, "ChunkedCipherOutputStream was already closed - ignoring");
return;
}
isClosed = true;
try {
writeChunk(false);

View File

@ -30,6 +30,7 @@ import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
import org.apache.poi.poifs.property.DirectoryProperty;
import org.apache.poi.poifs.property.Property;
import org.apache.poi.poifs.property.PropertyTable;
import org.apache.poi.poifs.property.RootProperty;
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
import org.apache.poi.poifs.storage.BlockList;
import org.apache.poi.poifs.storage.HeaderBlock;
@ -94,13 +95,15 @@ public class POIFSReader
new PropertyTable(header_block, data_blocks);
// process documents
RootProperty root = properties.getRoot();
processProperties(SmallBlockTableReader
.getSmallDocumentBlocks(
header_block.getBigBlockSize(),
data_blocks, properties.getRoot(),
header_block.getSBATStart()),
data_blocks, properties.getRoot()
.getChildren(), new POIFSDocumentPath());
data_blocks, root,
header_block.getSBATStart()
),
data_blocks, root.getChildren(), new POIFSDocumentPath()
);
}
/**

View File

@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.SuppressForbidden;
/**
* This class provides methods to read a DocumentEntry managed by a
@ -86,6 +87,7 @@ public class DocumentInputStream extends InputStream implements LittleEndianInpu
}
@Override
@SuppressForbidden("just delegating")
public int available() {
return delegate.available();
}

View File

@ -40,13 +40,13 @@ public final class NDocumentInputStream extends DocumentInputStream {
private int _marked_offset_count;
/** the Document's size */
private int _document_size;
private final int _document_size;
/** have we been closed? */
private boolean _closed;
/** the actual Document */
private NPOIFSDocument _document;
private final NPOIFSDocument _document;
private Iterator<ByteBuffer> _data;
private ByteBuffer _buffer;
@ -97,6 +97,15 @@ public final class NDocumentInputStream extends DocumentInputStream {
@Override
public int available() {
return remainingBytes();
}
/**
* Helper methods for forbidden api calls
*
* @return the bytes remaining until the end of the stream
*/
private int remainingBytes() {
if (_closed) {
throw new IllegalStateException("cannot perform requested operation on a closed stream");
}
@ -146,7 +155,7 @@ public final class NDocumentInputStream extends DocumentInputStream {
if (atEOD()) {
return EOF;
}
int limit = Math.min(available(), len);
int limit = Math.min(remainingBytes(), len);
readFully(b, off, limit);
return limit;
}
@ -297,13 +306,13 @@ public final class NDocumentInputStream extends DocumentInputStream {
return LittleEndian.getUShort(data);
}
@Override
public int readUByte() {
checkAvaliable(1);
byte[] data = new byte[1];
readFully(data, 0, 1);
if(data[0] >= 0)
return data[0];
return data[0] + 256;
}
@Override
public int readUByte() {
checkAvaliable(1);
byte[] data = new byte[1];
readFully(data, 0, 1);
if (data[0] >= 0)
return data[0];
return data[0] + 256;
}
}

View File

@ -33,13 +33,13 @@ public final class ODocumentInputStream extends DocumentInputStream {
private int _marked_offset;
/** the Document's size */
private int _document_size;
private final int _document_size;
/** have we been closed? */
private boolean _closed;
/** the actual Document */
private OPOIFSDocument _document;
private final OPOIFSDocument _document;
/** the data block containing the current stream pointer */
private DataInputBlock _currentBlock;

View File

@ -26,8 +26,6 @@ import java.io.InputStream;
*
* This class does not buffer any input, so the stream read position maintained
* by this class is consistent with that of the inner stream.
*
* @author Josh Micich
*/
public class LittleEndianInputStream extends FilterInputStream implements LittleEndianInput {
public LittleEndianInputStream(InputStream is) {
@ -35,7 +33,8 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
}
@Override
public int available() {
@SuppressForbidden("just delegating")
public int available() {
try {
return super.available();
} catch (IOException e) {
@ -44,12 +43,12 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
}
@Override
public byte readByte() {
public byte readByte() {
return (byte)readUByte();
}
@Override
public int readUByte() {
public int readUByte() {
byte buf[] = new byte[1];
try {
checkEOF(read(buf), 1);
@ -60,15 +59,15 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
}
@Override
public double readDouble() {
public double readDouble() {
return Double.longBitsToDouble(readLong());
}
@Override
public int readInt() {
byte buf[] = new byte[LittleEndianConsts.INT_SIZE];
public int readInt() {
byte buf[] = new byte[LittleEndianConsts.INT_SIZE];
try {
checkEOF(read(buf), buf.length);
checkEOF(read(buf), buf.length);
} catch (IOException e) {
throw new RuntimeException(e);
}
@ -82,13 +81,14 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
* @exception RuntimeException
* wraps any IOException thrown from reading the stream.
*/
//@Override
public long readUInt() {
long retNum = readInt();
return retNum & 0x00FFFFFFFFL;
}
@Override
public long readLong() {
public long readLong() {
byte buf[] = new byte[LittleEndianConsts.LONG_SIZE];
try {
checkEOF(read(buf), LittleEndianConsts.LONG_SIZE);
@ -99,12 +99,12 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
}
@Override
public short readShort() {
public short readShort() {
return (short)readUShort();
}
@Override
public int readUShort() {
public int readUShort() {
byte buf[] = new byte[LittleEndianConsts.SHORT_SIZE];
try {
checkEOF(read(buf), LittleEndianConsts.SHORT_SIZE);
@ -120,19 +120,19 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
}
}
@Override
@Override
public void readFully(byte[] buf) {
readFully(buf, 0, buf.length);
}
readFully(buf, 0, buf.length);
}
@Override
@Override
public void readFully(byte[] buf, int off, int len) {
try {
checkEOF(read(buf, off, len), len);
} catch (IOException e) {
try {
checkEOF(read(buf, off, len), len);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Override
public void readPlain(byte[] buf, int off, int len) {

View File

@ -42,6 +42,7 @@ import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.storage.HeaderBlockConstants;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.Removal;
public final class ZipHelper {
/**
@ -54,7 +55,11 @@ public final class ZipHelper {
* Buffer to read data from file. Use big buffer to improve performaces. the
* InputStream class is reading only 8192 bytes per read call (default value
* set by sun)
*
* @deprecated in POI 3.16-beta3, not used anymore
*/
@Deprecated
@Removal(version="3.18")
public static final int READ_WRITE_FILE_BUFFER_SIZE = 8192;
/**
@ -74,8 +79,9 @@ public final class ZipHelper {
PackageRelationship corePropsRel = pkg.getRelationshipsByType(
PackageRelationshipTypes.CORE_PROPERTIES).getRelationship(0);
if (corePropsRel == null)
if (corePropsRel == null) {
return null;
}
return new ZipEntry(corePropsRel.getTargetURI().getPath());
}
@ -91,8 +97,9 @@ public final class ZipHelper {
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if (entry.getName().equals(
ContentTypeManager.CONTENT_TYPES_PART_NAME))
ContentTypeManager.CONTENT_TYPES_PART_NAME)) {
return entry;
}
}
return null;
}
@ -106,8 +113,9 @@ public final class ZipHelper {
* @return An OPC compliant name.
*/
public static String getOPCNameFromZipItemName(String zipItemName) {
if (zipItemName == null)
throw new IllegalArgumentException("zipItemName");
if (zipItemName == null) {
throw new IllegalArgumentException("zipItemName cannot be null");
}
if (zipItemName.startsWith(FORWARD_SLASH)) {
return zipItemName;
}
@ -123,12 +131,14 @@ public final class ZipHelper {
* @return A zip item name without any leading slashes.
*/
public static String getZipItemNameFromOPCName(String opcItemName) {
if (opcItemName == null)
throw new IllegalArgumentException("opcItemName");
if (opcItemName == null) {
throw new IllegalArgumentException("opcItemName cannot be null");
}
String retVal = opcItemName;
while (retVal.startsWith(FORWARD_SLASH))
while (retVal.startsWith(FORWARD_SLASH)) {
retVal = retVal.substring(1);
}
return retVal;
}
@ -141,12 +151,14 @@ public final class ZipHelper {
* @return A zip URI without any leading slashes.
*/
public static URI getZipURIFromOPCName(String opcItemName) {
if (opcItemName == null)
if (opcItemName == null) {
throw new IllegalArgumentException("opcItemName");
}
String retVal = opcItemName;
while (retVal.startsWith(FORWARD_SLASH))
while (retVal.startsWith(FORWARD_SLASH)) {
retVal = retVal.substring(1);
}
try {
return new URI(retVal);
} catch (URISyntaxException e) {

View File

@ -44,8 +44,6 @@ import org.w3c.dom.Element;
/**
* Zip part marshaller. This marshaller is use to save any part in a zip stream.
*
* @author Julien Chable
*/
public final class ZipPartMarshaller implements PartMarshaller {
private final static POILogger logger = POILogFactory.getLogger(ZipPartMarshaller.class);
@ -56,6 +54,7 @@ public final class ZipPartMarshaller implements PartMarshaller {
* @throws OpenXML4JException
* Throws if an internal exception is thrown.
*/
@Override
public boolean marshall(PackagePart part, OutputStream os)
throws OpenXML4JException {
if (!(os instanceof ZipOutputStream)) {

View File

@ -160,6 +160,7 @@ public class ZipSecureFile extends ZipFile {
* @throws IOException if an I/O error has occurred
* @throws IllegalStateException if the zip file has been closed
*/
@Override
@SuppressWarnings("resource")
public InputStream getInputStream(ZipEntry entry) throws IOException {
InputStream zipIS = super.getInputStream(entry);
@ -170,6 +171,7 @@ public class ZipSecureFile extends ZipFile {
ThresholdInputStream newInner;
if (zipIS instanceof InflaterInputStream) {
newInner = AccessController.doPrivileged(new PrivilegedAction<ThresholdInputStream>() { // NOSONAR
@Override
@SuppressForbidden("TODO: Fix this to not use reflection (it will break in Java 9)! " +
"Better would be to wrap *before* instead of trying to insert wrapper afterwards.")
public ThresholdInputStream run() {
@ -177,9 +179,9 @@ public class ZipSecureFile extends ZipFile {
Field f = FilterInputStream.class.getDeclaredField("in");
f.setAccessible(true);
InputStream oldInner = (InputStream)f.get(zipIS);
ThresholdInputStream newInner = new ThresholdInputStream(oldInner, null);
f.set(zipIS, newInner);
return newInner;
ThresholdInputStream newInner2 = new ThresholdInputStream(oldInner, null);
f.set(zipIS, newInner2);
return newInner2;
} catch (Exception ex) {
LOG.log(POILogger.WARN, "SecurityManager doesn't allow manipulation via reflection for zipbomb detection - continue with original input stream", ex);
}
@ -203,24 +205,31 @@ public class ZipSecureFile extends ZipFile {
this.cis = cis;
}
@Override
public int read() throws IOException {
int b = in.read();
if (b > -1) advance(1);
if (b > -1) {
advance(1);
}
return b;
}
@Override
public int read(byte b[], int off, int len) throws IOException {
int cnt = in.read(b, off, len);
if (cnt > -1) advance(cnt);
if (cnt > -1) {
advance(cnt);
}
return cnt;
}
@Override
public long skip(long n) throws IOException {
counter = 0;
return in.skip(n);
}
@Override
public synchronized void reset() throws IOException {
counter = 0;
in.reset();
@ -277,31 +286,41 @@ public class ZipSecureFile extends ZipFile {
((ZipInputStream)in).closeEntry();
}
@Override
public void unread(int b) throws IOException {
if (!(in instanceof PushbackInputStream)) {
throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream");
}
if (--counter < 0) counter = 0;
if (--counter < 0) {
counter = 0;
}
((PushbackInputStream)in).unread(b);
}
@Override
public void unread(byte[] b, int off, int len) throws IOException {
if (!(in instanceof PushbackInputStream)) {
throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream");
}
counter -= len;
if (--counter < 0) counter = 0;
if (--counter < 0) {
counter = 0;
}
((PushbackInputStream)in).unread(b, off, len);
}
@Override
@SuppressForbidden("just delegating")
public int available() throws IOException {
return in.available();
}
@Override
public boolean markSupported() {
return in.markSupported();
}
@Override
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}

View File

@ -50,6 +50,8 @@ public class TestDecryptor {
Decryptor d = Decryptor.getInstance(info);
assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
fs.close();
}
@Test
@ -63,6 +65,8 @@ public class TestDecryptor {
d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
zipOk(fs.getRoot(), d);
fs.close();
}
@Test
@ -78,6 +82,8 @@ public class TestDecryptor {
assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
zipOk(fs.getRoot(), d);
fs.close();
}
private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException {
@ -85,9 +91,13 @@ public class TestDecryptor {
while (true) {
ZipEntry entry = zin.getNextEntry();
if (entry==null) break;
if (entry==null) {
break;
}
// crc32 is checked within zip-stream
if (entry.isDirectory()) continue;
if (entry.isDirectory()) {
continue;
}
zin.skip(entry.getSize());
byte buf[] = new byte[10];
int readBytes = zin.read(buf);
@ -182,4 +192,4 @@ public class TestDecryptor {
fs.close();
}
}
}