https://bz.apache.org/bugzilla/show_bug.cgi?id=64045
Bug ID: 64045
Summary: XSSFWorkbook constructor doesn't close ZipFile if an
exception occurs
Product: POI
Version: 4.1.1-FINAL
Hardware: PC
OS: All
Status: NEW
Severity: normal
Priority: P2
Component: XSSF
Assignee: dev@poi.apache.org
Reporter: radistao@gmail.com
Target Milestone: ---
Created attachment 36943
--> https://bz.apache.org/bugzilla/attachment.cgi?id=36943&action=edit
Corrupted XLSX file with malformed _rels/.rels XML
When a user creates XSSFWorkbook instance from some file or stream resource,
but exception happens in the process, ZipFile can't be closed by the developer
(neither explicitly catching an exception nor using `try-with-resource`
statement), but closes later invoking ZipFile#finalize() during garbage
collecting.
The message "Cleaning up unclosed ZipFile for archive ..." is printed to
stderr.
Because the behavior is depended on encapsulated GC behavior it's hard to
supply a simple working code snippet to reproduce.
The bug is observable in a web application when multiple XLSX files are
uploaded and parsed with some time pauses.
But from the source code perspective it could be also understood.
Imagine we want to print sheets number in an XLSX workbook:
1)
try (final var workbook = new XSSFWorkbook(inputFile)) {
System.out.println(workbook.getNumberOfSheets());
} catch (Exception e) {
// constructor throws POIXMLException, or XMLException, or
InvalidFormatException
// workbook is null
}
2) The steps in the source code starting from XSSFWorkbook(File)
XSSFWorkbook(File) -> OPCPackage#open(File) -> ZipPackage(File) -> ZipFile(...)
https://github.com/apache/poi/blob/a0770034fcc878a697b715d0b6a6e53406b2d02d/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java#L324
https://github.com/apache/commons-compress/blob/master/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java#L363
This creates a private ZipFile closable instance inside OPCPackage and
continues the workbook constructor XSSFWorkbook(OPCPackage pkg):
POIXMLDocument(OPCPackage pkg) -> POIXMLDocumentPart(OPCPackage pkg, String
coreDocumentRel) -> POIXMLDocumentPart#getPartFromOPCPackage(OPCPackage pkg,
String coreDocumentRel) ->
throw new POIXMLException("OOXML file structure broken/invalid - no core
document found!");
https://github.com/apache/poi/blob/a0770034fcc878a697b715d0b6a6e53406b2d02d/src/ooxml/java/org/apache/poi/ooxml/POIXMLDocumentPart.java#L753
Even if we catch the exception we can't close/release the ZipFile instance
because it's private! In the same time we don't have a XSSFWorkbook to
close/autoclose it in case of an exception.
The object is detached from the thread and becomes available for GC, but the
file stream is still not closed!
Note:
1) other ZIP/OOXML parsers likely affected (like DOCX, PPTX)
2) other exceptions (like "POIXMLException: org.apache.xmlbeans.XmlException:
error: DOCTYPE is disallowed when the feature
"http://apache.org/xml/features/disallow-doctype-decl" set to true.") also
create such detached closable source instances.
2) Some methods have proper exception handlers, like OPCPackage#open(File,
PackageAccess):
https://github.com/apache/poi/blob/a0770034fcc878a697b715d0b6a6e53406b2d02d/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java#L228
catch (InvalidFormatException | RuntimeException e) {
IOUtils.closeQuietly(pack);
throw e;
}
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@poi.apache.org
For additional commands, e-mail: dev-help@poi.apache.org
|