mirror of
https://github.com/UglyToad/PdfPig.git
synced 2026-03-10 00:23:29 +08:00
Improve HasFormXObjectCircularReference and fix #1250
This commit is contained in:
Binary file not shown.
@@ -11,6 +11,31 @@
|
|||||||
|
|
||||||
public class GithubIssuesTests
|
public class GithubIssuesTests
|
||||||
{
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Issues1250()
|
||||||
|
{
|
||||||
|
// Issue comes from HasFormXObjectCircularReference
|
||||||
|
var path = IntegrationHelpers.GetDocumentPath("SPE8EF26T0545.pdf");
|
||||||
|
using (var document = PdfDocument.Open(path, new ParsingOptions() { UseLenientParsing = true }))
|
||||||
|
{
|
||||||
|
var page = document.GetPage(1);
|
||||||
|
Assert.NotNull(page);
|
||||||
|
Assert.NotEmpty(page.Letters);
|
||||||
|
|
||||||
|
page = document.GetPage(7);
|
||||||
|
Assert.NotNull(page);
|
||||||
|
Assert.NotEmpty(page.Letters);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure still no StackOverflowException
|
||||||
|
using (var document = PdfDocument.Open(IntegrationHelpers.GetDocumentPath("issue_671")))
|
||||||
|
{
|
||||||
|
var page = document.GetPage(1);
|
||||||
|
Assert.NotNull(page);
|
||||||
|
Assert.NotEmpty(page.Letters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Issues1248()
|
public void Issues1248()
|
||||||
{
|
{
|
||||||
@@ -29,7 +54,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Issues1238()
|
public void Issues1238()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -587,7 +587,8 @@
|
|||||||
if (hasCircularReference)
|
if (hasCircularReference)
|
||||||
{
|
{
|
||||||
if (ParsingOptions.UseLenientParsing)
|
if (ParsingOptions.UseLenientParsing)
|
||||||
{
|
{
|
||||||
|
// TODO - We might be removing too much, good for the moment. See Issues1250() for examples
|
||||||
operations = operations.Where(o => o is not InvokeNamedXObject xo || xo.Name != xObjectName)
|
operations = operations.Where(o => o is not InvokeNamedXObject xo || xo.Name != xObjectName)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
ParsingOptions.Logger.Warn(
|
ParsingOptions.Logger.Warn(
|
||||||
@@ -618,14 +619,56 @@
|
|||||||
/// <param name="xObjectName">The form's name.</param>
|
/// <param name="xObjectName">The form's name.</param>
|
||||||
/// <param name="operations">The form operations parsed from original form stream.</param>
|
/// <param name="operations">The form operations parsed from original form stream.</param>
|
||||||
protected virtual bool HasFormXObjectCircularReference(StreamToken formStream,
|
protected virtual bool HasFormXObjectCircularReference(StreamToken formStream,
|
||||||
NameToken xObjectName,
|
NameToken? xObjectName,
|
||||||
IReadOnlyList<IGraphicsStateOperation> operations)
|
IReadOnlyList<IGraphicsStateOperation> operations)
|
||||||
{
|
{
|
||||||
return xObjectName != null
|
if (xObjectName is null)
|
||||||
&& operations.OfType<InvokeNamedXObject>()?.Any(o => o.Name == xObjectName) ==
|
{
|
||||||
true // operations contain another form with same name
|
return false;
|
||||||
&& ResourceStore.TryGetXObject(xObjectName, out var result)
|
}
|
||||||
&& result.Data.Span.SequenceEqual(formStream.Data.Span); // The form contained in the operations has identical data to current form
|
|
||||||
|
if (operations.OfType<InvokeNamedXObject>()?.Any(o => o.Name == xObjectName) != true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryGetXObjectToken(formStream, xObjectName, PdfScanner, out var t1))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ResourceStore.TryGetXObject(xObjectName, out var resourceStream))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryGetXObjectToken(resourceStream, xObjectName, PdfScanner, out var t2))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t1 is null || t2 is null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t1.Equals(t2);
|
||||||
|
|
||||||
|
static bool TryGetXObjectToken(StreamToken streamToken, NameToken xObjectName, IPdfTokenScanner scanner, out IToken? token)
|
||||||
|
{
|
||||||
|
token = null;
|
||||||
|
if (!streamToken.StreamDictionary.TryGet<DictionaryToken>(NameToken.Resources, scanner, out var formResources))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!formResources.TryGet<DictionaryToken>(NameToken.Xobject, out var xObjectBase) || !xObjectBase.TryGet(xObjectName, out token))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return token is not null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|||||||
Reference in New Issue
Block a user