Fix unsafe buffer usage in CPDF_RenderShading
Convert to array<> and span<> as needed.
Change-Id: I85b008df9d67a4a5b1bd8f1ccf7f6043b8fd174b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/119850
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/render/cpdf_rendershading.cpp b/core/fpdfapi/render/cpdf_rendershading.cpp
index 79f4966..325cee1 100644
--- a/core/fpdfapi/render/cpdf_rendershading.cpp
+++ b/core/fpdfapi/render/cpdf_rendershading.cpp
@@ -4,11 +4,6 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-#if defined(UNSAFE_BUFFERS_BUILD)
-// TODO(crbug.com/pdfium/2154): resolve buffer safety issues.
-#pragma allow_unsafe_buffers
-#endif
-
#include "core/fpdfapi/render/cpdf_rendershading.h"
#include <math.h>
@@ -31,6 +26,7 @@
#include "core/fpdfapi/render/cpdf_renderoptions.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
+#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/numerics/clamped_math.h"
@@ -139,28 +135,30 @@
CFX_Matrix matrix = mtObject2Bitmap.GetInverse();
for (int row = 0; row < height; row++) {
- uint32_t* dib_buf =
+ auto dest_buf =
fxcrt::reinterpret_span<uint32_t>(pBitmap->GetWritableScanline(row))
- .data();
- for (int column = 0; column < width; column++) {
- CFX_PointF pos = matrix.Transform(
- CFX_PointF(static_cast<float>(column), static_cast<float>(row)));
+ .first(width);
+ size_t column_counter = 0;
+ for (auto& pix : dest_buf) {
+ const float column = static_cast<float>(column_counter++);
+ const CFX_PointF pos =
+ matrix.Transform(CFX_PointF(column, static_cast<float>(row)));
float scale =
(((pos.x - start_x) * x_span) + ((pos.y - start_y) * y_span)) /
axis_len_square;
int index = static_cast<int32_t>(scale * (kShadingSteps - 1));
if (index < 0) {
- if (!bStartExtend)
+ if (!bStartExtend) {
continue;
-
+ }
index = 0;
} else if (index >= kShadingSteps) {
- if (!bEndExtend)
+ if (!bEndExtend) {
continue;
-
+ }
index = kShadingSteps - 1;
}
- dib_buf[column] = shading_steps[index];
+ pix = shading_steps[index];
}
}
}
@@ -213,12 +211,14 @@
CFX_Matrix matrix = mtObject2Bitmap.GetInverse();
for (int row = 0; row < height; row++) {
- uint32_t* dib_buf =
+ auto dest_buf =
fxcrt::reinterpret_span<uint32_t>(pBitmap->GetWritableScanline(row))
- .data();
- for (int column = 0; column < width; column++) {
- CFX_PointF pos = matrix.Transform(
- CFX_PointF(static_cast<float>(column), static_cast<float>(row)));
+ .first(width);
+ size_t column_counter = 0;
+ for (auto& pix : dest_buf) {
+ const float column = static_cast<float>(column_counter++);
+ const CFX_PointF pos =
+ matrix.Transform(CFX_PointF(column, static_cast<float>(row)));
float pos_dx = pos.x - start_x;
float pos_dy = pos.y - start_y;
float b = -2 * (pos_dx * dx + pos_dy * dy + start_r * dr);
@@ -230,34 +230,36 @@
s = -c / b;
} else {
float b2_4ac = (b * b) - 4 * (a * c);
- if (b2_4ac < 0)
+ if (b2_4ac < 0) {
continue;
-
+ }
float root = sqrt(b2_4ac);
float s1 = (-b - root) / (2 * a);
float s2 = (-b + root) / (2 * a);
if (a <= 0)
std::swap(s1, s2);
- if (bDecreasing)
+ if (bDecreasing) {
s = (s1 >= 0 || bStartExtend) ? s1 : s2;
- else
+ } else {
s = (s2 <= 1.0f || bEndExtend) ? s2 : s1;
-
- if (start_r + s * dr < 0)
+ }
+ if (start_r + s * dr < 0) {
continue;
+ }
}
-
int index = static_cast<int32_t>(s * (kShadingSteps - 1));
if (index < 0) {
- if (!bStartExtend)
+ if (!bStartExtend) {
continue;
+ }
index = 0;
} else if (index >= kShadingSteps) {
- if (!bEndExtend)
+ if (!bEndExtend) {
continue;
+ }
index = kShadingSteps - 1;
}
- dib_buf[column] = shading_steps[index];
+ pix = shading_steps[index];
}
}
}
@@ -295,9 +297,8 @@
CHECK_GE(total_results, pCS->ComponentCount());
std::vector<float> result_array(total_results);
for (int row = 0; row < height; ++row) {
- uint32_t* dib_buf =
- fxcrt::reinterpret_span<uint32_t>(pBitmap->GetWritableScanline(row))
- .data();
+ auto dib_buf =
+ fxcrt::reinterpret_span<uint32_t>(pBitmap->GetWritableScanline(row));
for (int column = 0; column < width; column++) {
CFX_PointF pos = matrix.Transform(
CFX_PointF(static_cast<float>(column), static_cast<float>(row)));
@@ -343,7 +344,7 @@
void DrawGouraud(const RetainPtr<CFX_DIBitmap>& pBitmap,
int alpha,
- CPDF_MeshVertex triangle[3]) {
+ pdfium::span<CPDF_MeshVertex, 3> triangle) {
float min_y = triangle[0].position.y;
float max_y = triangle[0].position.y;
for (int i = 1; i < 3; i++) {
@@ -360,10 +361,10 @@
for (int y = min_yi; y <= max_yi; y++) {
int nIntersects = 0;
- float inter_x[3];
- float r[3];
- float g[3];
- float b[3];
+ std::array<float, 3> inter_x;
+ std::array<float, 3> r;
+ std::array<float, 3> g;
+ std::array<float, 3> b;
for (int i = 0; i < 3; i++) {
const CPDF_MeshVertex& vertex1 = triangle[i];
const CPDF_MeshVertex& vertex2 = triangle[(i + 1) % 3];
@@ -416,13 +417,13 @@
pBitmap->GetWritableScanline(y).subspan(start_x * 4);
for (int x = start_x; x < end_x; x++) {
- uint8_t* dib_buf = dib_span.data();
r_result += r_unit;
g_result += g_unit;
b_result += b_unit;
- FXARGB_SetDIB(dib_buf, ArgbEncode(alpha, static_cast<int>(r_result * 255),
- static_cast<int>(g_result * 255),
- static_cast<int>(b_result * 255)));
+ UNSAFE_TODO(FXARGB_SetDIB(
+ dib_span.data(), ArgbEncode(alpha, static_cast<int>(r_result * 255),
+ static_cast<int>(g_result * 255),
+ static_cast<int>(b_result * 255))));
dib_span = dib_span.subspan(4);
}
}
@@ -442,7 +443,7 @@
if (!stream.Load())
return;
- CPDF_MeshVertex triangle[3];
+ std::array<CPDF_MeshVertex, 3> triangle;
while (!stream.IsEOF()) {
CPDF_MeshVertex vertex;
uint32_t flag;
@@ -485,7 +486,7 @@
if (!stream.Load())
return;
- std::vector<CPDF_MeshVertex> vertices[2];
+ std::array<std::vector<CPDF_MeshVertex>, 2> vertices;
vertices[0] = stream.ReadVertexRow(mtObject2Bitmap, row_verts);
if (vertices[0].empty())
return;
@@ -546,7 +547,7 @@
return result;
}
- void GetPoints(float p[4]) const {
+ void GetPoints(pdfium::span<float, 4> p) const {
p[0] = d;
p[1] = c / 3 + p[0];
p[2] = b / 3 - p[0] + 2 * p[1];
@@ -601,8 +602,8 @@
void GetPoints(pdfium::span<CFX_Path::Point> path_points) const {
constexpr size_t kPointsCount = 4;
- float points_x[kPointsCount];
- float points_y[kPointsCount];
+ std::array<float, kPointsCount> points_x;
+ std::array<float, kPointsCount> points_y;
x.GetPoints(points_x);
y.GetPoints(points_y);
for (size_t i = 0; i < kPointsCount; ++i)
@@ -611,8 +612,8 @@
void GetPointsReverse(pdfium::span<CFX_Path::Point> path_points) const {
constexpr size_t kPointsCount = 4;
- float points_x[kPointsCount];
- float points_y[kPointsCount];
+ std::array<float, kPointsCount> points_x;
+ std::array<float, kPointsCount> points_y;
x.GetPoints(points_x);
y.GetPoints(points_y);
for (size_t i = 0; i < kPointsCount; ++i) {
@@ -657,7 +658,11 @@
CoonColor() = default;
// Returns true if successful, false if overflow detected.
- bool BiInterpol(CoonColor colors[4], int x, int y, int x_scale, int y_scale) {
+ bool BiInterpol(pdfium::span<CoonColor, 4> colors,
+ 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],
@@ -672,7 +677,7 @@
abs(comp[2] - o.comp[2])});
}
- int comp[3] = {};
+ std::array<int, 3> comp = {};
};
struct PatchDrawer {
@@ -785,7 +790,7 @@
UnownedPtr<CFX_RenderDevice> pDevice;
bool bNoPathSmooth;
int alpha;
- CoonColor patch_colors[4];
+ std::array<CoonColor, 4> patch_colors;
};
void DrawCoonPatchMeshes(
@@ -820,7 +825,7 @@
: CFX_Path::Point::Type::kBezier);
}
- CFX_PointF coords[16];
+ std::array<CFX_PointF, 16> coords;
int point_count = type == kTensorProductPatchMeshShading ? 16 : 12;
while (!stream.IsEOF()) {
if (!stream.CanReadFlag())
@@ -832,14 +837,15 @@
if (flag) {
iStartPoint = 4;
iStartColor = 2;
- CFX_PointF tempCoords[4];
+ std::array<CFX_PointF, 4> tempCoords;
for (i = 0; i < 4; i++) {
tempCoords[i] = coords[(flag * 3 + i) % 12];
}
fxcrt::spancpy(pdfium::make_span(coords), pdfium::make_span(tempCoords));
- CoonColor tempColors[2] = {
- tempColors[0] = patch.patch_colors[flag],
- tempColors[1] = patch.patch_colors[(flag + 1) % 4]};
+ std::array<CoonColor, 2> tempColors = {{
+ patch.patch_colors[flag],
+ patch.patch_colors[(flag + 1) % 4],
+ }};
fxcrt::spancpy(pdfium::make_span(patch.patch_colors),
pdfium::make_span(tempColors));
}