diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java index d859139d3..c03a66792 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java @@ -266,17 +266,22 @@ public class NPOIFSFileSystem // Grab the block size bigBlockSize = _header.getBigBlockSize(); + // Each block should only ever be used by one of the + // FAT, XFAT or Property Table. Ensure it does + ChainLoopDetector loopDetector = new ChainLoopDetector(); + // Read the FAT blocks - for(int fatAT : _header.getBATArray()) { - ByteBuffer fatData = getBlockAt(fatAT); + for(int fatAt : _header.getBATArray()) { + loopDetector.claim(fatAt); + ByteBuffer fatData = getBlockAt(fatAt); _blocks.add(BATBlock.createBATBlock(bigBlockSize, fatData)); } // Now read the XFAT blocks -// TODO Corrupt / Loop checking BATBlock xfat; int nextAt = _header.getXBATIndex(); for(int i=0; i<_header.getXBATCount(); i++) { + loopDetector.claim(nextAt); ByteBuffer fatData = getBlockAt(nextAt); xfat = BATBlock.createBATBlock(bigBlockSize, fatData); nextAt = xfat.getValueAt(bigBlockSize.getNextXBATChainOffset()); @@ -287,7 +292,6 @@ public class NPOIFSFileSystem // We're now able to load steams // Use this to read in the properties // TODO -// TODO With loop checking } /** @@ -614,6 +618,27 @@ public class NPOIFSFileSystem } } } + + /** + * Used to detect if a chain has a loop in it, so + * we can bail out with an error rather than + * spinning away for ever... + */ + private class ChainLoopDetector { + private boolean[] used_blocks; + private ChainLoopDetector() throws IOException { + used_blocks = new boolean[(int)(_data.size()/bigBlockSize.getBigBlockSize())]; + } + private void claim(int offset) { + if(used_blocks[offset]) { + throw new IllegalStateException( + "Potential loop detected - Block " + offset + + " was already claimed but was just requested again" + ); + } + used_blocks[offset] = true; + } + } /* ********** START begin implementation of POIFSViewable ********** */ diff --git a/src/java/org/apache/poi/poifs/property/PropertyFactory.java b/src/java/org/apache/poi/poifs/property/PropertyFactory.java index a4036f9d0..7dc92df2e 100644 --- a/src/java/org/apache/poi/poifs/property/PropertyFactory.java +++ b/src/java/org/apache/poi/poifs/property/PropertyFactory.java @@ -28,7 +28,7 @@ import org.apache.poi.poifs.storage.ListManagedBlock; /** * Factory for turning an array of RawDataBlock instances containing - * Proprty data into an array of proper Property objects. + * Property data into an array of proper Property objects. * * The array produced may be sparse, in that any portion of data that * should correspond to a Property, but which does not map to a proper diff --git a/src/java/org/apache/poi/poifs/property/PropertyTable.java b/src/java/org/apache/poi/poifs/property/PropertyTable.java index 3fe40d528..cce2a5a16 100644 --- a/src/java/org/apache/poi/poifs/property/PropertyTable.java +++ b/src/java/org/apache/poi/poifs/property/PropertyTable.java @@ -32,7 +32,7 @@ import org.apache.poi.poifs.storage.RawDataBlockList; /** * This class embodies the Property Table for the filesystem; this is - * basically the dsirectory for all of the documents in the + * basically the directory for all of the documents in the * filesystem. * * @author Marc Johnson (mjohnson at apache dot org)