From e21501d9427539828b5d547b9d20a752d06914aa Mon Sep 17 00:00:00 2001 From: tsepez Date: Tue, 2 Aug 2016 13:36:16 -0700 Subject: Bound total pixels in JBig2 images to avoid overflows later. Also make these private to ensure they aren't modified so as to violate the bounds checks applied at creation time. BUG=633002 Review-Url: https://codereview.chromium.org/2202013002 --- BUILD.gn | 1 + core/fxcodec/jbig2/JBig2_Context.cpp | 14 ++-- core/fxcodec/jbig2/JBig2_GrdProc.cpp | 22 +++--- core/fxcodec/jbig2/JBig2_GrrdProc.cpp | 20 +++--- core/fxcodec/jbig2/JBig2_Image.cpp | 107 ++++++++++++++++------------ core/fxcodec/jbig2/JBig2_Image.h | 26 +++---- core/fxcodec/jbig2/JBig2_Image_unittest.cpp | 105 +++++++++++++++++++++++++++ core/fxcodec/jbig2/JBig2_SddProc.cpp | 2 +- core/fxcodec/jbig2/JBig2_TrdProc.cpp | 16 ++--- 9 files changed, 214 insertions(+), 99 deletions(-) create mode 100644 core/fxcodec/jbig2/JBig2_Image_unittest.cpp diff --git a/BUILD.gn b/BUILD.gn index 4b6e6581a8..60d656fb7d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1550,6 +1550,7 @@ test("pdfium_unittests") { "core/fpdfdoc/cpdf_filespec_unittest.cpp", "core/fpdftext/fpdf_text_int_unittest.cpp", "core/fxcodec/codec/fx_codec_jpx_unittest.cpp", + "core/fxcodec/jbig2/JBig2_Image_unittest.cpp", "core/fxcrt/cfx_retain_ptr_unittest.cpp", "core/fxcrt/fx_basic_bstring_unittest.cpp", "core/fxcrt/fx_basic_gcc_unittest.cpp", diff --git a/core/fxcodec/jbig2/JBig2_Context.cpp b/core/fxcodec/jbig2/JBig2_Context.cpp index 256ce3910a..911eb0bf63 100644 --- a/core/fxcodec/jbig2/JBig2_Context.cpp +++ b/core/fxcodec/jbig2/JBig2_Context.cpp @@ -924,7 +924,7 @@ int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) { if (!m_bBufSpecified) { JBig2PageInfo* pPageInfo = m_PageInfoList.back(); if ((pPageInfo->m_bIsStriped == 1) && - (ri.y + ri.height > m_pPage->m_nHeight)) { + (ri.y + ri.height > m_pPage->height())) { m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); } } @@ -1015,8 +1015,8 @@ int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment, pHRD->HNUMPATS = pPatternDict->NUMPATS; pHRD->HPATS = pPatternDict->HDPATS; - pHRD->HPW = pPatternDict->HDPATS[0]->m_nWidth; - pHRD->HPH = pPatternDict->HDPATS[0]->m_nHeight; + pHRD->HPW = pPatternDict->HDPATS[0]->width(); + pHRD->HPH = pPatternDict->HDPATS[0]->height(); pSegment->m_nResultType = JBIG2_IMAGE_POINTER; if (pHRD->HMMR == 0) { const size_t size = GetHuffContextSize(pHRD->HTEMPLATE); @@ -1042,7 +1042,7 @@ int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment, if (!m_bBufSpecified) { JBig2PageInfo* pPageInfo = m_PageInfoList.back(); if (pPageInfo->m_bIsStriped == 1 && - ri.y + ri.height > m_pPage->m_nHeight) { + ri.y + ri.height > m_pPage->height()) { m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); } } @@ -1108,7 +1108,7 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment, if (!m_bBufSpecified) { JBig2PageInfo* pPageInfo = m_PageInfoList.back(); if ((pPageInfo->m_bIsStriped == 1) && - (m_ri.y + m_ri.height > m_pPage->m_nHeight)) { + (m_ri.y + m_ri.height > m_pPage->height())) { m_pPage->expand(m_ri.y + m_ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); } @@ -1142,7 +1142,7 @@ int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment, if (!m_bBufSpecified) { JBig2PageInfo* pPageInfo = m_PageInfoList.back(); if ((pPageInfo->m_bIsStriped == 1) && - (m_ri.y + m_ri.height > m_pPage->m_nHeight)) { + (m_ri.y + m_ri.height > m_pPage->height())) { m_pPage->expand(m_ri.y + m_ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); } @@ -1215,7 +1215,7 @@ int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) { if (!m_bBufSpecified) { JBig2PageInfo* pPageInfo = m_PageInfoList.back(); if ((pPageInfo->m_bIsStriped == 1) && - (ri.y + ri.height > m_pPage->m_nHeight)) { + (ri.y + ri.height > m_pPage->height())) { m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0); } } diff --git a/core/fxcodec/jbig2/JBig2_GrdProc.cpp b/core/fxcodec/jbig2/JBig2_GrdProc.cpp index 9527c1eaf8..b692909c01 100644 --- a/core/fxcodec/jbig2/JBig2_GrdProc.cpp +++ b/core/fxcodec/jbig2/JBig2_GrdProc.cpp @@ -71,7 +71,7 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_opt3( FX_BOOL LTP = FALSE; uint8_t* pLine = GBREG->m_pData; - int32_t nStride = GBREG->m_nStride; + int32_t nStride = GBREG->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); @@ -197,7 +197,7 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_opt3( FX_BOOL LTP = FALSE; uint8_t* pLine = GBREG->m_pData; - int32_t nStride = GBREG->m_nStride; + int32_t nStride = GBREG->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); @@ -320,7 +320,7 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_opt3( FX_BOOL LTP = FALSE; uint8_t* pLine = GBREG->m_pData; - int32_t nStride = GBREG->m_nStride; + int32_t nStride = GBREG->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); @@ -441,7 +441,7 @@ CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_opt3( FX_BOOL LTP = FALSE; uint8_t* pLine = GBREG->m_pData; - int32_t nStride = GBREG->m_nStride; + int32_t nStride = GBREG->stride(); int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); for (uint32_t h = 0; h < GBH; h++) { @@ -602,7 +602,7 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith(IFX_Pause* pPause) { } } m_ReplaceRect.left = 0; - m_ReplaceRect.right = pImage->m_nWidth; + m_ReplaceRect.right = pImage->width(); m_ReplaceRect.top = iline; m_ReplaceRect.bottom = m_loopIndex; if (m_ProssiveStatus == FXCODEC_STATUS_DECODE_FINISH) { @@ -624,9 +624,9 @@ FXCODEC_STATUS CJBig2_GRDProc::Start_decode_MMR(CJBig2_Image** pImage, } bitpos = (int)pStream->getBitPos(); FaxG4Decode(pStream->getBuf(), pStream->getLength(), &bitpos, - (*pImage)->m_pData, GBW, GBH, (*pImage)->m_nStride); + (*pImage)->m_pData, GBW, GBH, (*pImage)->stride()); pStream->setBitPos(bitpos); - for (i = 0; (uint32_t)i < (*pImage)->m_nStride * GBH; i++) { + for (i = 0; (uint32_t)i < (*pImage)->stride() * GBH; i++) { (*pImage)->m_pData[i] = ~(*pImage)->m_pData[i]; } m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH; @@ -653,7 +653,7 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_opt3( if (!m_pLine) { m_pLine = pImage->m_pData; } - int32_t nStride = pImage->m_nStride; + int32_t nStride = pImage->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); @@ -791,7 +791,7 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_opt3( if (!m_pLine) { m_pLine = pImage->m_pData; } - int32_t nStride = pImage->m_nStride; + int32_t nStride = pImage->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); @@ -924,7 +924,7 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_opt3( if (!m_pLine) { m_pLine = pImage->m_pData; } - int32_t nStride = pImage->m_nStride; + int32_t nStride = pImage->stride(); int32_t nStride2 = nStride << 1; int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); @@ -1057,7 +1057,7 @@ FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_opt3( if (!m_pLine) m_pLine = pImage->m_pData; - int32_t nStride = pImage->m_nStride; + int32_t nStride = pImage->stride(); int32_t nLineBytes = ((GBW + 7) >> 3) - 1; int32_t nBitsLeft = GBW - (nLineBytes << 3); for (; m_loopIndex < GBH; m_loopIndex++) { diff --git a/core/fxcodec/jbig2/JBig2_GrrdProc.cpp b/core/fxcodec/jbig2/JBig2_GrrdProc.cpp index 25c9ea2d8a..672692da54 100644 --- a/core/fxcodec/jbig2/JBig2_GrrdProc.cpp +++ b/core/fxcodec/jbig2/JBig2_GrrdProc.cpp @@ -20,13 +20,13 @@ CJBig2_Image* CJBig2_GRRDProc::decode(CJBig2_ArithDecoder* pArithDecoder, if (GRTEMPLATE == 0) { if ((GRAT[0] == -1) && (GRAT[1] == -1) && (GRAT[2] == -1) && (GRAT[3] == -1) && (GRREFERENCEDX == 0) && - (GRW == (uint32_t)GRREFERENCE->m_nWidth)) { + (GRW == (uint32_t)GRREFERENCE->width())) { return decode_Template0_opt(pArithDecoder, grContext); } return decode_Template0_unopt(pArithDecoder, grContext); } - if ((GRREFERENCEDX == 0) && (GRW == (uint32_t)GRREFERENCE->m_nWidth)) + if ((GRREFERENCEDX == 0) && (GRW == (uint32_t)GRREFERENCE->width())) return decode_Template1_opt(pArithDecoder, grContext); return decode_Template1_unopt(pArithDecoder, grContext); } @@ -162,10 +162,10 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template0_opt( FX_BOOL LTP = FALSE; uint8_t* pLine = GRREG->m_pData; uint8_t* pLineR = GRREFERENCE->m_pData; - intptr_t nStride = GRREG->m_nStride; - intptr_t nStrideR = GRREFERENCE->m_nStride; - int32_t GRWR = GRREFERENCE->m_nWidth; - int32_t GRHR = GRREFERENCE->m_nHeight; + intptr_t nStride = GRREG->stride(); + intptr_t nStrideR = GRREFERENCE->stride(); + int32_t GRWR = GRREFERENCE->width(); + int32_t GRHR = GRREFERENCE->height(); if (GRREFERENCEDY < -GRHR + 1 || GRREFERENCEDY > GRHR - 1) GRREFERENCEDY = 0; intptr_t nOffset = -GRREFERENCEDY * nStrideR; @@ -396,10 +396,10 @@ CJBig2_Image* CJBig2_GRRDProc::decode_Template1_opt( FX_BOOL LTP = FALSE; uint8_t* pLine = GRREG->m_pData; uint8_t* pLineR = GRREFERENCE->m_pData; - intptr_t nStride = GRREG->m_nStride; - intptr_t nStrideR = GRREFERENCE->m_nStride; - int32_t GRWR = GRREFERENCE->m_nWidth; - int32_t GRHR = GRREFERENCE->m_nHeight; + intptr_t nStride = GRREG->stride(); + intptr_t nStrideR = GRREFERENCE->stride(); + int32_t GRWR = GRREFERENCE->width(); + int32_t GRHR = GRREFERENCE->height(); if (GRREFERENCEDY < -GRHR + 1 || GRREFERENCEDY > GRHR - 1) { GRREFERENCEDY = 0; } diff --git a/core/fxcodec/jbig2/JBig2_Image.cpp b/core/fxcodec/jbig2/JBig2_Image.cpp index cf0ee3bbbc..b8cb21165b 100644 --- a/core/fxcodec/jbig2/JBig2_Image.cpp +++ b/core/fxcodec/jbig2/JBig2_Image.cpp @@ -10,46 +10,65 @@ #include "core/fxcrt/include/fx_coordinates.h" #include "core/fxcrt/include/fx_safe_types.h" -CJBig2_Image::CJBig2_Image(int32_t w, int32_t h) { +namespace { + +const int kMaxImagePixels = INT_MAX - 31; +const int kMaxImageBytes = kMaxImagePixels / 8; + +} // namespace + +CJBig2_Image::CJBig2_Image(int32_t w, int32_t h) + : m_pData(nullptr), + m_nWidth(0), + m_nHeight(0), + m_nStride(0), + m_bOwnsBuffer(true) { + if (w < 0 || h < 0 || w > kMaxImagePixels) + return; + + int32_t stride_pixels = (w + 31) & ~31; + if (h > kMaxImagePixels / stride_pixels) + return; + m_nWidth = w; m_nHeight = h; - if (m_nWidth <= 0 || m_nHeight <= 0 || m_nWidth > INT_MAX - 31) { - m_pData = nullptr; - m_bNeedFree = FALSE; - return; - } - m_nStride = ((w + 31) >> 5) << 2; - if (m_nStride * m_nHeight > 0 && 104857600 / (int)m_nStride > m_nHeight) { - m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight); - } else { - m_pData = nullptr; - } - m_bNeedFree = TRUE; + m_nStride = stride_pixels / 8; + m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight); } -CJBig2_Image::CJBig2_Image(int32_t w, - int32_t h, - int32_t stride, - uint8_t* pBuf) { + +CJBig2_Image::CJBig2_Image(int32_t w, int32_t h, int32_t stride, uint8_t* pBuf) + : m_pData(nullptr), + m_nWidth(0), + m_nHeight(0), + m_nStride(0), + m_bOwnsBuffer(false) { + if (w < 0 || h < 0 || stride < 0 || stride > kMaxImageBytes) + return; + + int32_t stride_pixels = 8 * stride; + if (stride_pixels < w || h > kMaxImagePixels / stride_pixels) + return; + m_nWidth = w; m_nHeight = h; m_nStride = stride; m_pData = pBuf; - m_bNeedFree = FALSE; } -CJBig2_Image::CJBig2_Image(const CJBig2_Image& im) { - m_nWidth = im.m_nWidth; - m_nHeight = im.m_nHeight; - m_nStride = im.m_nStride; - if (im.m_pData) { + +CJBig2_Image::CJBig2_Image(const CJBig2_Image& other) + : m_pData(nullptr), + m_nWidth(other.m_nWidth), + m_nHeight(other.m_nHeight), + m_nStride(other.m_nStride), + m_bOwnsBuffer(true) { + if (other.m_pData) { m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight); - JBIG2_memcpy(m_pData, im.m_pData, m_nStride * m_nHeight); - } else { - m_pData = nullptr; + JBIG2_memcpy(m_pData, other.m_pData, m_nStride * m_nHeight); } - m_bNeedFree = TRUE; } + CJBig2_Image::~CJBig2_Image() { - if (m_bNeedFree) { + if (m_bOwnsBuffer) { FX_Free(m_pData); } } @@ -209,30 +228,24 @@ CJBig2_Image* CJBig2_Image::subImage(int32_t x, } return pImage; } + void CJBig2_Image::expand(int32_t h, FX_BOOL v) { - if (!m_pData || h <= m_nHeight) { + if (!m_pData || h <= m_nHeight || h > kMaxImageBytes / m_nStride) return; - } - uint32_t dwH = pdfium::base::checked_cast(h); - uint32_t dwStride = pdfium::base::checked_cast(m_nStride); - uint32_t dwHeight = pdfium::base::checked_cast(m_nHeight); - FX_SAFE_UINT32 safeMemSize = dwH; - safeMemSize *= dwStride; - if (!safeMemSize.IsValid()) { - return; - } - // The guaranteed reallocated memory is to be < 4GB (unsigned int). - m_pData = FX_Realloc(uint8_t, m_pData, safeMemSize.ValueOrDie()); - // The result of dwHeight * dwStride doesn't overflow after the - // checking of safeMemSize. - // The same as the result of (dwH - dwHeight) * dwStride) because - // dwH - dwHeight is always less than dwH(h) which is checked in - // the calculation of dwH * dwStride. - JBIG2_memset(m_pData + dwHeight * dwStride, v ? 0xff : 0, - (dwH - dwHeight) * dwStride); + if (m_bOwnsBuffer) { + m_pData = FX_Realloc(uint8_t, m_pData, h * m_nStride); + } else { + uint8_t* pExternalBuffer = m_pData; + m_pData = FX_Alloc(uint8_t, h * m_nStride); + JBIG2_memcpy(m_pData, pExternalBuffer, m_nHeight * m_nStride); + m_bOwnsBuffer = true; + } + JBIG2_memset(m_pData + m_nHeight * m_nStride, v ? 0xff : 0, + (h - m_nHeight) * m_nStride); m_nHeight = h; } + FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, int32_t x, int32_t y, diff --git a/core/fxcodec/jbig2/JBig2_Image.h b/core/fxcodec/jbig2/JBig2_Image.h index a18a95d596..f27b86e854 100644 --- a/core/fxcodec/jbig2/JBig2_Image.h +++ b/core/fxcodec/jbig2/JBig2_Image.h @@ -9,6 +9,8 @@ #include "core/fxcodec/jbig2/JBig2_Define.h" +struct FX_RECT; + enum JBig2ComposeOp { JBIG2_COMPOSE_OR = 0, JBIG2_COMPOSE_AND = 1, @@ -17,23 +19,21 @@ enum JBig2ComposeOp { JBIG2_COMPOSE_REPLACE = 4 }; -struct FX_RECT; class CJBig2_Image { public: CJBig2_Image(int32_t w, int32_t h); - CJBig2_Image(int32_t w, int32_t h, int32_t stride, uint8_t* pBuf); - CJBig2_Image(const CJBig2_Image& im); - ~CJBig2_Image(); - FX_BOOL getPixel(int32_t x, int32_t y); + int32_t width() const { return m_nWidth; } + int32_t height() const { return m_nHeight; } + int32_t stride() const { return m_nStride; } + FX_BOOL getPixel(int32_t x, int32_t y); int32_t setPixel(int32_t x, int32_t y, FX_BOOL v); void copyLine(int32_t hTo, int32_t hFrom); - void fill(FX_BOOL v); FX_BOOL composeTo(CJBig2_Image* pDst, @@ -67,19 +67,15 @@ class CJBig2_Image { const FX_RECT* pSrcRect); CJBig2_Image* subImage(int32_t x, int32_t y, int32_t w, int32_t h); - void expand(int32_t h, FX_BOOL v); - public: - int32_t m_nWidth; - - int32_t m_nHeight; - - int32_t m_nStride; - uint8_t* m_pData; - FX_BOOL m_bNeedFree; + private: + int32_t m_nWidth; // 1-bit pixels + int32_t m_nHeight; // lines + int32_t m_nStride; // bytes + bool m_bOwnsBuffer; }; #endif // CORE_FXCODEC_JBIG2_JBIG2_IMAGE_H_ diff --git a/core/fxcodec/jbig2/JBig2_Image_unittest.cpp b/core/fxcodec/jbig2/JBig2_Image_unittest.cpp new file mode 100644 index 0000000000..788f922a02 --- /dev/null +++ b/core/fxcodec/jbig2/JBig2_Image_unittest.cpp @@ -0,0 +1,105 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// TODO(tsepez) this requires a lot more testing. + +#include + +#include "core/fxcodec/jbig2/JBig2_Image.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const int32_t kWidthPixels = 80; +const int32_t kWidthBytes = 10; +const int32_t kStrideBytes = kWidthBytes + 1; // For testing stride != width. +const int32_t kHeightLines = 20; +const int32_t kLargerHeightLines = 100; +const int32_t kTooLargeHeightLines = 40000000; + +} // namespace + +TEST(fxcodec, JBig2ImageCreate) { + CJBig2_Image img(kWidthPixels, kHeightLines); + img.setPixel(0, 0, true); + img.setPixel(kWidthPixels - 1, kHeightLines - 1, false); + EXPECT_EQ(kWidthPixels, img.width()); + EXPECT_EQ(kHeightLines, img.height()); + EXPECT_TRUE(img.getPixel(0, 0)); + EXPECT_FALSE(img.getPixel(kWidthPixels - 1, kHeightLines - 1)); +} + +TEST(fxcodec, JBig2ImageCreateTooBig) { + CJBig2_Image img(kWidthPixels, kTooLargeHeightLines); + EXPECT_EQ(0, img.width()); + EXPECT_EQ(0, img.height()); + EXPECT_EQ(nullptr, img.m_pData); +} + +TEST(fxcodec, JBig2ImageCreateExternal) { + uint8_t buf[kHeightLines * kStrideBytes]; + CJBig2_Image img(kWidthPixels, kHeightLines, kStrideBytes, buf); + img.setPixel(0, 0, true); + img.setPixel(kWidthPixels - 1, kHeightLines - 1, false); + EXPECT_EQ(kWidthPixels, img.width()); + EXPECT_EQ(kHeightLines, img.height()); + EXPECT_TRUE(img.getPixel(0, 0)); + EXPECT_FALSE(img.getPixel(kWidthPixels - 1, kHeightLines - 1)); +} + +TEST(fxcodec, JBig2ImageCreateExternalTooBig) { + uint8_t buf[kHeightLines * kStrideBytes]; + CJBig2_Image img(kWidthPixels, kTooLargeHeightLines, kStrideBytes, buf); + EXPECT_EQ(0, img.width()); + EXPECT_EQ(0, img.height()); + EXPECT_EQ(nullptr, img.m_pData); +} + +TEST(fxcodec, JBig2ImageExpand) { + CJBig2_Image img(kWidthPixels, kHeightLines); + img.setPixel(0, 0, true); + img.setPixel(kWidthPixels - 1, kHeightLines - 1, false); + img.expand(kLargerHeightLines, true); + EXPECT_EQ(kWidthPixels, img.width()); + EXPECT_EQ(kLargerHeightLines, img.height()); + EXPECT_TRUE(img.getPixel(0, 0)); + EXPECT_FALSE(img.getPixel(kWidthPixels - 1, kHeightLines - 1)); + EXPECT_TRUE(img.getPixel(kWidthPixels - 1, kLargerHeightLines - 1)); +} + +TEST(fxcodec, JBig2ImageExpandTooBig) { + CJBig2_Image img(kWidthPixels, kHeightLines); + img.setPixel(0, 0, true); + img.setPixel(kWidthPixels - 1, kHeightLines - 1, false); + img.expand(kTooLargeHeightLines, true); + EXPECT_EQ(kWidthPixels, img.width()); + EXPECT_EQ(kHeightLines, img.height()); + EXPECT_TRUE(img.getPixel(0, 0)); + EXPECT_FALSE(img.getPixel(kWidthPixels - 1, kHeightLines - 1)); +} + +TEST(fxcodec, JBig2ImageExpandExternal) { + uint8_t buf[kHeightLines * kStrideBytes]; + CJBig2_Image img(kWidthPixels, kHeightLines, kStrideBytes, buf); + img.setPixel(0, 0, true); + img.setPixel(kWidthPixels - 1, kHeightLines - 1, false); + img.expand(kLargerHeightLines, true); + EXPECT_EQ(kWidthPixels, img.width()); + EXPECT_EQ(kLargerHeightLines, img.height()); + EXPECT_TRUE(img.getPixel(0, 0)); + EXPECT_FALSE(img.getPixel(kWidthPixels - 1, kHeightLines - 1)); + EXPECT_TRUE(img.getPixel(kWidthPixels - 1, kLargerHeightLines - 1)); +} + +TEST(fxcodec, JBig2ImageExpandExternalTooBig) { + uint8_t buf[kHeightLines * kStrideBytes]; + CJBig2_Image img(kWidthPixels, kHeightLines, kStrideBytes, buf); + img.setPixel(0, 0, true); + img.setPixel(kWidthPixels - 1, kHeightLines - 1, false); + img.expand(kTooLargeHeightLines, true); + EXPECT_EQ(kWidthPixels, img.width()); + EXPECT_EQ(kHeightLines, img.height()); + EXPECT_TRUE(img.getPixel(0, 0)); + EXPECT_FALSE(img.getPixel(kWidthPixels - 1, kHeightLines - 1)); +} diff --git a/core/fxcodec/jbig2/JBig2_SddProc.cpp b/core/fxcodec/jbig2/JBig2_SddProc.cpp index 9ab6cb8a2e..c6adfce784 100644 --- a/core/fxcodec/jbig2/JBig2_SddProc.cpp +++ b/core/fxcodec/jbig2/JBig2_SddProc.cpp @@ -523,7 +523,7 @@ CJBig2_SymbolDict* CJBig2_SDDProc::decode_Huffman( if (pStream->getByteLeft() >= stride * HCHEIGHT) { BHC = new CJBig2_Image(TOTWIDTH, HCHEIGHT); for (I = 0; I < HCHEIGHT; I++) { - JBIG2_memcpy(BHC->m_pData + I * BHC->m_nStride, + JBIG2_memcpy(BHC->m_pData + I * BHC->stride(), pStream->getPointer(), stride); pStream->offset(stride); } diff --git a/core/fxcodec/jbig2/JBig2_TrdProc.cpp b/core/fxcodec/jbig2/JBig2_TrdProc.cpp index 177db9dec9..f3dd6be2b3 100644 --- a/core/fxcodec/jbig2/JBig2_TrdProc.cpp +++ b/core/fxcodec/jbig2/JBig2_TrdProc.cpp @@ -114,8 +114,8 @@ CJBig2_Image* CJBig2_TRDProc::decode_Huffman(CJBig2_BitStream* pStream, if (!IBOI) return nullptr; - uint32_t WOI = IBOI->m_nWidth; - uint32_t HOI = IBOI->m_nHeight; + uint32_t WOI = IBOI->width(); + uint32_t HOI = IBOI->height(); if ((int)(WOI + RDWI) < 0 || (int)(HOI + RDHI) < 0) return nullptr; @@ -150,8 +150,8 @@ CJBig2_Image* CJBig2_TRDProc::decode_Huffman(CJBig2_BitStream* pStream, if (!IBI) { continue; } - uint32_t WI = IBI->m_nWidth; - uint32_t HI = IBI->m_nHeight; + uint32_t WI = IBI->width(); + uint32_t HI = IBI->height(); if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) || (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) { CURS = CURS + WI - 1; @@ -327,8 +327,8 @@ CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, if (!IBOI) return nullptr; - uint32_t WOI = IBOI->m_nWidth; - uint32_t HOI = IBOI->m_nHeight; + uint32_t WOI = IBOI->width(); + uint32_t HOI = IBOI->height(); if ((int)(WOI + RDWI) < 0 || (int)(HOI + RDHI) < 0) return nullptr; @@ -350,8 +350,8 @@ CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder, if (!pIBI) return nullptr; - uint32_t WI = pIBI->m_nWidth; - uint32_t HI = pIBI->m_nHeight; + uint32_t WI = pIBI->width(); + uint32_t HI = pIBI->height(); if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) || (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) { CURS += WI - 1; -- cgit v1.2.3