From 03b0742ad33783ec5e283467ea0993987e83f84a Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Mon, 1 Jul 2024 22:40:18 +0000 Subject: [PATCH] throw exception if xlsx contains duplicate file names git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1918802 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/ooxml/util/PackageHelper.java | 9 +++++-- .../apache/poi/openxml4j/opc/OPCPackage.java | 26 +++++++++++++----- .../util/ZipInputStreamZipEntrySource.java | 11 +++++++- .../poi/openxml4j/util/ZipSecureFile.java | 4 +-- .../poi/xssf/usermodel/TestXSSFWorkbook.java | 27 ++++++++++++++----- 5 files changed, 60 insertions(+), 17 deletions(-) diff --git a/poi-ooxml/src/main/java/org/apache/poi/ooxml/util/PackageHelper.java b/poi-ooxml/src/main/java/org/apache/poi/ooxml/util/PackageHelper.java index 75f4371c31..119289cfd4 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/ooxml/util/PackageHelper.java +++ b/poi-ooxml/src/main/java/org/apache/poi/ooxml/util/PackageHelper.java @@ -35,6 +35,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.openxml4j.opc.internal.InvalidZipException; import org.apache.poi.util.IOUtils; import org.apache.poi.util.Removal; @@ -62,8 +63,12 @@ public final class PackageHelper { public static OPCPackage open(InputStream stream, boolean closeStream) throws IOException { try { return OPCPackage.open(stream, closeStream); - } catch (InvalidFormatException e){ - throw new POIXMLException(e); + } catch (InvalidFormatException e) { + final Throwable cause = e.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } + throw new IOException(e); } finally { if (closeStream) { stream.close(); diff --git a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/OPCPackage.java b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/OPCPackage.java index e15284806d..0b476b1b12 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/OPCPackage.java +++ b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/OPCPackage.java @@ -50,6 +50,7 @@ import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; import org.apache.poi.openxml4j.exceptions.PartAlreadyExistsException; import org.apache.poi.openxml4j.opc.internal.ContentType; import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; +import org.apache.poi.openxml4j.opc.internal.InvalidZipException; import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; import org.apache.poi.openxml4j.opc.internal.PartMarshaller; import org.apache.poi.openxml4j.opc.internal.PartUnmarshaller; @@ -193,7 +194,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { } /** - * Open an user provided {@link ZipEntrySource} with read-only permission. + * Open a user provided {@link ZipEntrySource} with read-only permission. * This method can be used to stream data into POI. * Opposed to other open variants, the data is read as-is, e.g. there aren't * any zip-bomb protection put in place. @@ -202,8 +203,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { * @return A Package object * @throws InvalidFormatException if a parsing error occur. */ - public static OPCPackage open(ZipEntrySource zipEntry) - throws InvalidFormatException { + public static OPCPackage open(ZipEntrySource zipEntry) throws InvalidFormatException { OPCPackage pack = new ZipPackage(zipEntry, PackageAccess.READ); try { if (pack.partList == null) { @@ -282,7 +282,12 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { throw new IllegalArgumentException("file must not be a directory"); } - OPCPackage pack = new ZipPackage(file, access); //NOSONAR + final OPCPackage pack; + try { + pack = new ZipPackage(file, access); //NOSONAR + } catch (InvalidOperationException e) { + throw new InvalidFormatException(e.getMessage(), e); + } try { if (pack.partList == null && access != PackageAccess.WRITE) { pack.getParts(); @@ -316,8 +321,12 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { */ public static OPCPackage open(InputStream in) throws InvalidFormatException, IOException { - OPCPackage pack = new ZipPackage(in, PackageAccess.READ_WRITE); + final OPCPackage pack; try { + pack = new ZipPackage(in, PackageAccess.READ_WRITE); + } catch (InvalidZipException e) { + throw new InvalidFormatException(e.getMessage(), e); + } try { if (pack.partList == null) { pack.getParts(); } @@ -348,7 +357,12 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { */ public static OPCPackage open(InputStream in, boolean closeStream) throws InvalidFormatException, IOException { - OPCPackage pack = new ZipPackage(in, PackageAccess.READ_WRITE, closeStream); + final OPCPackage pack; + try { + pack = new ZipPackage(in, PackageAccess.READ_WRITE, closeStream); + } catch (InvalidZipException e) { + throw new InvalidFormatException(e.getMessage(), e); + } try { if (pack.partList == null) { pack.getParts(); diff --git a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java index 5f9a057d4f..676a9a3c0c 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java +++ b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java @@ -21,9 +21,12 @@ import java.io.InputStream; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.poi.openxml4j.opc.internal.InvalidZipException; /** * Provides a way to get at all the ZipEntries @@ -90,12 +93,18 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource { * @see #setThresholdBytesForTempFiles */ public ZipInputStreamZipEntrySource(ZipArchiveThresholdInputStream inp) throws IOException { + final Set filenames = new HashSet<>(); for (;;) { final ZipArchiveEntry zipEntry = inp.getNextEntry(); if (zipEntry == null) { break; } - zipEntries.put(zipEntry.getName(), new ZipArchiveFakeEntry(zipEntry, inp)); + String name = zipEntry.getName(); + if (filenames.contains(name)) { + throw new InvalidZipException("Input file contains more than 1 entry with the name " + name); + } + filenames.add(name); + zipEntries.put(name, new ZipArchiveFakeEntry(zipEntry, inp)); } streamToClose = inp; diff --git a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipSecureFile.java b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipSecureFile.java index ff183a696e..233661f5de 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipSecureFile.java +++ b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipSecureFile.java @@ -254,8 +254,8 @@ public class ZipSecureFile extends ZipFile { } private void validateEntryNames() throws IOException { - Enumeration en = getEntries(); - Set filenames = new HashSet<>(); + final Enumeration en = getEntries(); + final Set filenames = new HashSet<>(); while (en.hasMoreElements()) { String name = en.nextElement().getName(); if (filenames.contains(name)) { diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java index bd36492535..854798f16f 100644 --- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java +++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java @@ -27,7 +27,6 @@ import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.ooxml.POIXMLProperties; import org.apache.poi.ooxml.TrackingInputStream; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.InvalidOperationException; import org.apache.poi.openxml4j.opc.ContentTypes; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; @@ -38,6 +37,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.openxml4j.opc.ZipPackage; import org.apache.poi.openxml4j.opc.internal.FileHelper; +import org.apache.poi.openxml4j.opc.internal.InvalidZipException; import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart; import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; import org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource; @@ -1448,13 +1448,28 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook { } } + @Test + void testDuplicateFileReadAsOPCFile() { + assertThrows(InvalidFormatException.class, () -> { + try (OPCPackage pkg = OPCPackage.open(getSampleFile("duplicate-file.xlsx"), PackageAccess.READ)) { + // expect exception here + } + }); + } + @Test void testDuplicateFileReadAsFile() { - assertThrows(InvalidOperationException.class, () -> { - try ( - OPCPackage pkg = OPCPackage.open(getSampleFile("duplicate-file.xlsx"), PackageAccess.READ); - XSSFWorkbook wb = new XSSFWorkbook(pkg) - ) { + assertThrows(InvalidFormatException.class, () -> { + try (XSSFWorkbook wb = new XSSFWorkbook(getSampleFile("duplicate-file.xlsx"))) { + // expect exception here + } + }); + } + + @Test + void testDuplicateFileReadAsStream() { + assertThrows(InvalidZipException.class, () -> { + try (XSSFWorkbook wb = new XSSFWorkbook(openSampleFileStream("duplicate-file.xlsx"))) { // expect exception here } }); -- 2.39.5