xmlsecurity PDF verify: fix reading multiple subsections from an xref stream

This is especially needed, as we don't bother compressing updated
objects into sections on signing, we simply use a separate section for
each updated object.

Work towards supporting xref streams and incremental updates at the same
time.

Change-Id: Ie9759edbba816991615fafc6602cdd440141b989
This commit is contained in:
Miklos Vajna
2016-11-10 10:33:02 +01:00
parent 7cde8def93
commit bec9e673ad

View File

@@ -1265,7 +1265,7 @@ bool PDFDocument::Read(SvStream& rStream)
SAL_INFO("xmlsecurity.pdfio", "PDFDocument::Read: nStartXRef is " << nStartXRef); SAL_INFO("xmlsecurity.pdfio", "PDFDocument::Read: nStartXRef is " << nStartXRef);
if (nStartXRef == 0) if (nStartXRef == 0)
{ {
SAL_WARN("xmlsecurity.pdfio", "PDFDocument::Read: found no xref statrt offset"); SAL_WARN("xmlsecurity.pdfio", "PDFDocument::Read: found no xref start offset");
return false; return false;
} }
while (true) while (true)
@@ -1466,37 +1466,49 @@ void PDFDocument::ReadXRefStream(SvStream& rStream)
// Look up the first and the last entry we need to read. // Look up the first and the last entry we need to read.
auto pIndex = dynamic_cast<PDFArrayElement*>(pObject->Lookup("Index")); auto pIndex = dynamic_cast<PDFArrayElement*>(pObject->Lookup("Index"));
size_t nFirstObject = 0; std::vector<size_t> aFirstObjects;
size_t nNumberOfObjects = 0; std::vector<size_t> aNumberOfObjects;
if (!pIndex || pIndex->GetElements().size() < 2) if (!pIndex)
{ {
auto pSize = dynamic_cast<PDFNumberElement*>(pObject->Lookup("Size")); auto pSize = dynamic_cast<PDFNumberElement*>(pObject->Lookup("Size"));
if (pSize) if (pSize)
nNumberOfObjects = pSize->GetValue(); {
aFirstObjects.push_back(0);
aNumberOfObjects.push_back(pSize->GetValue());
}
else else
{ {
SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ReadXRefStream: Index not found or has < 2 elements"); SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ReadXRefStream: Index and Size not found");
return; return;
} }
} }
else else
{ {
const std::vector<PDFElement*>& rIndexElements = pIndex->GetElements(); const std::vector<PDFElement*>& rIndexElements = pIndex->GetElements();
auto pFirstObject = dynamic_cast<PDFNumberElement*>(rIndexElements[0]); size_t nFirstObject = 0;
for (size_t i = 0; i < rIndexElements.size(); ++i)
{
if (i % 2 == 0)
{
auto pFirstObject = dynamic_cast<PDFNumberElement*>(rIndexElements[i]);
if (!pFirstObject) if (!pFirstObject)
{ {
SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ReadXRefStream: Index has no first object"); SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ReadXRefStream: Index has no first object");
return; return;
} }
nFirstObject = pFirstObject->GetValue(); nFirstObject = pFirstObject->GetValue();
continue;
}
auto pNumberOfObjects = dynamic_cast<PDFNumberElement*>(rIndexElements[1]); auto pNumberOfObjects = dynamic_cast<PDFNumberElement*>(rIndexElements[i]);
if (!pNumberOfObjects) if (!pNumberOfObjects)
{ {
SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ReadXRefStream: Index has no number of objects"); SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ReadXRefStream: Index has no number of objects");
return; return;
} }
nNumberOfObjects = pNumberOfObjects->GetValue(); aFirstObjects.push_back(nFirstObject);
aNumberOfObjects.push_back(pNumberOfObjects->GetValue());
}
} }
// Look up the format of a single entry. // Look up the format of a single entry.
@@ -1529,6 +1541,11 @@ void PDFDocument::ReadXRefStream(SvStream& rStream)
} }
aStream.Seek(0); aStream.Seek(0);
for (size_t nSubSection = 0; nSubSection < aFirstObjects.size(); ++nSubSection)
{
size_t nFirstObject = aFirstObjects[nSubSection];
size_t nNumberOfObjects = aNumberOfObjects[nSubSection];
// This is the line as read from the stream. // This is the line as read from the stream.
std::vector<unsigned char> aOrigLine(nLineLength); std::vector<unsigned char> aOrigLine(nLineLength);
// This is the line as it appears after tweaking according to nPredictor. // This is the line as it appears after tweaking according to nPredictor.
@@ -1616,6 +1633,7 @@ void PDFDocument::ReadXRefStream(SvStream& rStream)
} }
} }
} }
}
void PDFDocument::ReadXRef(SvStream& rStream) void PDFDocument::ReadXRef(SvStream& rStream)
{ {