Align fax encoder interface with JPEG encoder interface. Just pass a bitmap in instead of multiple parameters that describe various bitmap attributes. Along the way, do more checks to safeguard against integer overflows and consolidate more CFX_PSRenderer fax encoding code into FaxCompressData(). Also pass the bitmap around using a RetainPtr with move semantics, instead of passing around a const-ref RetainPtr. Change-Id: I2d0b4180541048f48f2f345b86cd4011761c3b68 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/98010 Commit-Queue: Lei Zhang <thestig@chromium.org> Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcodec/fax/faxmodule.cpp b/core/fxcodec/fax/faxmodule.cpp index 542a7dd..d5b8262 100644 --- a/core/fxcodec/fax/faxmodule.cpp +++ b/core/fxcodec/fax/faxmodule.cpp
@@ -11,6 +11,7 @@ #include <algorithm> #include <iterator> #include <memory> +#include <utility> #include "build/build_config.h" #include "core/fxcodec/scanlinedecoder.h" @@ -24,6 +25,11 @@ #include "third_party/base/numerics/safe_conversions.h" #include "third_party/base/span.h" +#if BUILDFLAG(IS_WIN) +#include "core/fxcrt/span_util.h" +#include "core/fxge/dib/cfx_dibbase.h" +#endif + namespace fxcodec { namespace { @@ -675,10 +681,7 @@ class FaxEncoder { public: - FaxEncoder(pdfium::span<const uint8_t> src_span, - int width, - int height, - int pitch); + explicit FaxEncoder(RetainPtr<CFX_DIBBase> src); ~FaxEncoder(); DataVector<uint8_t> Encode(); @@ -687,8 +690,9 @@ void FaxEncodeRun(int run, bool bWhite); void AddBitStream(int data, int bitlen); + // Must outlive `m_RefLineSpan`. + RetainPtr<CFX_DIBBase> const m_Src; int m_DestBitpos = 0; - const pdfium::span<const uint8_t> m_SrcSpan; const int m_Cols; const int m_Rows; const int m_Pitch; @@ -699,17 +703,15 @@ pdfium::span<const uint8_t> m_RefLineSpan; }; -FaxEncoder::FaxEncoder(pdfium::span<const uint8_t> src_span, - int width, - int height, - int pitch) - : m_SrcSpan(src_span), - m_Cols(width), - m_Rows(height), - m_Pitch(pitch), +FaxEncoder::FaxEncoder(RetainPtr<CFX_DIBBase> src) + : m_Src(std::move(src)), + m_Cols(m_Src->GetWidth()), + m_Rows(m_Src->GetHeight()), + m_Pitch(m_Src->GetPitch()), m_InitialRefLine(m_Pitch, 0xff), m_LineBuf(Fx2DSizeOrDie(8, m_Pitch)), m_RefLineSpan(m_InitialRefLine) { + DCHECK_EQ(1, m_Src->GetBPP()); m_DestBuf.SetAllocStep(10240); } @@ -798,8 +800,7 @@ m_DestBitpos = 0; uint8_t last_byte = 0; for (int i = 0; i < m_Rows; ++i) { - pdfium::span<const uint8_t> scan_line = - m_SrcSpan.subspan(i * m_Pitch, m_Pitch); + pdfium::span<const uint8_t> scan_line = m_Src->GetScanline(i); std::fill(std::begin(m_LineBuf), std::end(m_LineBuf), 0); m_LineBuf[0] = last_byte; FaxEncode2DLine(scan_line); @@ -816,11 +817,9 @@ } // namespace // static -DataVector<uint8_t> FaxModule::FaxEncode(pdfium::span<const uint8_t> src_span, - int width, - int height, - int pitch) { - FaxEncoder encoder(src_span, width, height, pitch); +DataVector<uint8_t> FaxModule::FaxEncode(RetainPtr<CFX_DIBBase> src) { + DCHECK_EQ(1, src->GetBPP()); + FaxEncoder encoder(std::move(src)); return encoder.Encode(); }
diff --git a/core/fxcodec/fax/faxmodule.h b/core/fxcodec/fax/faxmodule.h index 882cf05..f0028bf 100644 --- a/core/fxcodec/fax/faxmodule.h +++ b/core/fxcodec/fax/faxmodule.h
@@ -16,8 +16,11 @@ #if BUILDFLAG(IS_WIN) #include "core/fxcrt/data_vector.h" +#include "core/fxcrt/retain_ptr.h" #endif +class CFX_DIBBase; + namespace fxcodec { class ScanlineDecoder; @@ -45,10 +48,8 @@ uint8_t* dest_buf); #if BUILDFLAG(IS_WIN) - static DataVector<uint8_t> FaxEncode(pdfium::span<const uint8_t> src_span, - int width, - int height, - int pitch); + // `src` must have a BPP value of 1. + static DataVector<uint8_t> FaxEncode(RetainPtr<CFX_DIBBase> src); #endif // BUILDFLAG(IS_WIN) FaxModule() = delete;
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp index 243c038..c51ada6 100644 --- a/core/fxge/win32/cfx_psrenderer.cpp +++ b/core/fxge/win32/cfx_psrenderer.cpp
@@ -19,6 +19,7 @@ #include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_memory_wrappers.h" +#include "core/fxcrt/fx_safe_types.h" #include "core/fxcrt/fx_stream.h" #include "core/fxcrt/span_util.h" #include "core/fxge/cfx_fillrenderoptions.h" @@ -524,22 +525,13 @@ const int width = pSource->GetWidth(); const int height = pSource->GetHeight(); - const int pitch = pSource->GetPitch(); buf << width << " " << height; if (pSource->GetBPP() == 1 && !pSource->HasPalette()) { - const uint32_t src_size = height * pitch; - DataVector<uint8_t> src_buf(src_size); - { - auto src_buf_span = pdfium::make_span(src_buf); - for (int row = 0; row < height; row++) { - pdfium::span<const uint8_t> src_scan = pSource->GetScanline(row); - fxcrt::spancpy(src_buf_span.subspan(row * pitch, pitch), src_scan); - } - } + FaxCompressResult compress_result = FaxCompressData(pSource); + if (compress_result.data.empty()) + return false; - FaxCompressResult compress_result = - FaxCompressData(std::move(src_buf), width, height, pitch); if (pSource->IsMaskFormat()) { SetColor(color); m_bColorSet = false; @@ -843,20 +835,30 @@ } CFX_PSRenderer::FaxCompressResult CFX_PSRenderer::FaxCompressData( - DataVector<uint8_t> src_buf, - int width, - int height, - int pitch) const { + RetainPtr<CFX_DIBBase> src) const { + DCHECK_EQ(1, src->GetBPP()); + FaxCompressResult result; - if (width * height <= 128) { - src_buf.resize(pitch * height); - result.data = std::move(src_buf); - result.compressed = false; - } else { - result.data = - m_pEncoderIface->pFaxEncodeFunc(src_buf, width, height, pitch); + const int height = src->GetHeight(); + const int pitch = src->GetPitch(); + FX_SAFE_UINT32 safe_size = pitch; + safe_size *= height; + if (!safe_size.IsValid()) + return result; + + if (safe_size.ValueOrDie() > 128) { + result.data = m_pEncoderIface->pFaxEncodeFunc(std::move(src)); result.compressed = true; + return result; } + + result.data.resize(safe_size.ValueOrDie()); + auto dest_span = pdfium::make_span(result.data); + for (int row = 0; row < height; row++) { + pdfium::span<const uint8_t> src_scan = src->GetScanline(row); + fxcrt::spancpy(dest_span.subspan(row * pitch, pitch), src_scan); + } + result.compressed = false; return result; }
diff --git a/core/fxge/win32/cfx_psrenderer.h b/core/fxge/win32/cfx_psrenderer.h index 31214de..ebe1b8c 100644 --- a/core/fxge/win32/cfx_psrenderer.h +++ b/core/fxge/win32/cfx_psrenderer.h
@@ -37,10 +37,7 @@ struct EncoderIface { DataVector<uint8_t> (*pA85EncodeFunc)(pdfium::span<const uint8_t> src_span); - DataVector<uint8_t> (*pFaxEncodeFunc)(pdfium::span<const uint8_t> src_span, - int width, - int height, - int pitch); + DataVector<uint8_t> (*pFaxEncodeFunc)(RetainPtr<CFX_DIBBase> src); DataVector<uint8_t> (*pFlateEncodeFunc)(pdfium::span<const uint8_t> src_span); bool (*pJpegEncodeFunc)(const RetainPtr<CFX_DIBBase>& pSource, uint8_t** dest_buf, @@ -159,10 +156,7 @@ CFX_Font* font, float font_size, fxcrt::ostringstream& buf); - FaxCompressResult FaxCompressData(DataVector<uint8_t> src_buf, - int width, - int height, - int pitch) const; + FaxCompressResult FaxCompressData(RetainPtr<CFX_DIBBase> src) const; absl::optional<PSCompressResult> PSCompressData( pdfium::span<const uint8_t> src_span) const; void WritePreambleString(ByteStringView str);