This is an automated email from the ASF dual-hosted git repository.
tballison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git
The following commit(s) were added to refs/heads/main by this push:
new 0d253449b6 TIKA-4993: two workarounds for 6.0.0 (#3434)
0d253449b6 is described below
commit 0d253449b6f178ecc5ba80663f6c113b06de0b0a
Author: Tim Allison <[email protected]>
AuthorDate: Tue Oct 27 12:07:18 2026 -0400
TIKA-4993: two workarounds for 6.0.0 (#3434)
---
.../tika/parser/microsoft/ExcelExtractor.java | 8 +++-
.../tika/parser/microsoft/HSLFExtractor.java | 27 ++++++++++-
.../parser/microsoft/TikaExcelDataFormatter.java | 16 ++++---
.../tika/parser/microsoft/ExcelParserTest.java | 28 +++++++++++
.../parser/microsoft/PowerPointParserTest.java | 55 ++++++++++++++++++++++
5 files changed, 125 insertions(+), 9 deletions(-)
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ExcelExtractor.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ExcelExtractor.java
index 7a2a7ab90f..d93f9e781f 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ExcelExtractor.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ExcelExtractor.java
@@ -892,7 +892,13 @@ public class ExcelExtractor extends AbstractPOIFSExtractor
{
.formatRawCellContents(value,
getFormatIndex(cell), formatString,
false);
}
- return super.formatNumberDateCell(cell);
+ try {
+ return super.formatNumberDateCell(cell);
+ } catch (RuntimeException e) {
+ // TODO: remove on POI 6.0.1, as in TikaExcelDataFormatter
+ return tikaExcelDataFormatter.formatRawCellContents(value,
0, "General",
+ false);
+ }
}
}
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/HSLFExtractor.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/HSLFExtractor.java
index b3c0e76adc..99116d094f 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/HSLFExtractor.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/HSLFExtractor.java
@@ -17,6 +17,7 @@
package org.apache.tika.parser.microsoft;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -28,6 +29,7 @@ import org.apache.poi.common.usermodel.Hyperlink;
import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;
import org.apache.poi.hslf.model.HeadersFooters;
import org.apache.poi.hslf.record.DocInfoListContainer;
+import org.apache.poi.hslf.record.ExOleObjStg;
import org.apache.poi.hslf.record.RecordContainer;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.record.VBAInfoAtom;
@@ -53,6 +55,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.sl.usermodel.Comment;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.SimpleShape;
+import org.apache.poi.util.RecordFormatException;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
@@ -81,6 +84,23 @@ public class HSLFExtractor extends AbstractPOIFSExtractor {
private static final int EXT_TIME_NODE_CONTAINER = 0xf144;
+ /**
+ * POI 6 caps an embedded OLE object at 100 MB uncompressed; POI 5 had no
cap, and real
+ * files carry objects over 130 MB.
+ */
+ public static final int MAX_OLE_OBJECT_LENGTH = 250_000_000;
+
+ static {
+ raiseOleObjectLength();
+ }
+
+ /** Sets POI's static OLE object cap; never lowers one the caller already
raised. */
+ public static void raiseOleObjectLength() {
+ if (ExOleObjStg.getMaxRecordLength() < MAX_OLE_OBJECT_LENGTH) {
+ ExOleObjStg.setMaxRecordLength(MAX_OLE_OBJECT_LENGTH);
+ }
+ }
+
public HSLFExtractor(ParseContext context, Metadata metadata) {
super(context, metadata);
}
@@ -239,7 +259,8 @@ public class HSLFExtractor extends AbstractPOIFSExtractor {
//coz ppts can have empty pfs...shrug...
//we may need to add more stringent requirements
if (pfs.getRoot().getEntryNames().size() < 1) {
- return;
+ i++;
+ continue;
}
Metadata metadata = Metadata.newInstance(context);
if (inferredExtension) {
@@ -268,7 +289,9 @@ public class HSLFExtractor extends AbstractPOIFSExtractor {
null, null, xhtml, true);
}
}
- } catch (IOException | TikaException e) {
+ } catch (IOException | TikaException | RecordFormatException |
UncheckedIOException e) {
+ // POI 6 throws these for an object over MAX_OLE_OBJECT_LENGTH
or longer than it
+ // claims; skip it, keep the rest
EmbeddedDocumentUtil.recordException(e, parentMetadata,
context);
}
i++;
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/TikaExcelDataFormatter.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/TikaExcelDataFormatter.java
index 532c7d47b0..4841b11169 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/TikaExcelDataFormatter.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/TikaExcelDataFormatter.java
@@ -44,13 +44,17 @@ public class TikaExcelDataFormatter extends DataFormatter {
@Override
public String formatRawCellContents(double value, int formatIndex, String
formatString,
boolean use1904Windowing) {
- if (DateUtil.isADateFormat(formatIndex, formatString)) {
- String activeDateFormatString =
- (dateOverrideFormatString == null) ? formatString :
dateOverrideFormatString;
- return super.formatRawCellContents(value, formatIndex,
activeDateFormatString,
+ String activeFormatString = formatString;
+ if (dateOverrideFormatString != null &&
DateUtil.isADateFormat(formatIndex, formatString)) {
+ activeFormatString = dateOverrideFormatString;
+ }
+ try {
+ return super.formatRawCellContents(value, formatIndex,
activeFormatString,
use1904Windowing);
- } else {
- return super.formatRawCellContents(value, formatIndex,
formatString, use1904Windowing);
+ } catch (RuntimeException e) {
+ // TODO: remove on POI 6.0.1, whose DataFormatter falls back per
value itself; 6.0.0
+ // throws from SimpleFraction on overflow for a fraction format
with text, e.g. #\ ???/???
+ return super.formatRawCellContents(value, 0, "General",
use1904Windowing);
}
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ExcelParserTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ExcelParserTest.java
index 900b1f6397..a70bae5148 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ExcelParserTest.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ExcelParserTest.java
@@ -31,6 +31,8 @@ import java.util.UUID;
import org.apache.poi.hpsf.CustomProperties;
import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.util.LocaleUtil;
import org.junit.jupiter.api.AfterAll;
@@ -809,4 +811,30 @@ public class ExcelParserTest extends TikaTest {
}
assertTrue(imagesChecked >= 4, "expected at least four embedded
images, got " + imagesChecked);
}
+
+ // POI 6.0.0 throws from SimpleFraction for the second value once the
format is cached
+ @Test
+ public void testFractionOverflowKeepsSheet() throws Exception {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try (HSSFWorkbook wb = new HSSFWorkbook()) {
+ HSSFCellStyle style = wb.createCellStyle();
+ style.setDataFormat(wb.createDataFormat().getFormat("#\\
???/???"));
+ HSSFSheet sheet = wb.createSheet();
+ double[] values = {1.25, 0.00308641975308642};
+ for (int i = 0; i < values.length; i++) {
+ sheet.createRow(i).createCell(0).setCellValue(values[i]);
+ sheet.getRow(i).getCell(0).setCellStyle(style);
+ }
+ sheet.createRow(2).createCell(0).setCellValue("after");
+ wb.write(bos);
+ }
+ String xml;
+ try (TikaInputStream tis = TikaInputStream.get(bos.toByteArray())) {
+ xml = getXML(tis, AUTO_DETECT_PARSER, new Metadata()).xml;
+ }
+ assertContains("1 1/4", xml);
+ // falls back to General; POI 6.0.1 shows this as "1/324"
+ assertContains("0.0030864198", xml);
+ assertContains("after", xml);
+ }
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/PowerPointParserTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/PowerPointParserTest.java
index a6efbdc0a0..00db2b089e 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/PowerPointParserTest.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/PowerPointParserTest.java
@@ -22,10 +22,17 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
+import org.apache.poi.hslf.record.ExOleObjStg;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.LocaleUtil;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
@@ -467,4 +474,52 @@ public class PowerPointParserTest extends TikaTest {
}
assertTrue(imagesChecked > 0, "expected at least one embedded image");
}
+
+ @Test
+ public void testOleObjectCapRaised() {
+ HSLFExtractor.raiseOleObjectLength();
+ assertTrue(ExOleObjStg.getMaxRecordLength() >=
HSLFExtractor.MAX_OLE_OBJECT_LENGTH);
+ }
+
+ // an object over the cap is recorded and skipped; it used to end the loop
+ @Test
+ public void testOleObjectOverCapKeepsLaterObjects() throws Exception {
+ byte[] big = xls("big", 2_000);
+ byte[] small = xls("small", 1);
+ ByteArrayOutputStream ppt = new ByteArrayOutputStream();
+ try (HSLFSlideShow ss = new HSLFSlideShow()) {
+ ss.createSlide();
+ ss.addEmbed(new POIFSFileSystem(new ByteArrayInputStream(big)));
+ ss.addEmbed(new POIFSFileSystem(new ByteArrayInputStream(small)));
+ ss.write(ppt);
+ }
+ HSLFExtractor.raiseOleObjectLength();
+ int cap = ExOleObjStg.getMaxRecordLength();
+ ExOleObjStg.setMaxRecordLength((big.length + small.length) / 2);
+ List<Metadata> metadataList;
+ try (TikaInputStream tis = TikaInputStream.get(ppt.toByteArray())) {
+ metadataList = getRecursiveMetadata(tis, true);
+ } finally {
+ ExOleObjStg.setMaxRecordLength(cap);
+ }
+ List<Metadata> xls = metadataList.stream()
+ .filter(m ->
"application/vnd.ms-excel".equals(m.get(HttpHeaders.CONTENT_TYPE)))
+ .toList();
+ assertEquals(1, xls.size());
+ assertContains("small0",
xls.get(0).get(TikaCoreProperties.TIKA_CONTENT));
+ assertContains("exceeds maximum allowed",
+
metadataList.get(0).get(TikaCoreProperties.TIKA_META_EXCEPTION_WARNING));
+ }
+
+ private static byte[] xls(String text, int rows) throws Exception {
+ try (HSSFWorkbook wb = new HSSFWorkbook();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
+ HSSFSheet sheet = wb.createSheet();
+ for (int r = 0; r < rows; r++) {
+ sheet.createRow(r).createCell(0).setCellValue(text + r);
+ }
+ wb.write(bos);
+ return bos.toByteArray();
+ }
+ }
}