diff --git a/src/UglyToad.PdfPig.Tests/Integration/GithubIssuesTests.cs b/src/UglyToad.PdfPig.Tests/Integration/GithubIssuesTests.cs index 039c9a59e..a963702d6 100644 --- a/src/UglyToad.PdfPig.Tests/Integration/GithubIssuesTests.cs +++ b/src/UglyToad.PdfPig.Tests/Integration/GithubIssuesTests.cs @@ -7,6 +7,15 @@ public class GithubIssuesTests { + [Fact] + public void Issue1122() + { + var path = IntegrationHelpers.GetSpecificTestDocumentPath("StackOverflow_Issue_1122.pdf"); + + var ex = Assert.Throws(() => PdfDocument.Open(path, new ParsingOptions() { UseLenientParsing = true })); + Assert.StartsWith("Reached maximum search depth while getting indirect reference.", ex.Message); + } + [Fact] public void Issue1096() { diff --git a/src/UglyToad.PdfPig.Tests/Integration/SpecificTestDocuments/StackOverflow_Issue_1122.pdf b/src/UglyToad.PdfPig.Tests/Integration/SpecificTestDocuments/StackOverflow_Issue_1122.pdf new file mode 100644 index 000000000..154aa9b56 Binary files /dev/null and b/src/UglyToad.PdfPig.Tests/Integration/SpecificTestDocuments/StackOverflow_Issue_1122.pdf differ diff --git a/src/UglyToad.PdfPig/Tokenization/Scanner/PdfTokenScanner.cs b/src/UglyToad.PdfPig/Tokenization/Scanner/PdfTokenScanner.cs index 319bbc45f..89cabdfe6 100644 --- a/src/UglyToad.PdfPig/Tokenization/Scanner/PdfTokenScanner.cs +++ b/src/UglyToad.PdfPig/Tokenization/Scanner/PdfTokenScanner.cs @@ -625,7 +625,8 @@ private DictionaryToken GetStreamDictionary() { if (offset < 0) { - var result = GetObjectFromStream(lengthReference.Data, offset); + ushort searchDepth = 0; + var result = GetObjectFromStream(lengthReference.Data, offset, ref searchDepth); if (!(result.Data is NumericToken streamLengthToken)) { @@ -714,9 +715,23 @@ public void DeregisterCustomTokenizer(ITokenizer tokenizer) coreTokenScanner.DeregisterCustomTokenizer(tokenizer); } - + public ObjectToken? Get(IndirectReference reference) { + ushort searchDepth = 0; + return Get(reference, ref searchDepth); + } + + private ObjectToken? Get(IndirectReference reference, ref ushort searchDepth) + { + if (searchDepth > 1_000) + { + throw new PdfDocumentFormatException("Reached maximum search depth while getting indirect reference."); + } + + searchDepth++; + + if (isDisposed) { throw new ObjectDisposedException(nameof(PdfTokenScanner)); @@ -740,7 +755,7 @@ public void DeregisterCustomTokenizer(ITokenizer tokenizer) // Negative offsets refer to a stream with that number. if (offset < 0) { - var result = GetObjectFromStream(reference, offset); + var result = GetObjectFromStream(reference, offset, ref searchDepth); return result; } @@ -802,11 +817,11 @@ private ObjectToken BruteForceFileToFindReference(IndirectReference reference) } } - private ObjectToken GetObjectFromStream(IndirectReference reference, long offset) + private ObjectToken GetObjectFromStream(IndirectReference reference, long offset, ref ushort searchDepth) { var streamObjectNumber = offset * -1; - var streamObject = Get(new IndirectReference(streamObjectNumber, 0)); + var streamObject = Get(new IndirectReference(streamObjectNumber, 0), ref searchDepth); if (!(streamObject?.Data is StreamToken stream)) {