diff options
author | Nicolas Pena <npm@chromium.org> | 2017-05-24 13:40:46 -0400 |
---|---|---|
committer | Chromium commit bot <commit-bot@chromium.org> | 2017-05-24 17:53:20 +0000 |
commit | a38f7989beacdf0a73441e4096d9ce7a196b10d3 (patch) | |
tree | 1d8c7fb6300ac5e2a6d34696aed7f0b7f6f7fa0d /core/fpdfapi/render | |
parent | e86d2f1acbd1e1d1ddae1a105b7c87f17b643f62 (diff) | |
download | pdfium-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>
Diffstat (limited to 'core/fpdfapi/render')
-rw-r--r-- | core/fpdfapi/render/cpdf_renderstatus.cpp | 50 |
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]); |