Prevent StackOverflow in ParseTrailer and fix #1122

This commit is contained in:
BobLd 2025-08-08 19:48:49 +01:00
parent 0f641774e6
commit 1031dcc221
3 changed files with 29 additions and 5 deletions

View File

@ -7,6 +7,15 @@
public class GithubIssuesTests public class GithubIssuesTests
{ {
[Fact]
public void Issue1122()
{
var path = IntegrationHelpers.GetSpecificTestDocumentPath("StackOverflow_Issue_1122.pdf");
var ex = Assert.Throws<PdfDocumentFormatException>(() => PdfDocument.Open(path, new ParsingOptions() { UseLenientParsing = true }));
Assert.StartsWith("Reached maximum search depth while getting indirect reference.", ex.Message);
}
[Fact] [Fact]
public void Issue1096() public void Issue1096()
{ {

View File

@ -625,7 +625,8 @@
{ {
if (offset < 0) 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)) if (!(result.Data is NumericToken streamLengthToken))
{ {
@ -714,9 +715,23 @@
coreTokenScanner.DeregisterCustomTokenizer(tokenizer); coreTokenScanner.DeregisterCustomTokenizer(tokenizer);
} }
public ObjectToken? Get(IndirectReference reference) 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) if (isDisposed)
{ {
throw new ObjectDisposedException(nameof(PdfTokenScanner)); throw new ObjectDisposedException(nameof(PdfTokenScanner));
@ -740,7 +755,7 @@
// Negative offsets refer to a stream with that number. // Negative offsets refer to a stream with that number.
if (offset < 0) if (offset < 0)
{ {
var result = GetObjectFromStream(reference, offset); var result = GetObjectFromStream(reference, offset, ref searchDepth);
return result; return result;
} }
@ -802,11 +817,11 @@
} }
} }
private ObjectToken GetObjectFromStream(IndirectReference reference, long offset) private ObjectToken GetObjectFromStream(IndirectReference reference, long offset, ref ushort searchDepth)
{ {
var streamObjectNumber = offset * -1; 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)) if (!(streamObject?.Data is StreamToken stream))
{ {