diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java index e808d357ce..e0ad436e2a 100644 --- a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java +++ b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java @@ -36,6 +36,11 @@ import org.apache.poi.util.LittleEndianInput; * {@link POIFSFileSystem} instance. */ public final class DocumentInputStream extends InputStream implements LittleEndianInput { + + private static int SKIP_BUFFER_SIZE = 2048; + + private static byte[] SKIP_BYTE_BUFFER = new byte[SKIP_BUFFER_SIZE]; + /** returned by read operations if we're at end of document */ private static final int EOF = -1; diff --git a/src/java/org/apache/poi/poifs/macros/VBAMacroReader.java b/src/java/org/apache/poi/poifs/macros/VBAMacroReader.java index cbb4ccba54..783ab9fdfa 100644 --- a/src/java/org/apache/poi/poifs/macros/VBAMacroReader.java +++ b/src/java/org/apache/poi/poifs/macros/VBAMacroReader.java @@ -260,10 +260,7 @@ public class VBAMacroReader implements Closeable { InputStream compressed = new DocumentInputStream(documentNode); try { // we know the offset already, so decompress immediately on-the-fly - long skippedBytes = compressed.skip(module.offset); - if (skippedBytes != module.offset) { - throw new IOException("tried to skip " + module.offset + " bytes, but actually skipped " + skippedBytes + " bytes"); - } + trySkip(compressed, module.offset); decompressed = new RLEDecompressingInputStream(compressed); module.read(decompressed); return; diff --git a/src/java/org/apache/poi/util/BoundedInputStream.java b/src/java/org/apache/poi/util/BoundedInputStream.java index 8b5a7a8dd5..df63cbc11b 100644 --- a/src/java/org/apache/poi/util/BoundedInputStream.java +++ b/src/java/org/apache/poi/util/BoundedInputStream.java @@ -131,13 +131,13 @@ public class BoundedInputStream extends InputStream { /** * Invokes the delegate's skip(long) method. * @param n the number of bytes to skip - * @return the actual number of bytes skipped + * @return the actual number of bytes skipped; might be fewer than requested * @throws IOException if an I/O error occurs */ @Override public long skip(long n) throws IOException { long toSkip = max>=0 ? Math.min(n, max-pos) : n; - long skippedBytes = in.skip(toSkip); + long skippedBytes = IOUtils.skipFully(in, toSkip); pos+=skippedBytes; return skippedBytes; } diff --git a/src/java/org/apache/poi/util/LittleEndianInputStream.java b/src/java/org/apache/poi/util/LittleEndianInputStream.java index 9a9652eb32..af61d375f2 100644 --- a/src/java/org/apache/poi/util/LittleEndianInputStream.java +++ b/src/java/org/apache/poi/util/LittleEndianInputStream.java @@ -204,6 +204,10 @@ public class LittleEndianInputStream extends FilterInputStream implements Little public void skipFully(int len) throws IOException { - IOUtils.skipFully(this, len); + long skipped = IOUtils.skipFully(this, len); + if (skipped > Integer.MAX_VALUE) { + throw new IOException("can't skip further than "+Integer.MAX_VALUE); + } + checkEOF((int)skipped, len); } } diff --git a/src/java/org/apache/poi/util/RLEDecompressingInputStream.java b/src/java/org/apache/poi/util/RLEDecompressingInputStream.java index 7cc68483c2..c84966ff22 100644 --- a/src/java/org/apache/poi/util/RLEDecompressingInputStream.java +++ b/src/java/org/apache/poi/util/RLEDecompressingInputStream.java @@ -123,6 +123,7 @@ public class RLEDecompressingInputStream extends InputStream { @Override public long skip(long n) throws IOException { + //this relies on readChunk's readFully to skipFully long length = n; while (length > 0) { if (pos >= len) { @@ -165,7 +166,7 @@ public class RLEDecompressingInputStream extends InputStream { } boolean rawChunk = (w & 0x8000) == 0; if (rawChunk) { - if (in.read(buf, 0, chunkSize) < chunkSize) { + if (IOUtils.readFully(in, buf, 0, chunkSize) < chunkSize) { throw new IllegalStateException(String.format(Locale.ROOT, "Not enough bytes read, expected %d", chunkSize)); } return chunkSize; diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveThresholdInputStream.java b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveThresholdInputStream.java index af76ffcd9e..5bcfd8f1c0 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveThresholdInputStream.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveThresholdInputStream.java @@ -31,6 +31,7 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.utils.InputStreamStatistics; import org.apache.poi.openxml4j.exceptions.NotOfficeXmlFileException; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; @Internal @@ -85,7 +86,7 @@ public class ZipArchiveThresholdInputStream extends FilterInputStream { @Override public long skip(long n) throws IOException { - long cnt = super.skip(n); + long cnt = IOUtils.skipFully(super.in, n); if (cnt > 0) { checkThreshold(); } diff --git a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java index ac24ecd909..f2b0b7be67 100644 --- a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java +++ b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java @@ -96,7 +96,7 @@ public abstract class XSSFBParser { is.readFully(buff); handleRecord(recordId, buff); } else { - long length = is.skip(recordLength); + long length = IOUtils.skipFully(is, recordLength); if (length != recordLength) { throw new XSSFBParseException("End of file reached before expected.\t"+ "Tried to skip "+recordLength + ", but only skipped "+length); diff --git a/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfFont.java b/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfFont.java index 256a7618e5..dd42fe63be 100644 --- a/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfFont.java +++ b/src/scratchpad/src/org/apache/poi/hemf/record/emf/HemfFont.java @@ -19,12 +19,10 @@ package org.apache.poi.hemf.record.emf; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; +import org.apache.poi.util.IOUtils; import org.apache.poi.common.usermodel.fonts.FontCharset; import org.apache.poi.hwmf.record.HwmfFont; -import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianInputStream; @@ -418,7 +416,10 @@ public class HemfFont extends HwmfFont { logPan.xHeight = LogFontPanose.XHeight.values()[leis.readUByte()]; // skip 2 byte to ensure 32-bit alignment of this structure. - leis.skip(2); + long skipped = IOUtils.skipFully(leis,2); + if (skipped != 2) { + throw new IOException("Didn't skip 2: "+skipped); + } size += 6*LittleEndianConsts.INT_SIZE+10* LittleEndianConsts.BYTE_SIZE+2; } else { diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java b/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java index 59ace3b599..ba90372f85 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java @@ -26,6 +26,7 @@ import java.util.zip.InflaterInputStream; import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.sl.image.ImageHeaderEMF; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Units; /** @@ -42,7 +43,7 @@ public final class EMF extends Metafile { InputStream is = new ByteArrayInputStream( rawdata ); Header header = new Header(); header.read(rawdata, CHECKSUM_SIZE); - long len = is.skip(header.getSize() + (long)CHECKSUM_SIZE); + long len = IOUtils.skipFully(is,header.getSize() + (long)CHECKSUM_SIZE); assert(len == header.getSize() + CHECKSUM_SIZE); InflaterInputStream inflater = new InflaterInputStream( is ); diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java b/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java index df55f4c687..59670e1298 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java @@ -26,6 +26,7 @@ import java.util.zip.InflaterInputStream; import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.sl.image.ImageHeaderPICT; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.Units; @@ -58,7 +59,7 @@ public final class PICT extends Metafile { Header header = new Header(); header.read(data, pos); long bs_exp = (long)pos + header.getSize(); - long bs_act = bis.skip(bs_exp); + long bs_act = IOUtils.skipFully(bis, bs_exp); if (bs_exp != bs_act) { throw new EOFException(); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java b/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java index 8f02df41de..632c6f68c1 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java @@ -26,6 +26,7 @@ import java.util.zip.InflaterInputStream; import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.sl.image.ImageHeaderWMF; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.Units; /** @@ -42,8 +43,9 @@ public final class WMF extends Metafile { InputStream is = new ByteArrayInputStream( rawdata ); Header header = new Header(); header.read(rawdata, CHECKSUM_SIZE*getUIDInstanceCount()); - long len = is.skip(header.getSize() + (long)CHECKSUM_SIZE*getUIDInstanceCount()); - assert(len == header.getSize() + CHECKSUM_SIZE*getUIDInstanceCount()); + long skipLen = header.getSize() + CHECKSUM_SIZE*getUIDInstanceCount(); + long skipped = IOUtils.skipFully(is, skipLen); + assert(skipped == skipLen); ImageHeaderWMF aldus = new ImageHeaderWMF(header.getBounds()); aldus.write(out);