Fix decryption of objects with number > 511, better use of zlib library

This commit is contained in:
Jakub Melka 2019-08-18 16:03:41 +02:00
parent cf0f91fdb0
commit 23a36f14a4
5 changed files with 76 additions and 13 deletions

View File

@ -135,6 +135,16 @@ openssl_lib.files = $$PDFFORQT_DEPENDENCIES_PATH/OpenSSL/libcrypto-3.dll $$PDFFO
openssl_lib.path = $$DESTDIR/install
INSTALLS += openssl_lib
# Link zlib
LIBS += -L$$PDFFORQT_DEPENDENCIES_PATH/zlib/bin/ -lzlib
INCLUDEPATH += $$PDFFORQT_DEPENDENCIES_PATH/zlib/include
DEPENDPATH += $$PDFFORQT_DEPENDENCIES_PATH/zlib/include
# Add zlib to installations
zlib.files = $$PDFFORQT_DEPENDENCIES_PATH/zlib/bin/zlib.dll
zlib.path = $$DESTDIR/install
INSTALLS += zlib
# ensure debug info even for RELEASE build
CONFIG += force_debug_info

View File

@ -518,9 +518,17 @@ void PDFPageContentProcessor::processContent(const QByteArray& content)
void PDFPageContentProcessor::processContentStream(const PDFStream* stream)
{
QByteArray content = m_document->getDecodedStream(stream);
try
{
QByteArray content = m_document->getDecodedStream(stream);
processContent(content);
processContent(content);
}
catch (PDFParserException exception)
{
m_operands.clear();
m_errorList.append(PDFRenderError(RenderErrorType::Error, exception.getMessage()));
}
}
void PDFPageContentProcessor::processForm(const QMatrix& matrix, const QRectF& boundingBox, const PDFObject& resources, const QByteArray& content)

View File

@ -660,7 +660,7 @@ QByteArray PDFStandardSecurityHandler::decryptUsingFilter(const QByteArray& data
std::vector<uint8_t> inputKeyData = convertByteArrayToVector(m_authorizationData.fileEncryptionKey);
uint32_t objectNumber = qToLittleEndian(static_cast<uint32_t>(reference.objectNumber));
uint32_t generation = qToLittleEndian(static_cast<uint32_t>(reference.generation));
inputKeyData.insert(inputKeyData.cend(), { uint8_t(objectNumber & 0xFF), uint8_t((objectNumber >> 8) && 0xFF), uint8_t((objectNumber >> 16) && 0xFF), uint8_t(generation & 0xFF), uint8_t((generation >> 8) && 0xFF), });
inputKeyData.insert(inputKeyData.cend(), { uint8_t(objectNumber & 0xFF), uint8_t((objectNumber >> 8) & 0xFF), uint8_t((objectNumber >> 16) & 0xFF), uint8_t(generation & 0xFF), uint8_t((generation >> 8) & 0xFF) });
std::vector<uint8_t> objectEncryptionKey(MD5_DIGEST_LENGTH, uint8_t(0));
MD5(inputKeyData.data(), inputKeyData.size(), objectEncryptionKey.data());
@ -682,7 +682,7 @@ QByteArray PDFStandardSecurityHandler::decryptUsingFilter(const QByteArray& data
std::vector<uint8_t> inputKeyData = convertByteArrayToVector(m_authorizationData.fileEncryptionKey);
uint32_t objectNumber = qToLittleEndian(static_cast<uint32_t>(reference.objectNumber));
uint32_t generation = qToLittleEndian(static_cast<uint32_t>(reference.generation));
inputKeyData.insert(inputKeyData.cend(), { uint8_t(objectNumber & 0xFF), uint8_t((objectNumber >> 8) && 0xFF), uint8_t((objectNumber >> 16) && 0xFF), uint8_t(generation & 0xFF), uint8_t((generation >> 8) && 0xFF), 0x73, 0x41, 0x6C, 0x54 });
inputKeyData.insert(inputKeyData.cend(), { uint8_t(objectNumber & 0xFF), uint8_t((objectNumber >> 8) & 0xFF), uint8_t((objectNumber >> 16) & 0xFF), uint8_t(generation & 0xFF), uint8_t((generation >> 8) & 0xFF), 0x73, 0x41, 0x6C, 0x54 });
std::vector<uint8_t> objectEncryptionKey(MD5_DIGEST_LENGTH, uint8_t(0));
MD5(inputKeyData.data(), inputKeyData.size(), objectEncryptionKey.data());

View File

@ -20,6 +20,9 @@
#include "pdfconstants.h"
#include "pdfparser.h"
#include "pdfsecurityhandler.h"
#include "pdfutils.h"
#include <zlib.h>
#include <QtEndian>
@ -395,16 +398,55 @@ QByteArray PDFFlateDecodeFilter::apply(const QByteArray& data,
}
}
uint32_t size = data.size();
QByteArray dataToUncompress;
dataToUncompress.resize(sizeof(decltype(size)) + data.size());
qToBigEndian(size, dataToUncompress.data());
std::copy(data.cbegin(), data.cend(), std::next(dataToUncompress.begin(), sizeof(decltype(size))));
PDFStreamPredictor predictor = PDFStreamPredictor::createPredictor(objectFetcher, parameters);
return predictor.apply(qUncompress(dataToUncompress));
return predictor.apply(uncompress(data));
}
QByteArray PDFFlateDecodeFilter::uncompress(const QByteArray& data)
{
QByteArray result;
z_stream stream = { };
stream.next_in = const_cast<Bytef*>(convertByteArrayToUcharPtr(data));
stream.avail_in = data.size();
std::array<Bytef, 1024> outputBuffer = { };
int error = inflateInit(&stream);
if (error != Z_OK)
{
throw PDFParserException(PDFTranslationContext::tr("Failed to initialize flate decompression stream."));
}
do
{
stream.next_out = outputBuffer.data();
stream.avail_out = static_cast<uInt>(outputBuffer.size());
error = inflate(&stream, Z_NO_FLUSH);
int bytesWritten = int(outputBuffer.size()) - stream.avail_out;
result.append(reinterpret_cast<const char*>(outputBuffer.data()), bytesWritten);
} while (error == Z_OK);
QString errorMessage;
if (stream.msg)
{
errorMessage = QString::fromLatin1(stream.msg);
}
inflateEnd(&stream);
switch (error)
{
case Z_STREAM_END:
break; // No error, normal behaviour
default:
throw PDFParserException(PDFTranslationContext::tr("Error decompressing by flate method: %1").arg(errorMessage));
}
return result;
}
QByteArray PDFRunLengthDecodeFilter::apply(const QByteArray& data,

View File

@ -184,6 +184,9 @@ public:
const PDFObjectFetcher& objectFetcher,
const PDFObject& parameters,
const PDFSecurityHandler* securityHandler) const override;
private:
static QByteArray uncompress(const QByteArray& data);
};
class PDFFORQTLIBSHARED_EXPORT PDFRunLengthDecodeFilter : public PDFStreamFilter