diff options
-rw-r--r-- | core/fxcodec/codec/fx_codec_flate.cpp | 156 |
1 files changed, 74 insertions, 82 deletions
diff --git a/core/fxcodec/codec/fx_codec_flate.cpp b/core/fxcodec/codec/fx_codec_flate.cpp index f0cbd6732a..eb68cedda5 100644 --- a/core/fxcodec/codec/fx_codec_flate.cpp +++ b/core/fxcodec/codec/fx_codec_flate.cpp @@ -17,6 +17,7 @@ #include "core/fxcrt/fx_extension.h" #include "third_party/base/numerics/safe_conversions.h" #include "third_party/base/ptr_util.h" +#include "third_party/base/span.h" #if defined(USE_SYSTEM_ZLIB) #include <zlib.h> @@ -42,15 +43,13 @@ namespace { static constexpr uint32_t kMaxTotalOutSize = 1024 * 1024 * 1024; // 1 GiB -uint32_t FlateGetPossiblyTruncatedTotalOut(void* context) { - return std::min(pdfium::base::saturated_cast<uint32_t>( - static_cast<z_stream*>(context)->total_out), +uint32_t FlateGetPossiblyTruncatedTotalOut(z_stream* context) { + return std::min(pdfium::base::saturated_cast<uint32_t>(context->total_out), kMaxTotalOutSize); } -uint32_t FlateGetPossiblyTruncatedTotalIn(void* context) { - return pdfium::base::saturated_cast<uint32_t>( - static_cast<z_stream*>(context)->total_in); +uint32_t FlateGetPossiblyTruncatedTotalIn(z_stream* context) { + return pdfium::base::saturated_cast<uint32_t>(context->total_in); } bool FlateCompress(unsigned char* dest_buf, @@ -60,28 +59,24 @@ bool FlateCompress(unsigned char* dest_buf, return compress(dest_buf, dest_size, src_buf, src_size) == Z_OK; } -void* FlateInit() { +z_stream* FlateInit() { z_stream* p = FX_Alloc(z_stream, 1); - memset(p, 0, sizeof(z_stream)); p->zalloc = my_alloc_func; p->zfree = my_free_func; inflateInit(p); return p; } -void FlateInput(void* context, - const unsigned char* src_buf, - uint32_t src_size) { - static_cast<z_stream*>(context)->next_in = - const_cast<unsigned char*>(src_buf); - static_cast<z_stream*>(context)->avail_in = src_size; +void FlateInput(z_stream* context, pdfium::span<const uint8_t> src_buf) { + context->next_in = const_cast<unsigned char*>(src_buf.data()); + context->avail_in = static_cast<uint32_t>(src_buf.size()); } -uint32_t FlateOutput(void* context, +uint32_t FlateOutput(z_stream* context, unsigned char* dest_buf, uint32_t dest_size) { - static_cast<z_stream*>(context)->next_out = dest_buf; - static_cast<z_stream*>(context)->avail_out = dest_size; + context->next_out = dest_buf; + context->avail_out = dest_size; uint32_t pre_pos = FlateGetPossiblyTruncatedTotalOut(context); int ret = inflate(static_cast<z_stream*>(context), Z_SYNC_FLUSH); @@ -95,15 +90,20 @@ uint32_t FlateOutput(void* context, return ret; } -uint32_t FlateGetAvailOut(void* context) { - return static_cast<z_stream*>(context)->avail_out; +uint32_t FlateGetAvailOut(z_stream* context) { + return context->avail_out; } -void FlateEnd(void* context) { - inflateEnd(static_cast<z_stream*>(context)); - static_cast<z_stream*>(context)->zfree(0, context); +void FlateEnd(z_stream* context) { + inflateEnd(context); + FX_Free(context); } +// For use with std::unique_ptr<z_stream>. +struct FlateDeleter { + inline void operator()(z_stream* context) { FlateEnd(context); } +}; + class CLZWDecoder { public: int Decode(uint8_t* output, @@ -489,22 +489,22 @@ bool TIFF_Predictor(uint8_t*& data_buf, return true; } -void FlateUncompress(const uint8_t* src_buf, - uint32_t src_size, +void FlateUncompress(pdfium::span<const uint8_t> src_buf, uint32_t orig_size, uint8_t*& dest_buf, uint32_t& dest_size, uint32_t& offset) { dest_buf = nullptr; dest_size = 0; - void* context = FlateInit(); + + std::unique_ptr<z_stream, FlateDeleter> context(FlateInit()); if (!context) return; - FlateInput(context, src_buf, src_size); + FlateInput(context.get(), src_buf); const uint32_t kMaxInitialAllocSize = 10000000; - uint32_t guess_size = orig_size ? orig_size : src_size * 2; + uint32_t guess_size = orig_size ? orig_size : src_buf.size() * 2; guess_size = std::min(guess_size, kMaxInitialAllocSize); uint32_t buf_size = guess_size; @@ -516,8 +516,8 @@ void FlateUncompress(const uint8_t* src_buf, std::vector<uint8_t*> result_tmp_bufs; uint8_t* cur_buf = guess_buf.release(); while (1) { - uint32_t ret = FlateOutput(context, cur_buf, buf_size); - uint32_t avail_buf_size = FlateGetAvailOut(context); + uint32_t ret = FlateOutput(context.get(), cur_buf, buf_size); + uint32_t avail_buf_size = FlateGetAvailOut(context.get()); if (ret != Z_OK || avail_buf_size != 0) { last_buf_size = buf_size - avail_buf_size; result_tmp_bufs.push_back(cur_buf); @@ -531,30 +531,30 @@ void FlateUncompress(const uint8_t* src_buf, // The TotalOut size returned from the library may not be big enough to // handle the content the library returns. We can only handle items // up to 4GB in size. - dest_size = FlateGetPossiblyTruncatedTotalOut(context); - offset = FlateGetPossiblyTruncatedTotalIn(context); + dest_size = FlateGetPossiblyTruncatedTotalOut(context.get()); + offset = FlateGetPossiblyTruncatedTotalIn(context.get()); if (result_tmp_bufs.size() == 1) { dest_buf = result_tmp_bufs[0]; - } else { - uint8_t* result_buf = FX_Alloc(uint8_t, dest_size); - uint32_t result_pos = 0; - uint32_t remaining = dest_size; - for (size_t i = 0; i < result_tmp_bufs.size(); i++) { - uint8_t* tmp_buf = result_tmp_bufs[i]; - uint32_t tmp_buf_size = buf_size; - if (i == result_tmp_bufs.size() - 1) - tmp_buf_size = last_buf_size; - - uint32_t cp_size = std::min(tmp_buf_size, remaining); - memcpy(result_buf + result_pos, tmp_buf, cp_size); - result_pos += cp_size; - remaining -= cp_size; - - FX_Free(result_tmp_bufs[i]); - } - dest_buf = result_buf; + return; + } + + uint8_t* result_buf = FX_Alloc(uint8_t, dest_size); + uint32_t result_pos = 0; + uint32_t remaining = dest_size; + for (size_t i = 0; i < result_tmp_bufs.size(); i++) { + uint8_t* tmp_buf = result_tmp_bufs[i]; + uint32_t tmp_buf_size = buf_size; + if (i == result_tmp_bufs.size() - 1) + tmp_buf_size = last_buf_size; + + uint32_t cp_size = std::min(tmp_buf_size, remaining); + memcpy(result_buf + result_pos, tmp_buf, cp_size); + result_pos += cp_size; + remaining -= cp_size; + + FX_Free(result_tmp_bufs[i]); } - FlateEnd(context); + dest_buf = result_buf; } enum class PredictorType : uint8_t { kNone, kFlate, kPng }; @@ -582,10 +582,9 @@ class CCodec_FlateScanlineDecoder : public CCodec_ScanlineDecoder { uint32_t GetSrcOffset() override; protected: - void* m_pFlate = nullptr; - const uint8_t* const m_SrcBuf; - const uint32_t m_SrcSize; - uint8_t* const m_pScanline; + std::unique_ptr<z_stream, FlateDeleter> m_pFlate; + pdfium::span<const uint8_t> const m_SrcBuf; + std::unique_ptr<uint8_t, FxFreeDeleter> const m_pScanline; }; CCodec_FlateScanlineDecoder::CCodec_FlateScanlineDecoder(const uint8_t* src_buf, @@ -601,35 +600,27 @@ CCodec_FlateScanlineDecoder::CCodec_FlateScanlineDecoder(const uint8_t* src_buf, nComps, bpc, CalculatePitch8(bpc, nComps, width).ValueOrDie()), - m_SrcBuf(src_buf), - m_SrcSize(src_size), + m_SrcBuf(src_buf, src_size), m_pScanline(FX_Alloc(uint8_t, m_Pitch)) {} -CCodec_FlateScanlineDecoder::~CCodec_FlateScanlineDecoder() { - FX_Free(m_pScanline); - if (m_pFlate) - FlateEnd(m_pFlate); -} +CCodec_FlateScanlineDecoder::~CCodec_FlateScanlineDecoder() = default; bool CCodec_FlateScanlineDecoder::v_Rewind() { - if (m_pFlate) - FlateEnd(m_pFlate); - - m_pFlate = FlateInit(); + m_pFlate.reset(FlateInit()); if (!m_pFlate) return false; - FlateInput(m_pFlate, m_SrcBuf, m_SrcSize); + FlateInput(m_pFlate.get(), m_SrcBuf); return true; } uint8_t* CCodec_FlateScanlineDecoder::v_GetNextLine() { - FlateOutput(m_pFlate, m_pScanline, m_Pitch); - return m_pScanline; + FlateOutput(m_pFlate.get(), m_pScanline.get(), m_Pitch); + return m_pScanline.get(); } uint32_t CCodec_FlateScanlineDecoder::GetSrcOffset() { - return FlateGetPossiblyTruncatedTotalIn(m_pFlate); + return FlateGetPossiblyTruncatedTotalIn(m_pFlate.get()); } class CCodec_FlatePredictorScanlineDecoder @@ -714,19 +705,19 @@ uint8_t* CCodec_FlatePredictorScanlineDecoder::v_GetNextLine() { GetNextLineWithPredictedPitch(); else GetNextLineWithoutPredictedPitch(); - return m_pScanline; + return m_pScanline.get(); } void CCodec_FlatePredictorScanlineDecoder::GetNextLineWithPredictedPitch() { if (m_Predictor == PredictorType::kPng) { - FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1); - PNG_PredictLine(m_pScanline, m_pPredictRaw, m_pLastLine, m_BitsPerComponent, - m_Colors, m_Columns); - memcpy(m_pLastLine, m_pScanline, m_PredictPitch); + FlateOutput(m_pFlate.get(), m_pPredictRaw, m_PredictPitch + 1); + PNG_PredictLine(m_pScanline.get(), m_pPredictRaw, m_pLastLine, + m_BitsPerComponent, m_Colors, m_Columns); + memcpy(m_pLastLine, m_pScanline.get(), m_PredictPitch); } else { ASSERT(m_Predictor == PredictorType::kFlate); - FlateOutput(m_pFlate, m_pScanline, m_Pitch); - TIFF_PredictLine(m_pScanline, m_PredictPitch, m_bpc, m_nComps, + FlateOutput(m_pFlate.get(), m_pScanline.get(), m_Pitch); + TIFF_PredictLine(m_pScanline.get(), m_PredictPitch, m_bpc, m_nComps, m_OutputWidth); } } @@ -735,26 +726,27 @@ void CCodec_FlatePredictorScanlineDecoder::GetNextLineWithoutPredictedPitch() { size_t bytes_to_go = m_Pitch; size_t read_leftover = m_LeftOver > bytes_to_go ? bytes_to_go : m_LeftOver; if (read_leftover) { - memcpy(m_pScanline, m_pPredictBuffer + m_PredictPitch - m_LeftOver, + memcpy(m_pScanline.get(), m_pPredictBuffer + m_PredictPitch - m_LeftOver, read_leftover); m_LeftOver -= read_leftover; bytes_to_go -= read_leftover; } while (bytes_to_go) { if (m_Predictor == PredictorType::kPng) { - FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1); + FlateOutput(m_pFlate.get(), m_pPredictRaw, m_PredictPitch + 1); PNG_PredictLine(m_pPredictBuffer, m_pPredictRaw, m_pLastLine, m_BitsPerComponent, m_Colors, m_Columns); memcpy(m_pLastLine, m_pPredictBuffer, m_PredictPitch); } else { ASSERT(m_Predictor == PredictorType::kFlate); - FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPitch); + FlateOutput(m_pFlate.get(), m_pPredictBuffer, m_PredictPitch); TIFF_PredictLine(m_pPredictBuffer, m_PredictPitch, m_BitsPerComponent, m_Colors, m_Columns); } size_t read_bytes = m_PredictPitch > bytes_to_go ? bytes_to_go : m_PredictPitch; - memcpy(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuffer, read_bytes); + memcpy(m_pScanline.get() + m_Pitch - bytes_to_go, m_pPredictBuffer, + read_bytes); m_LeftOver += m_PredictPitch - read_bytes; bytes_to_go -= read_bytes; } @@ -812,8 +804,8 @@ uint32_t CCodec_FlateModule::FlateOrLZWDecode(bool bLZW, (*dest_buf)[*dest_size] = '\0'; decoder->Decode(*dest_buf, *dest_size, src_buf, offset, bEarlyChange); } else { - FlateUncompress(src_buf, src_size, estimated_size, *dest_buf, *dest_size, - offset); + FlateUncompress(pdfium::make_span(src_buf, src_size), estimated_size, + *dest_buf, *dest_size, offset); } if (predictor_type == PredictorType::kNone) return offset; |