Author: centic Date: Tue Jul 16 13:26:16 2024 New Revision: 1919284 URL: http://svn.apache.org/viewvc?rev=1919284&view=rev Log: Bug 66425: Avoid exceptions found via poi-fuzz
Avoid a possible OutOfMemoryException with incorrect uniqueCount The ReadOnlySharedStringsTable pre-allocates whatever is stated in uniqueCount. As the uniqueCount may be an incorrect large number, we should cap it at some point to avoid OOMs if corrupt files are processed. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=66137 Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xssf/eventusermodel/TestReadOnlySharedStringsTable.java Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java?rev=1919284&r1=1919283&r2=1919284&view=diff ============================================================================== --- poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java (original) +++ poi/trunk/poi-ooxml/src/main/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java Tue Jul 16 13:26:16 2024 @@ -248,7 +248,10 @@ public class ReadOnlySharedStringsTable String uniqueCount = attributes.getValue("uniqueCount"); if(uniqueCount != null) this.uniqueCount = (int) Long.parseLong(uniqueCount); - this.strings = new ArrayList<>(this.uniqueCount); + this.strings = new ArrayList<>( + // corrupted files may have a very large number here, so only use it + // up to some size as guideline for pre-allocating the list + Math.min(this.uniqueCount, 100_000)); characters = new StringBuilder(64); } else if ("si".equals(localName)) { if (characters != null) { Modified: poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xssf/eventusermodel/TestReadOnlySharedStringsTable.java URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xssf/eventusermodel/TestReadOnlySharedStringsTable.java?rev=1919284&r1=1919283&r2=1919284&view=diff ============================================================================== --- poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xssf/eventusermodel/TestReadOnlySharedStringsTable.java (original) +++ poi/trunk/poi-ooxml/src/test/java/org/apache/poi/xssf/eventusermodel/TestReadOnlySharedStringsTable.java Tue Jul 16 13:26:16 2024 @@ -20,10 +20,14 @@ package org.apache.poi.xssf.eventusermodel; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.regex.Pattern; @@ -160,4 +164,39 @@ public final class TestReadOnlySharedStr assertEquals(0, sst.getCount()); assertEquals(0, sst.getUniqueCount()); } + + private static final String MINIMAL_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + + "<sst xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" count=\"55\" uniqueCount=\"49\">" + + "<si>" + + "<t>bla</t>" + + "<phoneticPr fontId=\"1\"/>" + + "</si>" + + "</sst>"; + + @Test + void testMinimalTable() throws IOException, SAXException { + ReadOnlySharedStringsTable tbl = new ReadOnlySharedStringsTable( + new ByteArrayInputStream(MINIMAL_XML.getBytes(StandardCharsets.UTF_8))); + assertNotNull(tbl); + assertEquals(49, tbl.getUniqueCount()); + assertEquals(55, tbl.getCount()); + assertTrue(tbl.includePhoneticRuns); + assertEquals("bla", tbl.getItemAt(0).getString()); + assertThrows(IllegalStateException.class, + () -> tbl.getItemAt(1).getString()); + } + + @Test + void testHugeUniqueCount() throws IOException, SAXException { + ReadOnlySharedStringsTable tbl = new ReadOnlySharedStringsTable( + new ByteArrayInputStream(MINIMAL_XML.replace("49", "99999999999999999"). + getBytes(StandardCharsets.UTF_8))); + assertNotNull(tbl); + assertEquals(1569325055, tbl.getUniqueCount()); + assertEquals(55, tbl.getCount()); + assertTrue(tbl.includePhoneticRuns); + assertEquals("bla", tbl.getItemAt(0).getString()); + assertThrows(IllegalStateException.class, + () -> tbl.getItemAt(1).getString()); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
