Remove NoDestructor usage in progressive image decoders
Add static methods to initialize/destroy {Bmp,Gif,Jpeg} progressive
decoders when the XFA module is initialized/destroyed. This lets
FPDF_DestroyLibrary() free more memory and work as it was originally
intended.
Bug: pdfium:1876
Change-Id: I4c3ca311b408e0befe837b52e7c0934dcd815088
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/113111
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcodec/bmp/bmp_progressive_decoder.cpp b/core/fxcodec/bmp/bmp_progressive_decoder.cpp
index 4ab9fda..61e770a 100644
--- a/core/fxcodec/bmp/bmp_progressive_decoder.cpp
+++ b/core/fxcodec/bmp/bmp_progressive_decoder.cpp
@@ -8,13 +8,31 @@
#include "core/fxcodec/bmp/bmp_decoder.h"
#include "core/fxcodec/cfx_codec_memory.h"
+#include "third_party/base/check.h"
namespace fxcodec {
+namespace {
+
+BmpProgressiveDecoder* g_bmp_decoder = nullptr;
+
+} // namespace
+
+// static
+void BmpProgressiveDecoder::InitializeGlobals() {
+ CHECK(!g_bmp_decoder);
+ g_bmp_decoder = new BmpProgressiveDecoder();
+}
+
+// static
+void BmpProgressiveDecoder::DestroyGlobals() {
+ delete g_bmp_decoder;
+ g_bmp_decoder = nullptr;
+}
+
// static
BmpProgressiveDecoder* BmpProgressiveDecoder::GetInstance() {
- static pdfium::base::NoDestructor<BmpProgressiveDecoder> s;
- return s.get();
+ return g_bmp_decoder;
}
BmpProgressiveDecoder::BmpProgressiveDecoder() = default;
diff --git a/core/fxcodec/bmp/bmp_progressive_decoder.h b/core/fxcodec/bmp/bmp_progressive_decoder.h
index f2040c8..865e112 100644
--- a/core/fxcodec/bmp/bmp_progressive_decoder.h
+++ b/core/fxcodec/bmp/bmp_progressive_decoder.h
@@ -8,7 +8,6 @@
#define CORE_FXCODEC_BMP_BMP_PROGRESSIVE_DECODER_H_
#include "core/fxcodec/progressive_decoder_iface.h"
-#include "third_party/base/no_destructor.h"
#ifndef PDF_ENABLE_XFA_BMP
#error "BMP must be enabled"
@@ -18,6 +17,9 @@
class BmpProgressiveDecoder final : public ProgressiveDecoderIface {
public:
+ static void InitializeGlobals();
+ static void DestroyGlobals();
+
static BmpProgressiveDecoder* GetInstance();
// ProgressiveDecoderIface:
@@ -26,8 +28,6 @@
RetainPtr<CFX_CodecMemory> codec_memory) override;
private:
- friend pdfium::base::NoDestructor<BmpProgressiveDecoder>;
-
BmpProgressiveDecoder();
~BmpProgressiveDecoder() override;
};
diff --git a/core/fxcodec/gif/gif_progressive_decoder.cpp b/core/fxcodec/gif/gif_progressive_decoder.cpp
index 78c6a8c..8816ea6 100644
--- a/core/fxcodec/gif/gif_progressive_decoder.cpp
+++ b/core/fxcodec/gif/gif_progressive_decoder.cpp
@@ -8,13 +8,31 @@
#include "core/fxcodec/cfx_codec_memory.h"
#include "core/fxcodec/gif/gif_decoder.h"
+#include "third_party/base/check.h"
namespace fxcodec {
+namespace {
+
+GifProgressiveDecoder* g_gif_decoder = nullptr;
+
+} // namespace
+
+// static
+void GifProgressiveDecoder::InitializeGlobals() {
+ CHECK(!g_gif_decoder);
+ g_gif_decoder = new GifProgressiveDecoder();
+}
+
+// static
+void GifProgressiveDecoder::DestroyGlobals() {
+ delete g_gif_decoder;
+ g_gif_decoder = nullptr;
+}
+
// static
GifProgressiveDecoder* GifProgressiveDecoder::GetInstance() {
- static pdfium::base::NoDestructor<GifProgressiveDecoder> s;
- return s.get();
+ return g_gif_decoder;
}
GifProgressiveDecoder::GifProgressiveDecoder() = default;
diff --git a/core/fxcodec/gif/gif_progressive_decoder.h b/core/fxcodec/gif/gif_progressive_decoder.h
index 6b58c3c..52075a6 100644
--- a/core/fxcodec/gif/gif_progressive_decoder.h
+++ b/core/fxcodec/gif/gif_progressive_decoder.h
@@ -8,7 +8,6 @@
#define CORE_FXCODEC_GIF_GIF_PROGRESSIVE_DECODER_H_
#include "core/fxcodec/progressive_decoder_iface.h"
-#include "third_party/base/no_destructor.h"
#ifndef PDF_ENABLE_XFA_GIF
#error "GIF must be enabled"
@@ -18,6 +17,9 @@
class GifProgressiveDecoder final : public ProgressiveDecoderIface {
public:
+ static void InitializeGlobals();
+ static void DestroyGlobals();
+
static GifProgressiveDecoder* GetInstance();
// ProgressiveDecoderIface:
@@ -26,8 +28,6 @@
RetainPtr<CFX_CodecMemory> codec_memory) override;
private:
- friend pdfium::base::NoDestructor<GifProgressiveDecoder>;
-
GifProgressiveDecoder();
~GifProgressiveDecoder() override;
};
diff --git a/core/fxcodec/jpeg/jpeg_progressive_decoder.cpp b/core/fxcodec/jpeg/jpeg_progressive_decoder.cpp
index 1f1a7c3..d4d8839 100644
--- a/core/fxcodec/jpeg/jpeg_progressive_decoder.cpp
+++ b/core/fxcodec/jpeg/jpeg_progressive_decoder.cpp
@@ -84,10 +84,27 @@
namespace fxcodec {
+namespace {
+
+JpegProgressiveDecoder* g_jpeg_decoder = nullptr;
+
+} // namespace
+
+// static
+void JpegProgressiveDecoder::InitializeGlobals() {
+ CHECK(!g_jpeg_decoder);
+ g_jpeg_decoder = new JpegProgressiveDecoder();
+}
+
+// static
+void JpegProgressiveDecoder::DestroyGlobals() {
+ delete g_jpeg_decoder;
+ g_jpeg_decoder = nullptr;
+}
+
// static
JpegProgressiveDecoder* JpegProgressiveDecoder::GetInstance() {
- static pdfium::base::NoDestructor<JpegProgressiveDecoder> s;
- return s.get();
+ return g_jpeg_decoder;
}
// static
diff --git a/core/fxcodec/jpeg/jpeg_progressive_decoder.h b/core/fxcodec/jpeg/jpeg_progressive_decoder.h
index 6429d01..a94e33a 100644
--- a/core/fxcodec/jpeg/jpeg_progressive_decoder.h
+++ b/core/fxcodec/jpeg/jpeg_progressive_decoder.h
@@ -12,7 +12,6 @@
#include <memory>
#include "core/fxcodec/progressive_decoder_iface.h"
-#include "third_party/base/no_destructor.h"
namespace fxcodec {
@@ -20,6 +19,9 @@
class JpegProgressiveDecoder final : public ProgressiveDecoderIface {
public:
+ static void InitializeGlobals();
+ static void DestroyGlobals();
+
static JpegProgressiveDecoder* GetInstance();
static std::unique_ptr<Context> Start();
@@ -41,8 +43,6 @@
RetainPtr<CFX_CodecMemory> codec_memory) override;
private:
- friend pdfium::base::NoDestructor<JpegProgressiveDecoder>;
-
JpegProgressiveDecoder();
~JpegProgressiveDecoder() override;
};
diff --git a/core/fxcodec/progressive_decoder_unittest.cpp b/core/fxcodec/progressive_decoder_unittest.cpp
index ccb0c03..682cd19 100644
--- a/core/fxcodec/progressive_decoder_unittest.cpp
+++ b/core/fxcodec/progressive_decoder_unittest.cpp
@@ -14,6 +14,7 @@
#include "core/fxcodec/fx_codec.h"
#include "core/fxcodec/fx_codec_def.h"
+#include "core/fxcodec/jpeg/jpeg_progressive_decoder.h"
#include "core/fxcrt/cfx_read_only_span_stream.h"
#include "core/fxcrt/cfx_read_only_vector_stream.h"
#include "core/fxcrt/data_vector.h"
@@ -26,10 +27,12 @@
#ifdef PDF_ENABLE_XFA_BMP
#include "core/fxcodec/bmp/bmp_decoder.h"
+#include "core/fxcodec/bmp/bmp_progressive_decoder.h"
#endif // PDF_ENABLE_XFA_BMP
#ifdef PDF_ENABLE_XFA_GIF
#include "core/fxcodec/gif/gif_decoder.h"
+#include "core/fxcodec/gif/gif_progressive_decoder.h"
#endif // PDF_ENABLE_XFA_GIF
namespace fxcodec {
@@ -55,10 +58,31 @@
return status;
}
+class ProgressiveDecoderTest : public testing::Test {
+ void SetUp() override {
+#ifdef PDF_ENABLE_XFA_BMP
+ BmpProgressiveDecoder::InitializeGlobals();
+#endif
+#ifdef PDF_ENABLE_XFA_GIF
+ GifProgressiveDecoder::InitializeGlobals();
+#endif
+ JpegProgressiveDecoder::InitializeGlobals();
+ }
+ void TearDown() override {
+ JpegProgressiveDecoder::DestroyGlobals();
+#ifdef PDF_ENABLE_XFA_GIF
+ GifProgressiveDecoder::DestroyGlobals();
+#endif
+#ifdef PDF_ENABLE_XFA_BMP
+ BmpProgressiveDecoder::DestroyGlobals();
+#endif
+ }
+};
+
} // namespace
#ifdef PDF_ENABLE_XFA_BMP
-TEST(ProgressiveDecoder, Indexed8Bmp) {
+TEST_F(ProgressiveDecoderTest, Indexed8Bmp) {
static constexpr uint8_t kInput[] = {
0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
@@ -91,7 +115,7 @@
EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
}
-TEST(ProgressiveDecoder, Indexed8BmpWithInvalidIndex) {
+TEST_F(ProgressiveDecoderTest, Indexed8BmpWithInvalidIndex) {
static constexpr uint8_t kInput[] = {
0x42, 0x4d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a,
0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
@@ -123,7 +147,7 @@
EXPECT_EQ(FXCODEC_STATUS::kError, status);
}
-TEST(ProgressiveDecoder, Direct24Bmp) {
+TEST_F(ProgressiveDecoderTest, Direct24Bmp) {
static constexpr uint8_t kInput[] = {
0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
@@ -155,7 +179,7 @@
EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
}
-TEST(ProgressiveDecoder, Direct32Bmp) {
+TEST_F(ProgressiveDecoderTest, Direct32Bmp) {
static constexpr uint8_t kInput[] = {
0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
@@ -187,7 +211,7 @@
EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
}
-TEST(ProgressiveDecoder, BmpWithDataOffsetBeforeEndOfHeader) {
+TEST_F(ProgressiveDecoderTest, BmpWithDataOffsetBeforeEndOfHeader) {
static constexpr uint8_t kInput[] = {
0x42, 0x4d, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x00,
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
@@ -219,7 +243,7 @@
EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
}
-TEST(ProgressiveDecoder, BmpWithDataOffsetAfterEndOfHeader) {
+TEST_F(ProgressiveDecoderTest, BmpWithDataOffsetAfterEndOfHeader) {
static constexpr uint8_t kInput[] = {
0x42, 0x4d, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00,
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
@@ -251,7 +275,7 @@
EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0x00));
}
-TEST(ProgressiveDecoder, LargeBmp) {
+TEST_F(ProgressiveDecoderTest, LargeBmp) {
// Construct a 24-bit BMP larger than `kBlockSize` (4096 bytes).
static constexpr uint8_t kWidth = 37;
static constexpr uint8_t kHeight = 38;
@@ -304,7 +328,7 @@
#endif // PDF_ENABLE_XFA_BMP
#ifdef PDF_ENABLE_XFA_GIF
-TEST(ProgressiveDecoder, Gif87a) {
+TEST_F(ProgressiveDecoderTest, Gif87a) {
static constexpr uint8_t kInput[] = {
0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80, 0x01,
0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x2c, 0x00, 0x00, 0x00, 0x00,
@@ -334,7 +358,7 @@
EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0xff));
}
-TEST(ProgressiveDecoder, Gif89a) {
+TEST_F(ProgressiveDecoderTest, Gif89a) {
static constexpr uint8_t kInput[] = {
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x80,
0x01, 0x00, 0x40, 0x80, 0xc0, 0x80, 0x80, 0x80, 0x21, 0xf9, 0x04,
@@ -365,7 +389,7 @@
EXPECT_THAT(bitmap->GetScanline(0), ElementsAre(0xc0, 0x80, 0x40, 0xff));
}
-TEST(ProgressiveDecoder, GifInsufficientCodeSize) {
+TEST_F(ProgressiveDecoderTest, GifInsufficientCodeSize) {
// This GIF causes `LZWDecompressor::Create()` to fail because the minimum
// code size is too small for the palette.
static constexpr uint8_t kInput[] = {
@@ -398,7 +422,7 @@
EXPECT_EQ(FXCODEC_STATUS::kError, status);
}
-TEST(ProgressiveDecoder, GifDecodeAcrossScanlines) {
+TEST_F(ProgressiveDecoderTest, GifDecodeAcrossScanlines) {
// This GIF contains an LZW code unit split across 2 scanlines. The decoder
// must continue decoding the second scanline using the residual data.
static constexpr uint8_t kInput[] = {
@@ -435,7 +459,7 @@
0x80, 0x40, 0xff, 0xc0, 0x80, 0x40, 0xff));
}
-TEST(ProgressiveDecoder, GifDecodeAcrossSubblocks) {
+TEST_F(ProgressiveDecoderTest, GifDecodeAcrossSubblocks) {
// This GIF contains a scanline split across 2 data sub-blocks. The decoder
// must continue decoding in the second sub-block.
static constexpr uint8_t kInput[] = {
diff --git a/fpdfsdk/fpdfxfa/BUILD.gn b/fpdfsdk/fpdfxfa/BUILD.gn
index b3d5fe0..4374f59 100644
--- a/fpdfsdk/fpdfxfa/BUILD.gn
+++ b/fpdfsdk/fpdfxfa/BUILD.gn
@@ -27,6 +27,7 @@
"../../core/fpdfapi/page",
"../../core/fpdfapi/parser",
"../../core/fpdfapi/render",
+ "../../core/fxcodec",
"../../core/fxcrt",
"../../fxbarcode",
"../../fxjs",
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
index 8d48750..1271fbd 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_context.cpp
@@ -15,6 +15,7 @@
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_seekablemultistream.h"
+#include "core/fxcodec/jpeg/jpeg_progressive_decoder.h"
#include "core/fxcrt/autonuller.h"
#include "core/fxcrt/fixed_zeroed_data_vector.h"
#include "core/fxcrt/stl_util.h"
@@ -40,6 +41,14 @@
#include "xfa/fxfa/cxfa_fontmgr.h"
#include "xfa/fxfa/cxfa_readynodeiterator.h"
+#ifdef PDF_ENABLE_XFA_BMP
+#include "core/fxcodec/bmp/bmp_progressive_decoder.h"
+#endif
+
+#ifdef PDF_ENABLE_XFA_GIF
+#include "core/fxcodec/gif/gif_progressive_decoder.h"
+#endif
+
namespace {
bool IsValidAlertButton(int type) {
@@ -94,9 +103,23 @@
void CPDFXFA_ModuleInit() {
CFGAS_GEModule::Create();
BC_Library_Init();
+#ifdef PDF_ENABLE_XFA_BMP
+ fxcodec::BmpProgressiveDecoder::InitializeGlobals();
+#endif
+#ifdef PDF_ENABLE_XFA_GIF
+ fxcodec::GifProgressiveDecoder::InitializeGlobals();
+#endif
+ fxcodec::JpegProgressiveDecoder::InitializeGlobals();
}
void CPDFXFA_ModuleDestroy() {
+ fxcodec::JpegProgressiveDecoder::DestroyGlobals();
+#ifdef PDF_ENABLE_XFA_GIF
+ fxcodec::GifProgressiveDecoder::DestroyGlobals();
+#endif
+#ifdef PDF_ENABLE_XFA_BMP
+ fxcodec::BmpProgressiveDecoder::DestroyGlobals();
+#endif
BC_Library_Destroy();
CFGAS_GEModule::Destroy();
}