#405 check encryption token value for null

This commit is contained in:
Eliot Jones
2022-01-11 16:13:52 +00:00
parent a342115b9c
commit 83948f42d7
2 changed files with 70 additions and 28 deletions

View File

@@ -417,6 +417,35 @@ endobj";
Assert.Equal(3, third.Number.ObjectNumber);
}
[Fact]
public void ReadsDictionaryContainingNull()
{
const string input = @"14224 0 obj
<</Type /XRef
/Root 8 0 R
/Prev 116
/Length 84
/Size 35
/W [1 3 2]
/Index [0 1 6 1 8 2 25 10]
/ID [ (ù¸7<C2B8>ãA×<41>žòÜ4<C39C><34>Š•)]
/Info 6 0 R
/Encrypt null>>
endobj";
var scanner = GetScanner(input);
var tokens = ReadToEnd(scanner);
var dictionaryToken = tokens[0].Data as DictionaryToken;
Assert.NotNull(dictionaryToken);
var encryptValue = dictionaryToken.Data["Encrypt"];
Assert.IsType<NullToken>(encryptValue);
}
private static PdfTokenScanner GetScanner(string s, TestObjectLocationProvider locationProvider = null)
{
var input = StringBytesTestConverter.Convert(s, false);

View File

@@ -53,7 +53,7 @@
private static PdfDocument Open(IInputBytes inputBytes, ParsingOptions options = null)
{
var isLenientParsing = options?.UseLenientParsing ?? true;
var tokenScanner = new CoreTokenScanner(inputBytes);
var passwords = new List<string>();
@@ -80,7 +80,7 @@
return document;
}
private static PdfDocument OpenDocument(IInputBytes inputBytes, ISeekableTokenScanner scanner, ILog log, bool isLenientParsing,
private static PdfDocument OpenDocument(IInputBytes inputBytes, ISeekableTokenScanner scanner, ILog log, bool isLenientParsing,
IReadOnlyList<string> passwords, bool clipPaths)
{
var filterProvider = new FilterProviderWithLookup(DefaultFilterProvider.Instance);
@@ -96,25 +96,25 @@
var crossReferenceStreamParser = new CrossReferenceStreamParser(filterProvider);
var crossReferenceParser = new CrossReferenceParser(log, xrefValidator, crossReferenceStreamParser);
var version = FileHeaderParser.Parse(scanner, isLenientParsing, log);
var crossReferenceOffset = FileTrailerParser.GetFirstCrossReferenceOffset(inputBytes, scanner,
isLenientParsing) + version.OffsetInFile;
// TODO: make this use the scanner.
var validator = new CrossReferenceOffsetValidator(xrefValidator);
crossReferenceOffset = validator.Validate(crossReferenceOffset, scanner, inputBytes, isLenientParsing);
crossReferenceTable = crossReferenceParser.Parse(inputBytes, isLenientParsing,
crossReferenceTable = crossReferenceParser.Parse(inputBytes, isLenientParsing,
crossReferenceOffset,
version.OffsetInFile,
pdfScanner,
pdfScanner,
scanner);
var (rootReference, rootDictionary) = ParseTrailer(crossReferenceTable, isLenientParsing,
pdfScanner,
var (rootReference, rootDictionary) = ParseTrailer(crossReferenceTable, isLenientParsing,
pdfScanner,
out var encryptionDictionary);
var encryptionHandler = encryptionDictionary != null ?
@@ -134,22 +134,22 @@
type1Handler),
type1Handler,
new Type3FontHandler(pdfScanner, filterProvider, encodingReader));
var resourceContainer = new ResourceStore(pdfScanner, fontFactory);
var information = DocumentInformationFactory.Create(pdfScanner, crossReferenceTable.Trailer);
var catalog = CatalogFactory.Create(rootReference, rootDictionary, pdfScanner, isLenientParsing);
var pageFactory = new PageFactory(pdfScanner, resourceContainer, filterProvider,
new PageContentParser(new ReflectionGraphicsStateOperationFactory()),
var pageFactory = new PageFactory(pdfScanner, resourceContainer, filterProvider,
new PageContentParser(new ReflectionGraphicsStateOperationFactory()),
log);
var caching = new ParsingCachingProviders(resourceContainer);
var acroFormFactory = new AcroFormFactory(pdfScanner, filterProvider, crossReferenceTable);
var bookmarksProvider = new BookmarksProvider(log, pdfScanner);
return new PdfDocument(log, inputBytes, version, crossReferenceTable, caching, pageFactory, catalog, information,
encryptionDictionary,
pdfScanner,
@@ -162,20 +162,10 @@
private static (IndirectReference, DictionaryToken) ParseTrailer(CrossReferenceTable crossReferenceTable, bool isLenientParsing, IPdfTokenScanner pdfTokenScanner,
out EncryptionDictionary encryptionDictionary)
{
encryptionDictionary = null;
encryptionDictionary = GetEncryptionDictionary(crossReferenceTable, pdfTokenScanner);
if (crossReferenceTable.Trailer.EncryptionToken != null)
{
if (!DirectObjectFinder.TryGet(crossReferenceTable.Trailer.EncryptionToken, pdfTokenScanner, out DictionaryToken encryptionDictionaryToken))
{
throw new PdfDocumentFormatException($"Unrecognized encryption token in trailer: {crossReferenceTable.Trailer.EncryptionToken}.");
}
encryptionDictionary = EncryptionDictionaryFactory.Read(encryptionDictionaryToken, pdfTokenScanner);
}
var rootDictionary = DirectObjectFinder.Get<DictionaryToken>(crossReferenceTable.Trailer.Root, pdfTokenScanner);
if (!rootDictionary.ContainsKey(NameToken.Type) && isLenientParsing)
{
rootDictionary = rootDictionary.With(NameToken.Type, NameToken.Catalog);
@@ -183,5 +173,28 @@
return (crossReferenceTable.Trailer.Root, rootDictionary);
}
private static EncryptionDictionary GetEncryptionDictionary(CrossReferenceTable crossReferenceTable, IPdfTokenScanner pdfTokenScanner)
{
if (crossReferenceTable.Trailer.EncryptionToken == null)
{
return null;
}
if (!DirectObjectFinder.TryGet(crossReferenceTable.Trailer.EncryptionToken, pdfTokenScanner, out DictionaryToken encryptionDictionaryToken))
{
if (DirectObjectFinder.TryGet(crossReferenceTable.Trailer.EncryptionToken, pdfTokenScanner, out NullToken _))
{
return null;
}
throw new PdfDocumentFormatException($"Unrecognized encryption token in trailer: {crossReferenceTable.Trailer.EncryptionToken}.");
}
var result = EncryptionDictionaryFactory.Read(encryptionDictionaryToken, pdfTokenScanner);
return result;
}
}
}