Bugfixing: Crash in case of invalid image, invalid font CID character 0 width

This commit is contained in:
Jakub Melka
2020-01-02 13:13:52 +01:00
parent 78b56ab007
commit b490dc7c89
2 changed files with 51 additions and 25 deletions

View File

@ -174,42 +174,61 @@ QImage PDFAbstractColorSpace::getImage(const PDFImageData& imageData,
const unsigned int imageWidth = imageData.getWidth(); const unsigned int imageWidth = imageData.getWidth();
const unsigned int imageHeight = imageData.getHeight(); const unsigned int imageHeight = imageData.getHeight();
//for (unsigned int i = 0, rowCount = imageData.getHeight(); i < rowCount; ++i)
QMutex exceptionMutex;
std::optional<PDFException> exception;
auto transformPixelLine = [&](unsigned int i) auto transformPixelLine = [&](unsigned int i)
{ {
PDFBitReader reader(&imageData.getData(), imageData.getBitsPerComponent()); try
reader.seek(i * imageData.getStride());
const double max = reader.max();
const double coefficient = 1.0 / max;
unsigned char* outputLine = image.scanLine(i);
std::vector<float> inputColors(imageWidth * componentCount, 0.0f);
auto itInputColor = inputColors.begin();
for (unsigned int j = 0; j < imageData.getWidth(); ++j)
{ {
for (unsigned int k = 0; k < componentCount; ++k) PDFBitReader reader(&imageData.getData(), imageData.getBitsPerComponent());
{ reader.seek(i * imageData.getStride());
PDFReal value = reader.read();
// Interpolate value, if it is not empty const double max = reader.max();
if (!decode.empty()) const double coefficient = 1.0 / max;
unsigned char* outputLine = image.scanLine(i);
std::vector<float> inputColors(imageWidth * componentCount, 0.0f);
auto itInputColor = inputColors.begin();
for (unsigned int j = 0; j < imageData.getWidth(); ++j)
{
for (unsigned int k = 0; k < componentCount; ++k)
{ {
*itInputColor++ = interpolate(value, 0.0, max, decode[2 * k], decode[2 * k + 1]); PDFReal value = reader.read();
}
else // Interpolate value, if it is not empty
{ if (!decode.empty())
*itInputColor++ = value * coefficient; {
*itInputColor++ = interpolate(value, 0.0, max, decode[2 * k], decode[2 * k + 1]);
}
else
{
*itInputColor++ = value * coefficient;
}
} }
} }
}
fillRGBBuffer(inputColors, outputLine, intent, cms, reporter); fillRGBBuffer(inputColors, outputLine, intent, cms, reporter);
}
catch (PDFException lineException)
{
QMutexLocker lock(&exceptionMutex);
if (!exception)
{
exception = lineException;
}
}
}; };
auto range = PDFIntegerRange<unsigned int>(0, imageHeight); auto range = PDFIntegerRange<unsigned int>(0, imageHeight);
std::for_each(std::execution::parallel_policy(), range.begin(), range.end(), transformPixelLine); std::for_each(std::execution::parallel_policy(), range.begin(), range.end(), transformPixelLine);
if (exception)
{
throw *exception;
}
return image; return image;
} }

View File

@ -538,10 +538,17 @@ void PDFRealizedFontImpl::fillTextSequence(const QByteArray& byteArray, TextSequ
} }
else else
{ {
reporter->reportRenderError(RenderErrorType::Warning, PDFTranslationContext::tr("Glyph for composite font character with cid '%1' not found.").arg(cid)); if (cid > 0)
{
// Character with CID == 0 is treated as default whitespace, it hasn't glyph
reporter->reportRenderError(RenderErrorType::Warning, PDFTranslationContext::tr("Glyph for composite font character with cid '%1' not found.").arg(cid));
}
if (glyphWidth > 0) if (glyphWidth > 0)
{ {
textSequence.items.emplace_back(nullptr, QChar(), glyphWidth * m_pixelSize * FONT_WIDTH_MULTIPLIER); // We do not multiply advance with font size and FONT_WIDTH_MULTIPLIER, because in the code,
// "advance" is treated as in font space.
textSequence.items.emplace_back(nullptr, QChar(), -glyphWidth);
} }
} }
} }