From c4576e4ffaa2021277ef4accf9afac3233c57d91 Mon Sep 17 00:00:00 2001 From: BobLd <38405645+BobLd@users.noreply.github.com> Date: Sun, 19 Jan 2025 11:00:43 +0000 Subject: [PATCH] Do not throw error on Pop when stack size is 1 in lenient mode and fix #973 --- .../SpecialGraphicsState/PopTests.cs | 2 +- .../Integration/GithubIssuesTests.cs | 26 +++++++++++++++++- .../SpecificTestDocuments/JD5008.pdf | Bin 0 -> 83416 bytes .../Graphics/BaseStreamProcessor.cs | 16 ++++++++++- .../Operations/SpecialGraphicsState/Pop.cs | 11 +------- 5 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 src/UglyToad.PdfPig.Tests/Integration/SpecificTestDocuments/JD5008.pdf diff --git a/src/UglyToad.PdfPig.Tests/Graphics/Operations/SpecialGraphicsState/PopTests.cs b/src/UglyToad.PdfPig.Tests/Graphics/Operations/SpecialGraphicsState/PopTests.cs index 97ac12958..bf9ce18cf 100644 --- a/src/UglyToad.PdfPig.Tests/Graphics/Operations/SpecialGraphicsState/PopTests.cs +++ b/src/UglyToad.PdfPig.Tests/Graphics/Operations/SpecialGraphicsState/PopTests.cs @@ -14,7 +14,7 @@ public void PopSymbolCorrect() Assert.Equal("Q", Pop.Value.Operator); } - [Fact] + [Fact(Skip = "The stack size check has been moved out of the Pop Operation, and is now in BaseStreamProcessor.PopState().")] public void CannotPopWithSingleFrame() { Action action = () => Pop.Value.Run(context); diff --git a/src/UglyToad.PdfPig.Tests/Integration/GithubIssuesTests.cs b/src/UglyToad.PdfPig.Tests/Integration/GithubIssuesTests.cs index 89f3790c4..eb011cf2a 100644 --- a/src/UglyToad.PdfPig.Tests/Integration/GithubIssuesTests.cs +++ b/src/UglyToad.PdfPig.Tests/Integration/GithubIssuesTests.cs @@ -8,10 +8,34 @@ public class GithubIssuesTests { [Fact] - public void Issue959() + public void Issue973() { + var path = IntegrationHelpers.GetSpecificTestDocumentPath("JD5008.pdf"); + // Lenient parsing ON + using (var document = PdfDocument.Open(path, new ParsingOptions() { UseLenientParsing = true })) + { + var page = document.GetPage(2); + Assert.NotNull(page); + Assert.Equal(2, page.Number); + Assert.NotEmpty(page.Letters); + } + + // Lenient parsing OFF + using (var document = PdfDocument.Open(path, new ParsingOptions() { UseLenientParsing = false })) + { + var exception = Assert.Throws(() => document.GetPage(2)); + Assert.Equal("Cannot execute a pop of the graphics state stack, it would leave the stack empty.", exception.Message); + } + } + + + [Fact] + public void Issue959() + { var path = IntegrationHelpers.GetSpecificTestDocumentPath("algo.pdf"); + + // Lenient parsing ON using (var document = PdfDocument.Open(path, new ParsingOptions() { UseLenientParsing = true })) { for (int i = 1; i <= document.NumberOfPages; ++i) diff --git a/src/UglyToad.PdfPig.Tests/Integration/SpecificTestDocuments/JD5008.pdf b/src/UglyToad.PdfPig.Tests/Integration/SpecificTestDocuments/JD5008.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9f7d3e1c9bae7101613c938c3272780e48e3e639 GIT binary patch literal 83416 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 public virtual void PopState() { - GraphicsStack.Pop(); + if (StackSize > 1) + { + GraphicsStack.Pop(); + } + else + { + const string error = "Cannot execute a pop of the graphics state stack, it would leave the stack empty."; + ParsingOptions.Logger.Error(error); + + if (!ParsingOptions.UseLenientParsing) + { + throw new InvalidOperationException(error); + } + } + ActiveExtendedGraphicsStateFont = null; } diff --git a/src/UglyToad.PdfPig/Graphics/Operations/SpecialGraphicsState/Pop.cs b/src/UglyToad.PdfPig/Graphics/Operations/SpecialGraphicsState/Pop.cs index ad343f075..43812a0a9 100644 --- a/src/UglyToad.PdfPig/Graphics/Operations/SpecialGraphicsState/Pop.cs +++ b/src/UglyToad.PdfPig/Graphics/Operations/SpecialGraphicsState/Pop.cs @@ -1,6 +1,5 @@ namespace UglyToad.PdfPig.Graphics.Operations.SpecialGraphicsState { - using System; using System.IO; /// @@ -29,15 +28,7 @@ private Pop() /// public void Run(IOperationContext operationContext) { - var currentStackSize = operationContext.StackSize; - if (currentStackSize > 1) - { - operationContext.PopState(); - } - else - { - throw new InvalidOperationException("Cannot execute a pop of the graphics state stack, it would leave the stack empty."); - } + operationContext.PopState(); } ///