/**
* 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;
}
* 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);
}
}
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) + "");
+ }
}
--- /dev/null
+[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