From a38f7989beacdf0a73441e4096d9ce7a196b10d3 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Wed, 24 May 2017 13:40:46 -0400 Subject: Use CheckedNumeric in BiInterpolImpl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: dsinclair --- core/fpdfapi/render/cpdf_renderstatus.cpp | 50 +++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'core/fpdfapi') 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 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]); -- cgit v1.2.3