Skip to content

Commit 648149b

Browse files
committed
TIKA-4744 - sweep based on copilot feedback
1 parent 7b6e860 commit 648149b

7 files changed

Lines changed: 49 additions & 5 deletions

File tree

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/OOXMLTikaBodyPartHandler.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,14 +386,21 @@ private void inlineNoteContent(byte[] xml, String cssClass) throws SAXException
386386
// from the footnote/endnote parts (needed for picture resolution)
387387
Map<String, String> noteRelationships = inlinePartMap.getLinkedRelationships();
388388
xhtml.startElement("div", "class", cssClass);
389+
// Track the inner handler so we can call its closeAnyPending() if
390+
// the inline-note parseSAX aborts mid-element. Without the drain
391+
// the surrounding </div> mismatches whatever the inner handler
392+
// left on the SAX stack (<p>/<td>/etc.) and StrictXHTMLValidator
393+
// propagates a misleading error.
394+
OOXMLTikaBodyPartHandler innerHandler = new OOXMLTikaBodyPartHandler(xhtml);
389395
try {
390396
XMLReaderUtils.parseSAX(new ByteArrayInputStream(xml),
391397
new EmbeddedContentHandler(
392398
new OOXMLWordAndPowerPointTextHandler(
393-
new OOXMLTikaBodyPartHandler(xhtml),
399+
innerHandler,
394400
noteRelationships)),
395401
parseContext);
396-
} catch (TikaException | IOException e) {
402+
} catch (TikaException | IOException | SAXException e) {
403+
innerHandler.closeAnyPending();
397404
xhtml.characters("[" + cssClass + " parse error]");
398405
}
399406
xhtml.endElement("div");

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XSSFExcelExtractorDecorator.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,13 @@ protected void buildXHTML(XHTMLContentHandler xhtml)
239239
// the </tbody></table></div> emitted below land in the
240240
// right place.
241241
sheetExtractor.closeAnyPending();
242+
} catch (IOException e) {
243+
// Truncated stream — same risk: partial <tr>/<td> still
244+
// open. Close them so the surrounding </tbody></table>
245+
// stays balanced, record the failure, and keep going.
246+
metadata.add(TikaCoreProperties.TIKA_META_EXCEPTION_WARNING,
247+
ExceptionUtils.getStackTrace(e));
248+
sheetExtractor.closeAnyPending();
242249
}
243250
try {
244251
getThreadedComments(container, sheetPart, xhtml);

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFParser.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,11 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
104104
tagged.throwIfCauseOf(e);
105105
balancer.drainOpenElements();
106106
throw new TikaException("Error parsing an RTF document", e);
107-
} catch (SAXException e) {
107+
} catch (SAXException | TikaException e) {
108+
// Drain on any exception escaping parseInline. parseInline can
109+
// throw TikaException too (memory limits, embedded extraction,
110+
// etc.); without the drain, the finally's xhtml.endDocument()
111+
// throws on the unbalanced stack and masks the real error.
108112
balancer.drainOpenElements();
109113
throw e;
110114
} finally {

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/TextExtractor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,10 @@ private void processGroupEnd() throws IOException, SAXException, TikaException {
15011501
embObjHandler.handleCompletedObject();
15021502
} catch (TikaException | IOException e) {
15031503
EmbeddedDocumentUtil.recordException(e, metadata);
1504+
} catch (SecurityException e) {
1505+
// Security-relevant exceptions must always propagate
1506+
// immediately -- never swallow them as a warning.
1507+
throw e;
15041508
} catch (RuntimeException e) {
15051509
// POI dispatch on a zero-byte embedded object throws
15061510
// EmptyFileException; other malformed embedded payloads

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/xml/AbstractXML2003Parser.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
111111
// Close anything the aborted parse left open, then propagate.
112112
balancer.drainOpenElements();
113113
throw new TikaException("XML parse error", e);
114+
} catch (IOException e) {
115+
// Truncated streams etc. -- same problem as the SAX path: without
116+
// a drain, the finally's xhtml.endDocument() throws on the
117+
// unbalanced stack and masks the real IO error.
118+
balancer.drainOpenElements();
119+
throw e;
114120
} finally {
115121
tis.removeCloseShield();
116122
xhtml.endDocument();

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/epub/EpubParser.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ private Set<String> bufferedParseZipFile(ZipFile zipFile, ContentHandler bodyHan
248248
normalizer.drainOpenElements();
249249
} catch (IOException ioe) {
250250
LOG.trace("epub spine read IOException on {}: {}", path, ioe.toString());
251+
// Same risk as the SAX path: the partial parse may
252+
// have left elements open. Drain before rethrow so
253+
// subsequent spine items and the outer </body>
254+
// don't land on a corrupted stack.
255+
normalizer.drainOpenElements();
251256
throw ioe;
252257
} finally {
253258
processed.add(id);
@@ -351,6 +356,9 @@ private Set<String> fallbackParseAllHtmlEntries(ZipFile zipFile,
351356
} catch (IOException e) {
352357
failed++;
353358
LOG.trace("epub fallback: IO failure on {}: {}", entry.getName(), e.toString());
359+
// Same drain need as the SAX path: a partial parse before the
360+
// IO failure may have left elements open for the next iter.
361+
normalizer.drainOpenElements();
354362
}
355363
}
356364
LOG.trace("epub fallback summary: parsed={} failed={}", parsed, failed);

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/odf/FlatOpenDocumentParser.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,11 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
119119
if (detected != null) {
120120
metadata.set(Metadata.CONTENT_TYPE, detected.toString());
121121
}
122-
} catch (SAXException e) {
122+
} catch (SAXException | IOException | TikaException e) {
123+
// Drain the balancer on ANY exception that escapes the parse
124+
// loop. Without this, the finally's xhtml.endDocument() throws
125+
// on the unbalanced stack and the masked </body> vs <p>/<b>
126+
// hides the real failure (truncated input, malformed XML, etc.).
123127
balancer.drainOpenElements();
124128
throw e;
125129
} finally {
@@ -228,9 +232,13 @@ public void startElement(String namespaceURI, String localName, String qName,
228232
}
229233
} else if (outerSectionDepth > 0
230234
&& (META.equals(localName) || BODY.equals(localName)
231-
|| SCRIPTS.equals(localName))) {
235+
|| (extractMacros && SCRIPTS.equals(localName)))) {
232236
// Track nested occurrences so the matching end doesn't
233237
// prematurely flip currentHandler back to defaultHandler.
238+
// SCRIPTS is gated on extractMacros to match the decrement
239+
// condition in endElement -- otherwise a <office:scripts>
240+
// inside an outer section would inflate the counter without
241+
// a matching decrement, stranding currentHandler.
234242
outerSectionDepth++;
235243
}
236244
currentHandler.startElement(namespaceURI, localName, qName, attrs);

0 commit comments

Comments
 (0)