]> source.dussan.org Git - poi.git/commitdiff
[bug-65543] HSSF: fix issue with incomplete SSTs. Thanks to Simon Carter.
authorPJ Fanning <fanningpj@apache.org>
Fri, 6 Jan 2023 23:50:54 +0000 (23:50 +0000)
committerPJ Fanning <fanningpj@apache.org>
Fri, 6 Jan 2023 23:50:54 +0000 (23:50 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1906434 13f79535-47bb-0310-9956-ffa450edef68

poi/src/main/java/org/apache/poi/hssf/record/SSTDeserializer.java
poi/src/test/java/org/apache/poi/hssf/record/TestSSTDeserializer.java
test-data/spreadsheet/notenoughstrings.txt [new file with mode: 0644]

index b4c2d3cd7316dc78d0147a448b6bbe68bc6761c0..d840078c73e43f6f7af22586d89525af77c89147 100644 (file)
@@ -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);
     }
 }
index 20057c42ac071707f5a32dfd341a7fc341170c78..c627bbfc558dbeefd9de8b24957bb0d691cb5efd 100644 (file)
@@ -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 (file)
index 0000000..3ecc2d3
--- /dev/null
@@ -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