Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/UglyToad.PdfPig/Parser/FileStructure/XrefBruteForcer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace UglyToad.PdfPig.Parser.FileStructure;
namespace UglyToad.PdfPig.Parser.FileStructure;

using Core;
using Logging;
Expand Down Expand Up @@ -135,6 +135,12 @@ void AddQueues(long num)

var potentialTableOffset = bytes.CurrentOffset - 4;

// TryReadTableAtOffset seeks the shared stream and does not restore
// position (including on failure). Snapshot so the scan resumes from
// here — otherwise a failed parse can skip past later keywords such
// as a recoverable 'trailer' dictionary.
var resumePosition = bytes.CurrentOffset;

if (xrefOffsetSeen.Contains(potentialTableOffset))
{
log.Debug($"Skipping circular xref reference at {potentialTableOffset}");
Expand All @@ -158,6 +164,8 @@ void AddQueues(long num)
log.Warn(
$"Found a table at {potentialTableOffset} but couldn't parse it.");
}

bytes.Seek(resumePosition);
}
else if (buffer.EndsWith("/XRef"))
{
Expand All @@ -176,6 +184,9 @@ void AddQueues(long num)
}
xrefOffsetSeen.Add(offset);

// Same position-preservation as the table branch above.
var resumePosition = bytes.CurrentOffset;

var stream = XrefStreamParser.TryReadStreamAtOffset(
new FileHeaderOffset(0),
offset,
Expand All @@ -187,11 +198,17 @@ void AddQueues(long num)
{
results.Add(stream);
}

bytes.Seek(resumePosition);
}
else if (buffer.EndsWith("trailer "))
{
ClearQueues();

// Ensure the scanner reads from the byte scan's current position —
// a preceding failed table/stream parse may have moved it elsewhere.
scanner.Seek(bytes.CurrentOffset);

// Grab the last trailer dictionary as backup in case we find no valid xrefs.
if (scanner.TryReadToken(out DictionaryToken trailerDict))
{
Expand Down
Loading