From a9bbab647b8c63c677ead5d8dd31fbc1abd27a2b Mon Sep 17 00:00:00 2001 From: Shane Krueger Date: Mon, 19 Oct 2026 11:11:56 -0400 Subject: [PATCH] Fix loading workbooks with 64-bit ZIP data descriptors --- EPPlus/Packaging/ZipPackage.cs | 38 ++++++++++-------- EPPlusTest/EPPlusTest.Core.csproj | 4 ++ EPPlusTest/ExcelPackageTests.cs | 38 ++++++++++++++++-- .../Workbooks/test-zip64-descriptor.xlsx | Bin 0 -> 1764 bytes 4 files changed, 61 insertions(+), 19 deletions(-) create mode 100644 EPPlusTest/Workbooks/test-zip64-descriptor.xlsx diff --git a/EPPlus/Packaging/ZipPackage.cs b/EPPlus/Packaging/ZipPackage.cs index 38ce3035..d420bb1a 100644 --- a/EPPlus/Packaging/ZipPackage.cs +++ b/EPPlus/Packaging/ZipPackage.cs @@ -96,14 +96,15 @@ internal ZipPackage(Stream stream) { var rels = new Dictionary(); stream.Seek(0, SeekOrigin.Begin); - using (ZipInputStream zip = new ZipInputStream(stream)) + using (stream) + using (ZipFile zip = ReadZipFile(stream)) { - var e = zip.GetNextEntry(); - if(e==null) + var firstEntry = zip.Entries.FirstOrDefault(); + if (firstEntry == null) { throw (new InvalidDataException("The file is not an valid Package file. If the file is encrypted, please supply the password in the constructor.")); } - if (e.FileName.Contains("\\")) + if (firstEntry.FileName.Contains("\\")) { _dirSeparator = '\\'; } @@ -111,12 +112,15 @@ internal ZipPackage(Stream stream) { _dirSeparator = '/'; } - while (e != null) + foreach (var e in zip) { if (e.UncompressedSize > 0) { var b = new byte[e.UncompressedSize]; - var size = zip.Read(b, 0, (int)e.UncompressedSize); + using (var entryStream = new MemoryStream(b)) + { + e.Extract(entryStream); + } if (e.FileName.Equals("[content_types].xml", StringComparison.OrdinalIgnoreCase)) { AddContentTypes(Encoding.UTF8.GetString(b)); @@ -141,10 +145,6 @@ internal ZipPackage(Stream stream) } } } - else - { - } - e = zip.GetNextEntry(); } foreach (var p in Parts) @@ -169,16 +169,22 @@ internal ZipPackage(Stream stream) { throw (new InvalidDataException("The file is not an valid Package file. If the file is encrypted, please supply the password in the constructor.")); } - if (!hasContentTypeXml) - { - throw (new InvalidDataException("The file is not an valid Package file. If the file is encrypted, please supply the password in the constructor.")); - } - zip.Close(); - zip.Dispose(); } } } + private static ZipFile ReadZipFile(Stream stream) + { + try + { + return ZipFile.Read(stream); + } + catch (ZipException ex) + { + throw new InvalidDataException("The file is not an valid Package file. If the file is encrypted, please supply the password in the constructor.", ex); + } + } + private void AddContentTypes(string xml) { var doc = new XmlDocument(); diff --git a/EPPlusTest/EPPlusTest.Core.csproj b/EPPlusTest/EPPlusTest.Core.csproj index c96bbd36..23cca473 100644 --- a/EPPlusTest/EPPlusTest.Core.csproj +++ b/EPPlusTest/EPPlusTest.Core.csproj @@ -33,6 +33,10 @@ $(WarningsAsErrors);CA1416 + + + + diff --git a/EPPlusTest/ExcelPackageTests.cs b/EPPlusTest/ExcelPackageTests.cs index 981959ca..6c70921c 100644 --- a/EPPlusTest/ExcelPackageTests.cs +++ b/EPPlusTest/ExcelPackageTests.cs @@ -1,15 +1,47 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using OfficeOpenXml; using System; -using System.Collections.Generic; using System.IO; -using System.Text; namespace EPPlusTest { [TestClass] public class ExcelPackageTests { - + [TestMethod] + public void ReadWorkbookWithZip64DataDescriptors() + { + var path = Path.Combine(AppContext.BaseDirectory, "Workbooks", "test-zip64-descriptor.xlsx"); + using (var stream = File.OpenRead(path)) + using (var package = new ExcelPackage(stream)) + { + Assert.AreEqual(1, package.Workbook.Worksheets.Count); + var worksheet = package.Workbook.Worksheets["Sheet1"]; + Assert.IsNotNull(worksheet); + Assert.AreEqual("test", worksheet.Cells["A1"].Value); + Assert.AreEqual("A1", worksheet.Dimension.Address); + } + } + + [TestMethod] + public void SaveAndReloadWorkbookWithZip64DataDescriptors() + { + var path = Path.Combine(AppContext.BaseDirectory, "Workbooks", "test-zip64-descriptor.xlsx"); + using (var input = File.OpenRead(path)) + using (var output = new MemoryStream()) + { + using (var package = new ExcelPackage(input)) + { + package.SaveAs(output); + } + output.Position = 0; + using (var package = new ExcelPackage(output)) + { + Assert.AreEqual(1, package.Workbook.Worksheets.Count); + Assert.AreEqual("test", package.Workbook.Worksheets["Sheet1"].Cells["A1"].Value); + } + Assert.IsTrue(input.CanRead, "Loading the package must leave the caller's input stream open."); + } + } } } diff --git a/EPPlusTest/Workbooks/test-zip64-descriptor.xlsx b/EPPlusTest/Workbooks/test-zip64-descriptor.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a0698a0f9c1ab2de3278206bb9306d1505c45779 GIT binary patch literal 1764 zcmWIWW@gc4-~d7f2E`a40SCfBR%s$ff|4FI$uWuHa4;#2*EY`l6c{4x7{PxMnvI8z^Kc=mB zJu6uyy5(c->G<;gtGww`4rXsSn0&h5qh@zz+3}7eUe|(8x6gUJcFGdA5(g!hFRm}0 ziYA;k{A$!Bwa~pX^!oK6*7+BoYn`|Lv25pYzHerm+gHZSuTt4^-9cu{lB?AW?%JZ#sF`2 zj=aPjy#JuVq{{?h1mFxtZlHqrqSTyXeLWD_d;TC_lK~IggYd|z>5c5kJk8yP53@cn zJ_}=Gyp}qfEB}38l1)XBfbjOW3nn?%X>4jzh;KbL*TF ziyB0kuY^_}^*mN0^y?t&G#+V|FNV8>pF4iFI6Yya^K3KOpOME*st(T$S!{CRdu82& zf0rB9o|Mu(V7`mt+B&}f8&|$&YfTU8m(2YW_;ISorY~%Z8&V(Xe|kJOSjG_g;6%fM<`_6Wb-Jjq_G* z%MlRDe!#G>Fw-SDyzIxG+ro9#VaC@ojv0S_CFfr3dhx&&2TT0}3Z-wD=So?;G2d)& zFiWP=+$fRx|B4M+ucc4_JW*qI)9==S370}5SKn>8_;QZ=k~Lp+E-tM(b@G+Ui#>cD zntf$~BHq%m3Ki-hpS;<=*S;t?dskIyX?e$k7eRXKoo9&L`t{Y(KI6pEn5yqjQsq7! zS$p34pogf@#I^bdw{87<>rHv&Zw8R>=jJ%?-3j%*G(q1>L3|I1Z{#q5#{EgILk^(0 zmn_*Zqj@i zW1zLn?8}R(^FsW0oc%1@md|``*@|e+g?ZcpXCJ+kzg>EF#mgsO&Q9pH_j_=-wUd3( zi~!N9E+ISRW96EgmN12>uCrSc2MU0wzfIX2p#h*lFaRVF(O;aAnp#q<52g%3>A<(o zF^k!d$8~+umVA?!i>4%4i+Jf@c*cfafgG$K7-c>nJf@86%xX|EDx zt$yP@8^@94`C9QpbN1QIi&I=7I`7n_nL>Xi9x^m$)hd(r}4QZ2EeyhX0L7~L&!#4IaAM|+;CZ@wo#@1cFwK5(vYXFiv_3mOi8p>%*Z zBa`q)AICN>bszyOjC@MZ<`{v!bf1^@{kdx8J} literal 0 HcmV?d00001