You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ce...@apache.org on 2025/05/05 17:23:59 UTC
svn commit: r1925419 - in /poi/trunk/poi/src: main/java/org/apache/poi/hssf/record/WriteAccessRecord.java test/java/org/apache/poi/hssf/record/TestWriteAccessRecord.java
Author: centic
Date: Mon May 5 17:23:59 2025
New Revision: 1925419
URL: http://svn.apache.org/viewvc?rev=1925419&view=rev
Log:
Bug 69667: Handle slightly broken WriteAccessRecord gracefully
It seems some software creates records with invalid length.
If it uses UTF-16LE encoding, we can end up with 109 bytes,
which is invalid as UTF-16LE always requires an even number of
bytes.
Therefor we now sanitize the number of bytes we read from the
record to avoid this issue.
Also improve error message and add tests
Modified:
poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java
poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/TestWriteAccessRecord.java
Modified: poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java?rev=1925419&r1=1925418&r2=1925419&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/hssf/record/WriteAccessRecord.java Mon May 5 17:23:59 2025
@@ -108,10 +108,19 @@ public final class WriteAccessRecord ext
data = IOUtils.safelyAllocate(in.remaining(), STRING_SIZE);
in.readFully(data);
if (UTF16FLAG.isSet(is16BitFlag)) {
- byteCnt = Math.min(nChars * 2, data.length);
+ // the spec only allows up to 109 bytes for the string in this record, but it seems some broken
+ // software out there will generate invalid records
+ int min = Math.min(nChars * 2, data.length);
+
+ // make sure byteCnt is divisible by 2 as we read UTF-16LE
+ byteCnt = min - (min % 2);
+
charset = StandardCharsets.UTF_16LE;
} else {
+ // the spec only allows up to 109 bytes for the string in this record, but it seems some broken
+ // software out there will generate invalid records
byteCnt = Math.min(nChars, data.length);
+
charset = StandardCharsets.ISO_8859_1;
}
}
@@ -130,7 +139,8 @@ public final class WriteAccessRecord ext
boolean is16bit = StringUtil.hasMultibyte(username);
int encodedByteCount = username.length() * (is16bit ? 2 : 1);
if (encodedByteCount > STRING_SIZE) {
- throw new IllegalArgumentException("Name is too long: " + username);
+ throw new IllegalArgumentException("Name is too long, expecting up to " + STRING_SIZE +
+ " bytes, but had: " + encodedByteCount + " bytes: " + username);
}
field_1_username = username;
Modified: poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/TestWriteAccessRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/TestWriteAccessRecord.java?rev=1925419&r1=1925418&r2=1925419&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/TestWriteAccessRecord.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/hssf/record/TestWriteAccessRecord.java Mon May 5 17:23:59 2025
@@ -93,4 +93,47 @@ final class TestWriteAccessRecord {
confirmRecordEncoding(WriteAccessRecord.sid, expectedEncoding, rec.serialize());
}
+
+ @Test
+ void testUTF16LE() {
+ byte[] data = HexRead.readFromString(""
+ + "5c 00 70 00 1C 00 01 "
+ + "44 00 61 00 74 00 61 00 20 00 44 00 79 00 6e 00 "
+ + "61 00 6d 00 69 00 63 00 73 00 27 00 20 00 53 00 "
+ + "70 00 72 00 65 00 61 00 64 00 42 00 75 00 69 00 "
+ + "6c 00 64 00 65 00 72 00 20 00 20 00 20 00 20 00 "
+ + "20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 "
+ + "20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 "
+ + "20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 "
+ + "20 00 20 00 20 00"
+ );
+ RecordInputStream in = TestcaseRecordInputStream.create(data);
+
+ WriteAccessRecord rec = new WriteAccessRecord(in);
+
+ assertEquals("Data Dynamics' SpreadBuilder", rec.getUsername());
+ }
+
+ @Test
+ void testUTF16LE_wrong_size() {
+ // "0x51" on position 5 is an incorrect size, as it would require 162 bytes to encode as UTF-16LE
+ // the spec only allows up to 109 bytes for the string in this record, but it seems some broken
+ // software out there will generate such a file
+ byte[] data = HexRead.readFromString(""
+ + "5c 00 70 00 51 00 01 "
+ + "44 00 61 00 74 00 61 00 20 00 44 00 79 00 6e 00 "
+ + "61 00 6d 00 69 00 63 00 73 00 27 00 20 00 53 00 "
+ + "70 00 72 00 65 00 61 00 64 00 42 00 75 00 69 00 "
+ + "6c 00 64 00 65 00 72 00 20 00 20 00 20 00 20 00 "
+ + "20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 "
+ + "20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 "
+ + "20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 "
+ + "20 00 20 00 20 00"
+ );
+ RecordInputStream in = TestcaseRecordInputStream.create(data);
+
+ WriteAccessRecord rec = new WriteAccessRecord(in);
+
+ assertEquals("Data Dynamics' SpreadBuilder", rec.getUsername());
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org