summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Pena <npm@chromium.org>2017-05-24 13:40:46 -0400
committerChromium commit bot <commit-bot@chromium.org>2017-05-24 17:53:20 +0000
commita38f7989beacdf0a73441e4096d9ce7a196b10d3 (patch)
tree1d8c7fb6300ac5e2a6d34696aed7f0b7f6f7fa0d
parente86d2f1acbd1e1d1ddae1a105b7c87f17b643f62 (diff)
downloadpdfium-a38f7989beacdf0a73441e4096d9ce7a196b10d3.tar.xz
Use CheckedNumeric in BiInterpolImpl
This CL splits up BiInterpolImpl into the three interpolations its made of. In the interpolation, safe math is used, and a boolean keeps track of whether an overflow has occurred. If it does, we consider the patch to be invalid and immediately terminate the Draw method. Bug: chromium:724885 Change-Id: I4944ee1d821d8dd46c04e6b145eabe19d2ad8a5a Reviewed-on: https://pdfium-review.googlesource.com/5851 Commit-Queue: Nicolás Peña <npm@chromium.org> Reviewed-by: dsinclair <dsinclair@chromium.org>
-rw-r--r--core/fpdfapi/render/cpdf_renderstatus.cpp50
1 files changed, 37 insertions, 13 deletions
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index 9f4bda1409..9170ae9daf 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -673,6 +673,17 @@ struct Coon_Bezier {
float Distance() { return x.Distance() + y.Distance(); }
};
+int Interpolate(int p1, int p2, int delta1, int delta2, bool* overflow) {
+ pdfium::base::CheckedNumeric<int> p = p2;
+ p -= p1;
+ p *= delta1;
+ p /= delta2;
+ p += p1;
+ if (!p.IsValid())
+ *overflow = true;
+ return p.ValueOrDefault(0);
+}
+
int BiInterpolImpl(int c0,
int c1,
int c2,
@@ -680,26 +691,30 @@ int BiInterpolImpl(int c0,
int x,
int y,
int x_scale,
- int y_scale) {
- int x1 = c0 + (c3 - c0) * x / x_scale;
- int x2 = c1 + (c2 - c1) * x / x_scale;
- return x1 + (x2 - x1) * y / y_scale;
+ int y_scale,
+ bool* overflow) {
+ int x1 = Interpolate(c0, c3, x, x_scale, overflow);
+ int x2 = Interpolate(c1, c2, x, x_scale, overflow);
+ return Interpolate(x1, x2, y, y_scale, overflow);
}
struct Coon_Color {
Coon_Color() { memset(comp, 0, sizeof(int) * 3); }
int comp[3];
- void BiInterpol(Coon_Color colors[4],
+ // Returns true if successful, false if overflow detected.
+ bool BiInterpol(Coon_Color colors[4],
int x,
int y,
int x_scale,
int y_scale) {
+ bool overflow = false;
for (int i = 0; i < 3; i++) {
comp[i] = BiInterpolImpl(colors[0].comp[i], colors[1].comp[i],
colors[2].comp[i], colors[3].comp[i], x, y,
- x_scale, y_scale);
+ x_scale, y_scale, &overflow);
}
+ return !overflow;
}
int Distance(Coon_Color& o) {
@@ -731,14 +746,23 @@ struct CPDF_PatchDrawer {
int d_left = 0;
int d_top = 0;
int d_right = 0;
- div_colors[0].BiInterpol(patch_colors, left, bottom, x_scale, y_scale);
+ if (!div_colors[0].BiInterpol(patch_colors, left, bottom, x_scale,
+ y_scale)) {
+ return;
+ }
if (!bSmall) {
- div_colors[1].BiInterpol(patch_colors, left, bottom + 1, x_scale,
- y_scale);
- div_colors[2].BiInterpol(patch_colors, left + 1, bottom + 1, x_scale,
- y_scale);
- div_colors[3].BiInterpol(patch_colors, left + 1, bottom, x_scale,
- y_scale);
+ if (!div_colors[1].BiInterpol(patch_colors, left, bottom + 1, x_scale,
+ y_scale)) {
+ return;
+ }
+ if (!div_colors[2].BiInterpol(patch_colors, left + 1, bottom + 1, x_scale,
+ y_scale)) {
+ return;
+ }
+ if (!div_colors[3].BiInterpol(patch_colors, left + 1, bottom, x_scale,
+ y_scale)) {
+ return;
+ }
d_bottom = div_colors[3].Distance(div_colors[0]);
d_left = div_colors[1].Distance(div_colors[0]);
d_top = div_colors[1].Distance(div_colors[2]);