From 631a59c8f3927f4e8fd22ff6bc7e4f3620dac047 Mon Sep 17 00:00:00 2001 From: Michele Bastione Date: Sat, 13 Sep 2025 20:03:48 +0200 Subject: [PATCH] Fixed exception not being thrown when too long a sheet name was passed as dictionary key Co-Authored-By: RiRiSharp <30719799+RiRiSharp@users.noreply.github.com> --- src/MiniExcel.Core/Helpers/ThrowHelper.cs | 14 ++++++++++++- .../OpenXml/OpenXmlWriter.DefaultOpenXml.cs | 2 ++ src/MiniExcel.Core/OpenXml/OpenXmlWriter.cs | 5 +---- .../MiniExcelIssueTests.cs | 20 +++++++++++++++++++ 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/MiniExcel.Core/Helpers/ThrowHelper.cs b/src/MiniExcel.Core/Helpers/ThrowHelper.cs index 892e0645..a277600c 100644 --- a/src/MiniExcel.Core/Helpers/ThrowHelper.cs +++ b/src/MiniExcel.Core/Helpers/ThrowHelper.cs @@ -2,6 +2,9 @@ internal static class ThrowHelper { + private static readonly byte[] ZipArchiveHeader = [0x50, 0x4B]; + private const int ExcelMaxSheetNameLength = 31; + internal static void ThrowIfInvalidOpenXml(Stream stream) { var probe = new byte[8]; @@ -13,7 +16,16 @@ internal static void ThrowIfInvalidOpenXml(Stream stream) stream.Seek(0, SeekOrigin.Begin); // OpenXml format can be any ZIP archive - if (probe is not [0x50, 0x4B, ..]) + if (!probe.StartsWith(ZipArchiveHeader)) throw new InvalidDataException("The file is not a valid OpenXml document."); } + + internal static void ThrowIfInvalidSheetName(string? sheetName) + { + if (string.IsNullOrEmpty(sheetName)) + throw new ArgumentException("Sheet names cannot be empty or null"); + + if (sheetName.Length > ExcelMaxSheetNameLength) + throw new ArgumentException("Sheet names must be less than 31 characters"); + } } diff --git a/src/MiniExcel.Core/OpenXml/OpenXmlWriter.DefaultOpenXml.cs b/src/MiniExcel.Core/OpenXml/OpenXmlWriter.DefaultOpenXml.cs index fc3e8ca2..eb56f013 100644 --- a/src/MiniExcel.Core/OpenXml/OpenXmlWriter.DefaultOpenXml.cs +++ b/src/MiniExcel.Core/OpenXml/OpenXmlWriter.DefaultOpenXml.cs @@ -17,6 +17,8 @@ internal partial class OpenXmlWriter : IMiniExcelWriter { foreach (var sheet in dictionary) { + ThrowHelper.ThrowIfInvalidSheetName(sheet.Key); + sheetId++; var sheetInfos = GetSheetInfos(sheet.Key); yield return Tuple.Create(sheetInfos.ToDto(sheetId), sheet.Value); diff --git a/src/MiniExcel.Core/OpenXml/OpenXmlWriter.cs b/src/MiniExcel.Core/OpenXml/OpenXmlWriter.cs index c4c3b7e2..c1ee9b8f 100644 --- a/src/MiniExcel.Core/OpenXml/OpenXmlWriter.cs +++ b/src/MiniExcel.Core/OpenXml/OpenXmlWriter.cs @@ -45,10 +45,7 @@ internal OpenXmlWriter(Stream stream, object? value, string? sheetName, IMiniExc [CreateSyncVersion] internal static Task CreateAsync(Stream stream, object? value, string? sheetName, bool printHeader, IMiniExcelConfiguration? configuration, CancellationToken cancellationToken = default) { - if (string.IsNullOrEmpty(sheetName)) - throw new ArgumentException("Sheet names cannot be empty or null", nameof(sheetName)); - if (sheetName?.Length > 31) - throw new ArgumentException("Sheet names must be less than 31 characters", nameof(sheetName)); + ThrowHelper.ThrowIfInvalidSheetName(sheetName); var writer = new OpenXmlWriter(stream, value, sheetName, configuration, printHeader); return Task.FromResult(writer); diff --git a/tests/MiniExcel.Core.Tests/MiniExcelIssueTests.cs b/tests/MiniExcel.Core.Tests/MiniExcelIssueTests.cs index 3c912ef9..d48ccb9c 100644 --- a/tests/MiniExcel.Core.Tests/MiniExcelIssueTests.cs +++ b/tests/MiniExcel.Core.Tests/MiniExcelIssueTests.cs @@ -3690,4 +3690,24 @@ public void TestIssue869(string fileName, DateOnlyConversionMode mode, bool thro } } } + + [Fact] + public void TestIssue876() + { + var someTable = new[] + { + new { Name = "Jack", Age = 25 }, + }; + + var sheets = new Dictionary + { + ["SomeVeryLongNameWithMoreThan31Characters"] = someTable + }; + + Assert.Throws(() => + { + using var outputPath = AutoDeletingPath.Create(); + _excelExporter.Export(outputPath.ToString(), sheets); + }); + } } \ No newline at end of file