Fix integer overflow after recent change
https://pdfium-review.googlesource.com/c/pdfium/+/134090 changed this
code to used signed integers. But signed integer overflow isn't
defined.
Switch to int64_t. THe products are int32_t * uint16_t, and we add
two of those and one int32_t. This easily fits into an int64_t.
The first loop already naturally filters out very big and small
x and y values.
The second does too as long as we let CJBig2_Image::Compose*()
take int64_ts, so switch to that.
No intended behavior change, except for fuzzer (and fuzzer-like)
inputs.
Bug: 432691328
Change-Id: I22ee3bb5306409eb9a965f254d534a9dca9caa39
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/134470
Commit-Queue: Nico Weber <thakis@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Nico Weber <thakis@google.com>
diff --git a/core/fxcodec/jbig2/JBig2_HtrdProc.cpp b/core/fxcodec/jbig2/JBig2_HtrdProc.cpp
index 9f764ac..6f9e796 100644
--- a/core/fxcodec/jbig2/JBig2_HtrdProc.cpp
+++ b/core/fxcodec/jbig2/JBig2_HtrdProc.cpp
@@ -28,10 +28,12 @@
for (uint32_t ng = 0; ng < HGW; ++ng) {
// The `>> 8` is an arithmetic shift per spec. Cast mg, ng to int,
// else implicit conversions would evaluate it as unsigned shift.
- int32_t mg_int = static_cast<int32_t>(mg);
- int32_t ng_int = static_cast<int32_t>(ng);
- int32_t x = (HGX + mg_int * HRY + ng_int * HRX) >> 8;
- int32_t y = (HGY + mg_int * HRX - ng_int * HRY) >> 8;
+ // HGX / HGY are 32 bit, HRX / HRY 16, mg / ng 32.
+ // The result after >> 8 fits in about 42 bit; int64_t suffices.
+ auto mg_int = static_cast<int64_t>(mg);
+ auto ng_int = static_cast<int64_t>(ng);
+ int64_t x = (HGX + mg_int * HRY + ng_int * HRX) >> 8;
+ int64_t y = (HGY + mg_int * HRX - ng_int * HRY) >> 8;
if ((x + HPW <= 0) | (x >= static_cast<int32_t>(HBW)) | (y + HPH <= 0) |
(y >= static_cast<int32_t>(HBH))) {
@@ -147,11 +149,13 @@
uint32_t pat_index = std::min(gsval, HNUMPATS - 1);
// The `>> 8` is an arithmetic shift per spec. Cast mg, ng to int,
// else implicit conversions would evaluate it as unsigned shift.
- int32_t mg_int = static_cast<int32_t>(mg);
- int32_t ng_int = static_cast<int32_t>(ng);
- int32_t out_x = (HGX + mg_int * HRY + ng_int * HRX) >> 8;
- int32_t out_y = (HGY + mg_int * HRX - ng_int * HRY) >> 8;
- (*HPATS)[pat_index]->ComposeTo(HTREG.get(), out_x, out_y, HCOMBOP);
+ // HGX / HGY are 32 bit, HRX / HRY 16, mg / ng 32.
+ // The result after >> 8 fits in about 42 bit; int64_t suffices.
+ auto mg_int = static_cast<int64_t>(mg);
+ auto ng_int = static_cast<int64_t>(ng);
+ int64_t x = (HGX + mg_int * HRY + ng_int * HRX) >> 8;
+ int64_t y = (HGY + mg_int * HRX - ng_int * HRY) >> 8;
+ (*HPATS)[pat_index]->ComposeTo(HTREG.get(), x, y, HCOMBOP);
}
}
return HTREG;
diff --git a/core/fxcodec/jbig2/JBig2_Image.cpp b/core/fxcodec/jbig2/JBig2_Image.cpp
index 9883f9d..d1c2e4a 100644
--- a/core/fxcodec/jbig2/JBig2_Image.cpp
+++ b/core/fxcodec/jbig2/JBig2_Image.cpp
@@ -176,30 +176,30 @@
}
bool CJBig2_Image::ComposeTo(CJBig2_Image* pDst,
- int32_t x,
- int32_t y,
+ int64_t x,
+ int64_t y,
JBig2ComposeOp op) {
return data_ &&
ComposeToInternal(pDst, x, y, op, FX_RECT(0, 0, width_, height_));
}
bool CJBig2_Image::ComposeToWithRect(CJBig2_Image* pDst,
- int32_t x,
- int32_t y,
+ int64_t x,
+ int64_t y,
const FX_RECT& rtSrc,
JBig2ComposeOp op) {
return data_ && ComposeToInternal(pDst, x, y, op, rtSrc);
}
-bool CJBig2_Image::ComposeFrom(int32_t x,
- int32_t y,
+bool CJBig2_Image::ComposeFrom(int64_t x,
+ int64_t y,
CJBig2_Image* pSrc,
JBig2ComposeOp op) {
return data_ && pSrc->ComposeTo(this, x, y, op);
}
-bool CJBig2_Image::ComposeFromWithRect(int32_t x,
- int32_t y,
+bool CJBig2_Image::ComposeFromWithRect(int64_t x,
+ int64_t y,
CJBig2_Image* pSrc,
const FX_RECT& rtSrc,
JBig2ComposeOp op) {
@@ -294,16 +294,18 @@
}
bool CJBig2_Image::ComposeToInternal(CJBig2_Image* pDst,
- int32_t x,
- int32_t y,
+ int64_t x_in,
+ int64_t y_in,
JBig2ComposeOp op,
const FX_RECT& rtSrc) {
DCHECK(data_);
// TODO(weili): Check whether the range check is correct. Should x>=1048576?
- if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) {
+ if (x_in < -1048576 || x_in > 1048576 || y_in < -1048576 || y_in > 1048576) {
return false;
}
+ int32_t x = static_cast<int32_t>(x_in);
+ int32_t y = static_cast<int32_t>(y_in);
int32_t sw = rtSrc.Width();
int32_t sh = rtSrc.Height();
diff --git a/core/fxcodec/jbig2/JBig2_Image.h b/core/fxcodec/jbig2/JBig2_Image.h
index 55d7e3e..7e72e9e 100644
--- a/core/fxcodec/jbig2/JBig2_Image.h
+++ b/core/fxcodec/jbig2/JBig2_Image.h
@@ -62,9 +62,9 @@
void CopyLine(int32_t hTo, int32_t hFrom);
void Fill(bool v);
- bool ComposeFrom(int32_t x, int32_t y, CJBig2_Image* pSrc, JBig2ComposeOp op);
- bool ComposeFromWithRect(int32_t x,
- int32_t y,
+ bool ComposeFrom(int64_t x, int64_t y, CJBig2_Image* pSrc, JBig2ComposeOp op);
+ bool ComposeFromWithRect(int64_t x,
+ int64_t y,
CJBig2_Image* pSrc,
const FX_RECT& rtSrc,
JBig2ComposeOp op);
@@ -75,10 +75,10 @@
int32_t h);
void Expand(int32_t h, bool v);
- bool ComposeTo(CJBig2_Image* pDst, int32_t x, int32_t y, JBig2ComposeOp op);
+ bool ComposeTo(CJBig2_Image* pDst, int64_t x, int64_t y, JBig2ComposeOp op);
bool ComposeToWithRect(CJBig2_Image* pDst,
- int32_t x,
- int32_t y,
+ int64_t x,
+ int64_t y,
const FX_RECT& rtSrc,
JBig2ComposeOp op);
@@ -94,8 +94,8 @@
int32_t h,
CJBig2_Image* pImage);
bool ComposeToInternal(CJBig2_Image* pDst,
- int32_t x,
- int32_t y,
+ int64_t x_in,
+ int64_t y_in,
JBig2ComposeOp op,
const FX_RECT& rtSrc);