[poppler] poppler/ImageEmbeddingUtils.cc
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Nov 30 14:11:48 UTC 2021
poppler/ImageEmbeddingUtils.cc | 52 +++++++++++++++--------------------------
1 file changed, 20 insertions(+), 32 deletions(-)
New commits:
commit d1be2ba7a8e324d09646bbb0355574feaa6d98ca
Author: Albert Astals Cid <aacid at kde.org>
Date: Tue Nov 30 00:07:25 2021 +0100
Fix memory leak when embedders are not available
diff --git a/poppler/ImageEmbeddingUtils.cc b/poppler/ImageEmbeddingUtils.cc
index eeaa9ad9..4abdfc35 100644
--- a/poppler/ImageEmbeddingUtils.cc
+++ b/poppler/ImageEmbeddingUtils.cc
@@ -3,6 +3,7 @@
// ImageEmbeddingUtils.cc
//
// Copyright (C) 2021 Georgiy Sgibnev <georgiy at sgibnev.com>. Work sponsored by lab50.net.
+// Copyright (C) 2021 Albert Astals Cid <aacid at kde.org>
//
// This file is licensed under the GPLv2 or later
//
@@ -85,7 +86,7 @@ class PngEmbedder : public ImageEmbedder
// Used with png_set_read_fn().
class LibpngInputStream
{
- uint8_t *m_fileContent;
+ std::unique_ptr<uint8_t[]> m_fileContent;
uint8_t *m_iterator;
png_size_t m_remainingSize;
@@ -98,12 +99,11 @@ class PngEmbedder : public ImageEmbedder
}
public:
- // LibpngInputStream takes ownership over the buffer.
- LibpngInputStream(uint8_t *fileContent, const Goffset size) : m_fileContent(fileContent), m_iterator(fileContent), m_remainingSize(size) { }
+ LibpngInputStream(std::unique_ptr<uint8_t[]> &&fileContent, const Goffset size) : m_fileContent(std::move(fileContent)), m_iterator(m_fileContent.get()), m_remainingSize(size) { }
LibpngInputStream() = delete;
LibpngInputStream(const LibpngInputStream &) = delete;
LibpngInputStream &operator=(const LibpngInputStream &) = delete;
- ~LibpngInputStream() { gfree(m_fileContent); }
+ ~LibpngInputStream() = default;
// Pass this static function to png_set_read_fn().
static void readCallback(png_structp png, png_bytep out, png_size_t size)
@@ -219,30 +219,26 @@ public:
Ref embedImage(XRef *xref) override;
- // The function takes ownership over fileContent.
- static std::unique_ptr<ImageEmbedder> create(uint8_t *fileContent, const Goffset fileSize)
+ static std::unique_ptr<ImageEmbedder> create(std::unique_ptr<uint8_t[]> &&fileContent, const Goffset fileSize)
{
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (png == nullptr) {
error(errInternal, -1, "Couldn't load PNG. png_create_read_struct() failed");
- gfree(fileContent);
return nullptr;
}
png_infop info = png_create_info_struct(png);
if (info == nullptr) {
error(errInternal, -1, "Couldn't load PNG. png_create_info_struct() failed");
png_destroy_read_struct(&png, nullptr, nullptr);
- gfree(fileContent);
return nullptr;
}
if (setjmp(png_jmpbuf(png))) {
error(errInternal, -1, "Couldn't load PNG. Failed to set up error handling for reading PNG");
png_destroy_read_struct(&png, &info, nullptr);
- gfree(fileContent);
return nullptr;
}
- LibpngInputStream *stream = new LibpngInputStream(fileContent, fileSize);
+ LibpngInputStream *stream = new LibpngInputStream(std::move(fileContent), fileSize);
png_set_read_fn(png, stream, LibpngInputStream::readCallback);
png_read_info(png, info);
fixPng(png, info);
@@ -298,26 +294,20 @@ static void jpegExitErrorHandler(j_common_ptr info)
// Transforms a JPEG image to XObject.
class JpegEmbedder : public ImageEmbedder
{
- uint8_t *m_fileContent;
+ std::unique_ptr<uint8_t[]> m_fileContent;
Goffset m_fileSize;
- JpegEmbedder(const int width, const int height, uint8_t *fileContent, const Goffset fileSize) : ImageEmbedder(width, height), m_fileContent(fileContent), m_fileSize(fileSize) { }
+ JpegEmbedder(const int width, const int height, std::unique_ptr<uint8_t[]> &&fileContent, const Goffset fileSize) : ImageEmbedder(width, height), m_fileContent(std::move(fileContent)), m_fileSize(fileSize) { }
public:
JpegEmbedder() = delete;
JpegEmbedder(const JpegEmbedder &) = delete;
JpegEmbedder &operator=(const JpegEmbedder &) = delete;
- ~JpegEmbedder() override
- {
- if (m_fileContent) {
- gfree(m_fileContent);
- }
- }
+ ~JpegEmbedder() override = default;
Ref embedImage(XRef *xref) override;
- // The function takes ownership over fileContent.
- static std::unique_ptr<ImageEmbedder> create(uint8_t *fileContent, const Goffset fileSize)
+ static std::unique_ptr<ImageEmbedder> create(std::unique_ptr<uint8_t[]> &&fileContent, const Goffset fileSize)
{
jpeg_decompress_struct info;
JpegErrorManager errorManager;
@@ -331,10 +321,10 @@ public:
}
jpeg_create_decompress(&info);
- jpeg_mem_src(&info, fileContent, fileSize);
+ jpeg_mem_src(&info, fileContent.get(), fileSize);
jpeg_read_header(&info, TRUE);
jpeg_start_decompress(&info);
- auto result = std::unique_ptr<ImageEmbedder>(new JpegEmbedder(info.output_width, info.output_height, fileContent, fileSize));
+ auto result = std::unique_ptr<ImageEmbedder>(new JpegEmbedder(info.output_width, info.output_height, std::move(fileContent), fileSize));
jpeg_abort_decompress(&info);
jpeg_destroy_decompress(&info);
return result;
@@ -348,8 +338,7 @@ Ref JpegEmbedder::embedImage(XRef *xref)
}
Dict *baseImageDict = createImageDict(xref, DEVICE_RGB, m_width, m_height, 8);
baseImageDict->add("Filter", Object(objName, "DCTDecode"));
- Ref baseImageRef = xref->addStreamObject(baseImageDict, m_fileContent, m_fileSize);
- m_fileContent = nullptr;
+ Ref baseImageRef = xref->addStreamObject(baseImageDict, m_fileContent.release(), m_fileSize);
return baseImageRef;
}
#endif
@@ -362,28 +351,27 @@ Ref embed(XRef *xref, const GooFile &imageFile)
error(errIO, -1, "Image file size could not be calculated");
return Ref::INVALID();
}
- uint8_t *fileContent = (uint8_t *)gmalloc(fileSize);
- const Goffset bytesRead = imageFile.read((char *)fileContent, fileSize, 0);
+ std::unique_ptr<uint8_t[]> fileContent = std::make_unique<uint8_t[]>(fileSize);
+ const Goffset bytesRead = imageFile.read((char *)fileContent.get(), fileSize, 0);
if ((bytesRead != fileSize) || (fileSize < MAX_MAGIC_NUM_SIZE)) {
- gfree(fileContent);
error(errIO, -1, "Couldn't load the image file");
return Ref::INVALID();
}
std::unique_ptr<ImageEmbedder> embedder;
- if (checkMagicNum(fileContent, PNG_MAGIC_NUM, sizeof(PNG_MAGIC_NUM))) {
+ if (checkMagicNum(fileContent.get(), PNG_MAGIC_NUM, sizeof(PNG_MAGIC_NUM))) {
#ifdef ENABLE_LIBPNG
- embedder = PngEmbedder::create(fileContent, fileSize);
+ embedder = PngEmbedder::create(std::move(fileContent), fileSize);
#else
error(errUnimplemented, -1, "PNG format is not supported");
#endif
- } else if (checkMagicNum(fileContent, JPEG_MAGIC_NUM, sizeof(JPEG_MAGIC_NUM))) {
+ } else if (checkMagicNum(fileContent.get(), JPEG_MAGIC_NUM, sizeof(JPEG_MAGIC_NUM))) {
#ifdef ENABLE_LIBJPEG
- embedder = JpegEmbedder::create(fileContent, fileSize);
+ embedder = JpegEmbedder::create(std::move(fileContent), fileSize);
#else
error(errUnimplemented, -1, "JPEG format is not supported");
#endif
- } else if (checkMagicNum(fileContent, JPEG2000_MAGIC_NUM, sizeof(JPEG2000_MAGIC_NUM))) {
+ } else if (checkMagicNum(fileContent.get(), JPEG2000_MAGIC_NUM, sizeof(JPEG2000_MAGIC_NUM))) {
// TODO: implement JPEG2000 support using libopenjpeg2.
error(errUnimplemented, -1, "JPEG2000 format is not supported");
return Ref::INVALID();
More information about the poppler
mailing list