Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: core/fxcodec/jbig2/JBig2_Image.cpp

Issue 2202013002: Bound total pixels in JBig2 images to avoid overflows later. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Add tests Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 PDFium Authors. All rights reserved. 1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 6
7 #include <limits.h> 7 #include <limits.h>
8 8
9 #include "core/fxcodec/jbig2/JBig2_Image.h" 9 #include "core/fxcodec/jbig2/JBig2_Image.h"
10 #include "core/fxcrt/include/fx_coordinates.h" 10 #include "core/fxcrt/include/fx_coordinates.h"
11 #include "core/fxcrt/include/fx_safe_types.h" 11 #include "core/fxcrt/include/fx_safe_types.h"
12 12
13 CJBig2_Image::CJBig2_Image(int32_t w, int32_t h) { 13 namespace {
14
15 const int kMaxImagePixels = INT_MAX - 31;
16 const int kMaxImageBytes = kMaxImagePixels / 8;
17
18 } // namespace
19
20 CJBig2_Image::CJBig2_Image(int32_t w, int32_t h)
21 : m_pData(nullptr),
22 m_nWidth(0),
23 m_nHeight(0),
24 m_nStride(0),
25 m_bOwnsBuffer(true) {
26 if (w < 0 || h < 0 || w > kMaxImagePixels)
27 return;
28
29 int32_t stride_pixels = (w + 31) & ~31;
30 if (h > kMaxImagePixels / stride_pixels)
31 return;
32
14 m_nWidth = w; 33 m_nWidth = w;
15 m_nHeight = h; 34 m_nHeight = h;
16 if (m_nWidth <= 0 || m_nHeight <= 0 || m_nWidth > INT_MAX - 31) { 35 m_nStride = stride_pixels / 8;
17 m_pData = nullptr; 36 m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight);
18 m_bNeedFree = FALSE; 37 }
38
39 CJBig2_Image::CJBig2_Image(int32_t w, int32_t h, int32_t stride, uint8_t* pBuf)
40 : m_pData(nullptr),
41 m_nWidth(0),
42 m_nHeight(0),
43 m_nStride(0),
44 m_bOwnsBuffer(false) {
45 if (w < 0 || h < 0 || stride < 0 || stride > kMaxImageBytes)
19 return; 46 return;
20 } 47
21 m_nStride = ((w + 31) >> 5) << 2; 48 int32_t stride_pixels = 8 * stride;
22 if (m_nStride * m_nHeight > 0 && 104857600 / (int)m_nStride > m_nHeight) { 49 if (stride_pixels < w || h > kMaxImagePixels / stride_pixels)
23 m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight); 50 return;
24 } else { 51
25 m_pData = nullptr;
26 }
27 m_bNeedFree = TRUE;
28 }
29 CJBig2_Image::CJBig2_Image(int32_t w,
30 int32_t h,
31 int32_t stride,
32 uint8_t* pBuf) {
33 m_nWidth = w; 52 m_nWidth = w;
34 m_nHeight = h; 53 m_nHeight = h;
35 m_nStride = stride; 54 m_nStride = stride;
36 m_pData = pBuf; 55 m_pData = pBuf;
37 m_bNeedFree = FALSE;
38 } 56 }
39 CJBig2_Image::CJBig2_Image(const CJBig2_Image& im) { 57
40 m_nWidth = im.m_nWidth; 58 CJBig2_Image::CJBig2_Image(const CJBig2_Image& other)
41 m_nHeight = im.m_nHeight; 59 : m_pData(nullptr),
42 m_nStride = im.m_nStride; 60 m_nWidth(other.m_nWidth),
43 if (im.m_pData) { 61 m_nHeight(other.m_nHeight),
62 m_nStride(other.m_nStride),
63 m_bOwnsBuffer(true) {
64 if (other.m_pData) {
44 m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight); 65 m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight);
45 JBIG2_memcpy(m_pData, im.m_pData, m_nStride * m_nHeight); 66 JBIG2_memcpy(m_pData, other.m_pData, m_nStride * m_nHeight);
46 } else {
47 m_pData = nullptr;
48 } 67 }
49 m_bNeedFree = TRUE;
50 } 68 }
69
51 CJBig2_Image::~CJBig2_Image() { 70 CJBig2_Image::~CJBig2_Image() {
52 if (m_bNeedFree) { 71 if (m_bOwnsBuffer) {
53 FX_Free(m_pData); 72 FX_Free(m_pData);
54 } 73 }
55 } 74 }
56 FX_BOOL CJBig2_Image::getPixel(int32_t x, int32_t y) { 75 FX_BOOL CJBig2_Image::getPixel(int32_t x, int32_t y) {
57 if (!m_pData) { 76 if (!m_pData) {
58 return 0; 77 return 0;
59 } 78 }
60 int32_t m, n; 79 int32_t m, n;
61 if (x < 0 || x >= m_nWidth) { 80 if (x < 0 || x >= m_nWidth) {
62 return 0; 81 return 0;
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 pDst[1] = (uint8_t)(wTmp >> 16); 221 pDst[1] = (uint8_t)(wTmp >> 16);
203 pDst[2] = (uint8_t)(wTmp >> 8); 222 pDst[2] = (uint8_t)(wTmp >> 8);
204 pDst[3] = (uint8_t)wTmp; 223 pDst[3] = (uint8_t)wTmp;
205 } 224 }
206 pLineSrc += m_nStride; 225 pLineSrc += m_nStride;
207 pLineDst += pImage->m_nStride; 226 pLineDst += pImage->m_nStride;
208 } 227 }
209 } 228 }
210 return pImage; 229 return pImage;
211 } 230 }
231
212 void CJBig2_Image::expand(int32_t h, FX_BOOL v) { 232 void CJBig2_Image::expand(int32_t h, FX_BOOL v) {
213 if (!m_pData || h <= m_nHeight) { 233 if (!m_pData || h <= m_nHeight || h > kMaxImageBytes / m_nStride)
214 return; 234 return;
235
236 if (m_bOwnsBuffer) {
237 m_pData = FX_Realloc(uint8_t, m_pData, h * m_nStride);
238 } else {
239 uint8_t* pExternalBuffer = m_pData;
240 m_pData = FX_Alloc(uint8_t, h * m_nStride);
241 JBIG2_memcpy(m_pData, pExternalBuffer, m_nHeight * m_nStride);
242 m_bOwnsBuffer = true;
215 } 243 }
216 uint32_t dwH = pdfium::base::checked_cast<uint32_t>(h); 244 JBIG2_memset(m_pData + m_nHeight * m_nStride, v ? 0xff : 0,
217 uint32_t dwStride = pdfium::base::checked_cast<uint32_t>(m_nStride); 245 (h - m_nHeight) * m_nStride);
218 uint32_t dwHeight = pdfium::base::checked_cast<uint32_t>(m_nHeight);
219 FX_SAFE_UINT32 safeMemSize = dwH;
220 safeMemSize *= dwStride;
221 if (!safeMemSize.IsValid()) {
222 return;
223 }
224 // The guaranteed reallocated memory is to be < 4GB (unsigned int).
225 m_pData = FX_Realloc(uint8_t, m_pData, safeMemSize.ValueOrDie());
226
227 // The result of dwHeight * dwStride doesn't overflow after the
228 // checking of safeMemSize.
229 // The same as the result of (dwH - dwHeight) * dwStride) because
230 // dwH - dwHeight is always less than dwH(h) which is checked in
231 // the calculation of dwH * dwStride.
232 JBIG2_memset(m_pData + dwHeight * dwStride, v ? 0xff : 0,
233 (dwH - dwHeight) * dwStride);
234 m_nHeight = h; 246 m_nHeight = h;
235 } 247 }
248
236 FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst, 249 FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst,
237 int32_t x, 250 int32_t x,
238 int32_t y, 251 int32_t y,
239 JBig2ComposeOp op) { 252 JBig2ComposeOp op) {
240 int32_t xs0 = 0, ys0 = 0, xs1 = 0, ys1 = 0, xd0 = 0, yd0 = 0, xd1 = 0, 253 int32_t xs0 = 0, ys0 = 0, xs1 = 0, ys1 = 0, xd0 = 0, yd0 = 0, xd1 = 0,
241 yd1 = 0, xx = 0, yy = 0, w = 0, h = 0, middleDwords = 0, lineLeft = 0; 254 yd1 = 0, xx = 0, yy = 0, w = 0, h = 0, middleDwords = 0, lineLeft = 0;
242 255
243 uint32_t s1 = 0, d1 = 0, d2 = 0, shift = 0, shift1 = 0, shift2 = 0, tmp = 0, 256 uint32_t s1 = 0, d1 = 0, d2 = 0, shift = 0, shift1 = 0, shift2 = 0, tmp = 0,
244 tmp1 = 0, tmp2 = 0, maskL = 0, maskR = 0, maskM = 0; 257 tmp1 = 0, tmp2 = 0, maskL = 0, maskR = 0, maskM = 0;
245 258
(...skipping 828 matching lines...) Expand 10 before | Expand all | Expand 10 after
1074 dp[2] = (uint8_t)(tmp >> 8); 1087 dp[2] = (uint8_t)(tmp >> 8);
1075 dp[3] = (uint8_t)tmp; 1088 dp[3] = (uint8_t)tmp;
1076 } 1089 }
1077 lineSrc += m_nStride; 1090 lineSrc += m_nStride;
1078 lineDst += pDst->m_nStride; 1091 lineDst += pDst->m_nStride;
1079 } 1092 }
1080 } 1093 }
1081 } 1094 }
1082 return 1; 1095 return 1;
1083 } 1096 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698