Do not throw exception when lenient parsing in GetExtendedGraphicsStateDictionary() and improve StackDictionary.TryGetValue() to not throw on empty

This commit is contained in:
BobLd 2025-03-02 11:43:16 +00:00
parent f26e7d90a3
commit 67d8f56366
5 changed files with 43 additions and 4 deletions

View File

@ -7,6 +7,33 @@
public class GithubIssuesTests
{
[Fact]
public void Issue953()
{
// NB: We actually do not fix issue 953 here, but another bug found with the same document.
var path = IntegrationHelpers.GetSpecificTestDocumentPath("FailedToParseContentForPage32.pdf");
// Lenient parsing ON + Skip missing fonts
using (var document = PdfDocument.Open(path, new ParsingOptions() { UseLenientParsing = true, SkipMissingFonts = true}))
{
var page = document.GetPage(33);
Assert.Equal(33, page.Number);
Assert.Equal(792, page.Height);
Assert.Equal(612, page.Width);
}
// Lenient parsing ON + Do not Skip missing fonts
using (var document = PdfDocument.Open(path, new ParsingOptions() { UseLenientParsing = true, SkipMissingFonts = false }))
{
var pageException = Assert.Throws<InvalidOperationException>(() => document.GetPage(33));
Assert.Equal("Could not find the font with name /TT4 in the resource store. It has not been loaded yet.", pageException.Message);
}
var docException = Assert.Throws<PdfDocumentFormatException>(() =>
PdfDocument.Open(path, new ParsingOptions() { UseLenientParsing = false, SkipMissingFonts = false }));
Assert.Equal("Could not find dictionary associated with reference in pages kids array: 102 0.", docException.Message);
}
[Fact]
public void Issue987()
{

View File

@ -35,7 +35,7 @@
/// <summary>
/// Get the extended graphics state dictionary corresponding to the name.
/// </summary>
DictionaryToken GetExtendedGraphicsStateDictionary(NameToken name);
DictionaryToken? GetExtendedGraphicsStateDictionary(NameToken name);
/// <summary>
/// Get the font from the <see cref="IndirectReferenceToken"/>.

View File

@ -336,8 +336,14 @@
return DirectObjectFinder.TryGet(new IndirectReferenceToken(indirectReference), scanner, out stream);
}
public DictionaryToken GetExtendedGraphicsStateDictionary(NameToken name)
public DictionaryToken? GetExtendedGraphicsStateDictionary(NameToken name)
{
if (parsingOptions.UseLenientParsing && !extendedGraphicsStates.ContainsKey(name))
{
parsingOptions.Logger.Error($"The graphic state dictionary does not contain the key '{name}'.");
return null;
}
return extendedGraphicsStates[name];
}

View File

@ -5,7 +5,7 @@ namespace UglyToad.PdfPig.Util
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
internal class StackDictionary<K, V> where K : notnull
internal sealed class StackDictionary<K, V> where K : notnull
{
private readonly List<Dictionary<K, V>> values = new List<Dictionary<K, V>>();
@ -13,6 +13,11 @@ namespace UglyToad.PdfPig.Util
{
get
{
if (values.Count == 0)
{
throw new InvalidOperationException($"Cannot get item from empty stack, call {nameof(Push)} before use.");
}
if (TryGetValue(key, out var result))
{
return result;
@ -35,7 +40,8 @@ namespace UglyToad.PdfPig.Util
{
if (values.Count == 0)
{
throw new InvalidOperationException($"Cannot get item from empty stack, call {nameof(Push)} before use.");
result = default!;
return false;
}
for (var i = values.Count - 1; i >= 0; i--)