diff --git a/src/UglyToad.PdfPig.Tests/Writer/PdfMergerTests.cs b/src/UglyToad.PdfPig.Tests/Writer/PdfMergerTests.cs index ccbabccc..ce906c43 100644 --- a/src/UglyToad.PdfPig.Tests/Writer/PdfMergerTests.cs +++ b/src/UglyToad.PdfPig.Tests/Writer/PdfMergerTests.cs @@ -2,6 +2,7 @@ { using Integration; using PdfPig.Writer; + using System; using System.IO; using Xunit; @@ -172,5 +173,22 @@ // ignored. } } + + [Fact] + public void NoStackoverflow() + { + try + { + var bytes = PdfMerger.Merge(IntegrationHelpers.GetDocumentPath("68-1990-01_A.pdf")); + using (var document = PdfDocument.Open(bytes, ParsingOptions.LenientParsingOff)) + { + Assert.Equal(45, document.NumberOfPages); + } + } + catch (StackOverflowException) + { + Assert.True(false); + } + } } } diff --git a/src/UglyToad.PdfPig/Writer/PdfMerger.cs b/src/UglyToad.PdfPig/Writer/PdfMerger.cs index e8e87bcf..d884fcd9 100644 --- a/src/UglyToad.PdfPig/Writer/PdfMerger.cs +++ b/src/UglyToad.PdfPig/Writer/PdfMerger.cs @@ -415,15 +415,15 @@ return newReferenceToken; } - var tokenObject = DirectObjectFinder.Get(referenceToken.Data, tokenScanner); + //we add the token to referencesFromDocument to prevent stackoverflow on references cycles + newReferenceToken = context.ReserveNumberToken(); + referencesFromDocument.Add(referenceToken, newReferenceToken); + var tokenObject = DirectObjectFinder.Get(referenceToken.Data, tokenScanner); Debug.Assert(!(tokenObject is IndirectReferenceToken)); var newToken = CopyToken(tokenObject, tokenScanner, referencesFromDocument); - newReferenceToken = context.WriteToken(newToken); - - referencesFromDocument.Add(referenceToken, newReferenceToken); - + context.WriteToken(newReferenceToken, newToken); return newReferenceToken; } case StreamToken streamToken: diff --git a/src/UglyToad.PdfPig/Writer/PdfStreamWriter.cs b/src/UglyToad.PdfPig/Writer/PdfStreamWriter.cs index 040d1a28..dec4c269 100644 --- a/src/UglyToad.PdfPig/Writer/PdfStreamWriter.cs +++ b/src/UglyToad.PdfPig/Writer/PdfStreamWriter.cs @@ -89,7 +89,11 @@ // When we end up writing this token, all of his child would already have been added and checked for duplicate return AddToken(token, reservedNumber.Value); + } + public void WriteToken(IndirectReferenceToken referenceToken, IToken token) + { + tokenReferences.Add(referenceToken, token); } public int ReserveNumber()