diff options
3 files changed, 47 insertions, 19 deletions
diff --git a/poi/src/main/java/org/apache/poi/hssf/record/SSTDeserializer.java b/poi/src/main/java/org/apache/poi/hssf/record/SSTDeserializer.java index b4c2d3cd73..d840078c73 100644 --- a/poi/src/main/java/org/apache/poi/hssf/record/SSTDeserializer.java +++ b/poi/src/main/java/org/apache/poi/hssf/record/SSTDeserializer.java @@ -29,13 +29,11 @@ import static org.apache.logging.log4j.util.Unbox.box; /** * Handles the task of deserializing a SST string. The two main entry points are */ -class SSTDeserializer -{ +class SSTDeserializer { private static final Logger LOG = LogManager.getLogger(SSTDeserializer.class); private IntMapper<UnicodeString> strings; - public SSTDeserializer( IntMapper<UnicodeString> strings ) - { + public SSTDeserializer(IntMapper<UnicodeString> strings) { this.strings = strings; } @@ -44,23 +42,21 @@ class SSTDeserializer * strings may span across multiple continuations. Read the SST record * carefully before beginning to hack. */ - public void manufactureStrings( int stringCount, RecordInputStream in ) - { - for (int i=0;i<stringCount;i++) { - // Extract exactly the count of strings from the SST record. - UnicodeString str; - if (in.available() == 0 && !in.hasNextRecord()) { - LOG.atError().log("Ran out of data before creating all the strings! String at index {}", box(i)); - str = new UnicodeString(""); - } else { - str = new UnicodeString(in); - } - addToStringTable( strings, str ); - } + public void manufactureStrings(int stringCount, RecordInputStream in) { + for (int i = 0; i < stringCount; i++) { + // Extract exactly the count of strings from the SST record. + UnicodeString str; + if (in.available() == 0 && (!in.hasNextRecord() || in.getNextSid() != ContinueRecord.sid)) { + LOG.atError().log("Ran out of data before creating all the strings! String at index {}", box(i)); + str = new UnicodeString(""); + } else { + str = new UnicodeString(in); + } + addToStringTable(strings, str); + } } - static public void addToStringTable( IntMapper<UnicodeString> strings, UnicodeString string ) - { + static public void addToStringTable(IntMapper<UnicodeString> strings, UnicodeString string) { strings.add(string); } } diff --git a/poi/src/test/java/org/apache/poi/hssf/record/TestSSTDeserializer.java b/poi/src/test/java/org/apache/poi/hssf/record/TestSSTDeserializer.java index 20057c42ac..c627bbfc55 100644 --- a/poi/src/test/java/org/apache/poi/hssf/record/TestSSTDeserializer.java +++ b/poi/src/test/java/org/apache/poi/hssf/record/TestSSTDeserializer.java @@ -120,4 +120,23 @@ final class TestSSTDeserializer { assertEquals( "At a dinner party orAt At At ", strings.get( 0 ) + "" ); } + + /** + * Ensure that invalid SST records with an incorrect number of strings specified, does not consume non-continuation records. + */ + @Test + void test65543() throws IOException { + final byte[] sstRecord = readSampleHexData("notenoughstrings.txt", "sst-record", SSTRecord.sid); + byte[] nonContinuationRecord = readSampleHexData("notenoughstrings.txt", "non-continuation-record", ExtSSTRecord.sid); + RecordInputStream in = TestcaseRecordInputStream.create(concat(sstRecord, nonContinuationRecord)); + + IntMapper<UnicodeString> strings = new IntMapper<>(); + SSTDeserializer deserializer = new SSTDeserializer(strings); + + // The record data in notenoughstrings.txt only contains 1 string, deliberately pass in a larger number. + deserializer.manufactureStrings(2, in); + + assertEquals("At a dinner party or", strings.get(0) + ""); + assertEquals("", strings.get(1) + ""); + } } diff --git a/test-data/spreadsheet/notenoughstrings.txt b/test-data/spreadsheet/notenoughstrings.txt new file mode 100644 index 0000000000..3ecc2d3fda --- /dev/null +++ b/test-data/spreadsheet/notenoughstrings.txt @@ -0,0 +1,13 @@ +[sst-record] +14 00 # String length 0x14=20 +01 # Option flag, 16bit +# String: At a dinner party or +41 00 74 00 20 00 61 00 20 00 +64 00 69 00 6E 00 6E 00 65 00 +72 00 20 00 70 00 61 00 72 00 +74 00 79 00 20 00 6F 00 72 00 + +# This is not a complete record +# It only matters that the record type is not 0x003C +[non-continuation-record] +00 11 22 33 |