Mark unsafe buffer regions in CPDF_DIB and CPDF_TransferFuncDIB.
-- Introduce INCR_ON_APPLE() macro to avoid #ifdef inside an expansion
of the UNSAFE_BUFFERS() macro. The MSVC build breaks if such an
#ifdef occurs.
Bug: 42271175
Change-Id: I100bd8c7ef2c9e8a1d6a68a9b719906842adf7b6
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/119679
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fpdfapi/page/cpdf_dib.cpp b/core/fpdfapi/page/cpdf_dib.cpp
index a6caa68..782a377 100644
--- a/core/fpdfapi/page/cpdf_dib.cpp
+++ b/core/fpdfapi/page/cpdf_dib.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/page/cpdf_dib.h"
#include <stdint.h>
@@ -40,6 +35,7 @@
#include "core/fxcodec/scanlinedecoder.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
+#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_safe_types.h"
@@ -57,18 +53,20 @@
unsigned int GetBits8(const uint8_t* pData, uint64_t bitpos, size_t nbits) {
DCHECK(nbits == 1 || nbits == 2 || nbits == 4 || nbits == 8 || nbits == 16);
DCHECK_EQ((bitpos & (nbits - 1)), 0u);
- unsigned int byte = pData[bitpos / 8];
- if (nbits == 8)
- return byte;
-
- if (nbits == 16)
- return byte * 256 + pData[bitpos / 8 + 1];
-
- return (byte >> (8 - nbits - (bitpos % 8))) & ((1 << nbits) - 1);
+ UNSAFE_TODO({
+ unsigned int byte = pData[bitpos / 8];
+ if (nbits == 8) {
+ return byte;
+ }
+ if (nbits == 16) {
+ return byte * 256 + pData[bitpos / 8 + 1];
+ }
+ return (byte >> (8 - nbits - (bitpos % 8))) & ((1 << nbits) - 1);
+ });
}
bool GetBitValue(const uint8_t* pSrc, uint32_t pos) {
- return pSrc[pos / 8] & (1 << (7 - pos % 8));
+ return UNSAFE_TODO(pSrc[pos / 8] & (1 << (7 - pos % 8)));
}
// Just to sanity check and filter out obvious bad values.
@@ -87,10 +85,13 @@
bool AreColorIndicesOutOfBounds(const uint8_t* indices,
const DIB_COMP_DATA* comp_data,
size_t count) {
- for (size_t i = 0; i < count; ++i) {
- if (IsColorIndexOutOfBounds(indices[i], comp_data[i]))
- return true;
- }
+ UNSAFE_TODO({
+ for (size_t i = 0; i < count; ++i) {
+ if (IsColorIndexOutOfBounds(indices[i], comp_data[i])) {
+ return true;
+ }
+ }
+ });
return false;
}
@@ -744,30 +745,34 @@
for (uint32_t row = 0; row < image_info.height; ++row) {
const uint8_t* src = result_bitmap->GetScanline(row).data();
uint8_t* dest = rgb_bitmap->GetWritableScanline(row).data();
- for (uint32_t col = 0; col < image_info.width; ++col) {
- uint8_t a = src[3];
- m_JpxInlineData.data.push_back(a);
- uint8_t na = 255 - a;
- uint8_t b = (src[0] * a + 255 * na) / 255;
- uint8_t g = (src[1] * a + 255 * na) / 255;
- uint8_t r = (src[2] * a + 255 * na) / 255;
- dest[0] = b;
- dest[1] = g;
- dest[2] = r;
- src += 4;
- dest += 3;
- }
+ UNSAFE_TODO({
+ for (uint32_t col = 0; col < image_info.width; ++col) {
+ uint8_t a = src[3];
+ m_JpxInlineData.data.push_back(a);
+ uint8_t na = 255 - a;
+ uint8_t b = (src[0] * a + 255 * na) / 255;
+ uint8_t g = (src[1] * a + 255 * na) / 255;
+ uint8_t r = (src[2] * a + 255 * na) / 255;
+ dest[0] = b;
+ dest[1] = g;
+ dest[2] = r;
+ src += 4;
+ dest += 3;
+ }
+ });
}
} else {
// TODO(thestig): Is there existing code that does this already?
for (uint32_t row = 0; row < image_info.height; ++row) {
const uint8_t* src = result_bitmap->GetScanline(row).data();
uint8_t* dest = rgb_bitmap->GetWritableScanline(row).data();
- for (uint32_t col = 0; col < image_info.width; ++col) {
- FXSYS_memcpy(dest, src, 3);
- src += 4;
- dest += 3;
- }
+ UNSAFE_TODO({
+ for (uint32_t col = 0; col < image_info.width; ++col) {
+ FXSYS_memcpy(dest, src, 3);
+ src += 4;
+ dest += 3;
+ }
+ });
}
}
result_bitmap = std::move(rgb_bitmap);
@@ -777,10 +782,12 @@
int scale = 8 - m_bpc;
for (uint32_t row = 0; row < image_info.height; ++row) {
uint8_t* scanline = result_bitmap->GetWritableScanline(row).data();
- for (uint32_t col = 0; col < image_info.width; ++col) {
- *scanline = (*scanline) >> scale;
- ++scanline;
- }
+ UNSAFE_TODO({
+ for (uint32_t col = 0; col < image_info.width; ++col) {
+ *scanline = (*scanline) >> scale;
+ ++scanline;
+ }
+ });
}
}
@@ -1096,40 +1103,46 @@
const uint8_t* src_pos = src_scan.data();
switch (m_bpc) {
case 8:
- for (int column = 0; column < m_Width; column++) {
- *dest_pos++ = src_pos[2];
- *dest_pos++ = src_pos[1];
- *dest_pos++ = *src_pos;
- src_pos += 3;
- }
+ UNSAFE_TODO({
+ for (int column = 0; column < m_Width; column++) {
+ *dest_pos++ = src_pos[2];
+ *dest_pos++ = src_pos[1];
+ *dest_pos++ = *src_pos;
+ src_pos += 3;
+ }
+ });
break;
case 16:
- for (int col = 0; col < m_Width; col++) {
- *dest_pos++ = src_pos[4];
- *dest_pos++ = src_pos[2];
- *dest_pos++ = *src_pos;
- src_pos += 6;
- }
+ UNSAFE_TODO({
+ for (int col = 0; col < m_Width; col++) {
+ *dest_pos++ = src_pos[4];
+ *dest_pos++ = src_pos[2];
+ *dest_pos++ = *src_pos;
+ src_pos += 6;
+ }
+ });
break;
default:
const unsigned int max_data = (1 << m_bpc) - 1;
uint64_t src_bit_pos = 0;
size_t dest_byte_pos = 0;
- for (int column = 0; column < m_Width; column++) {
- unsigned int R = GetBits8(src_scan.data(), src_bit_pos, m_bpc);
- src_bit_pos += m_bpc;
- unsigned int G = GetBits8(src_scan.data(), src_bit_pos, m_bpc);
- src_bit_pos += m_bpc;
- unsigned int B = GetBits8(src_scan.data(), src_bit_pos, m_bpc);
- src_bit_pos += m_bpc;
- R = std::min(R, max_data);
- G = std::min(G, max_data);
- B = std::min(B, max_data);
- dest_pos[dest_byte_pos] = B * 255 / max_data;
- dest_pos[dest_byte_pos + 1] = G * 255 / max_data;
- dest_pos[dest_byte_pos + 2] = R * 255 / max_data;
- dest_byte_pos += 3;
- }
+ UNSAFE_TODO({
+ for (int column = 0; column < m_Width; column++) {
+ unsigned int R = GetBits8(src_scan.data(), src_bit_pos, m_bpc);
+ src_bit_pos += m_bpc;
+ unsigned int G = GetBits8(src_scan.data(), src_bit_pos, m_bpc);
+ src_bit_pos += m_bpc;
+ unsigned int B = GetBits8(src_scan.data(), src_bit_pos, m_bpc);
+ src_bit_pos += m_bpc;
+ R = std::min(R, max_data);
+ G = std::min(G, max_data);
+ B = std::min(B, max_data);
+ dest_pos[dest_byte_pos] = B * 255 / max_data;
+ dest_pos[dest_byte_pos + 1] = G * 255 / max_data;
+ dest_pos[dest_byte_pos + 2] = R * 255 / max_data;
+ dest_byte_pos += 3;
+ }
+ });
break;
}
return true;
@@ -1178,7 +1191,7 @@
if (m_bImageMask && m_bDefaultDecode) {
for (uint32_t i = 0; i < src_pitch_value; i++) {
// TODO(tsepez): Bounds check if cost is acceptable.
- m_LineBuf[i] = ~pSrcLine.data()[i];
+ UNSAFE_TODO(m_LineBuf[i] = ~pSrcLine.data()[i]);
}
return pdfium::make_span(m_LineBuf).first(src_pitch_value);
}
@@ -1190,9 +1203,11 @@
uint32_t reset_argb = Get1BitResetValue();
uint32_t set_argb = Get1BitSetValue();
uint32_t* dest_scan = reinterpret_cast<uint32_t*>(m_MaskBuf.data());
- for (int col = 0; col < m_Width; col++, dest_scan++) {
- *dest_scan = GetBitValue(pSrcLine.data(), col) ? set_argb : reset_argb;
- }
+ UNSAFE_TODO({
+ for (int col = 0; col < m_Width; col++, dest_scan++) {
+ *dest_scan = GetBitValue(pSrcLine.data(), col) ? set_argb : reset_argb;
+ }
+ });
return pdfium::make_span(m_MaskBuf).first(m_Width * sizeof(uint32_t));
}
if (m_bpc * m_nComponents <= 8) {
@@ -1219,35 +1234,40 @@
uint8_t* pDestPixel = m_MaskBuf.data();
const uint8_t* pSrcPixel = m_LineBuf.data();
pdfium::span<const uint32_t> palette = GetPaletteSpan();
- if (HasPalette()) {
- for (int col = 0; col < m_Width; col++) {
- uint8_t index = *pSrcPixel++;
- *pDestPixel++ = FXARGB_B(palette[index]);
- *pDestPixel++ = FXARGB_G(palette[index]);
- *pDestPixel++ = FXARGB_R(palette[index]);
- *pDestPixel++ =
- IsColorIndexOutOfBounds(index, m_CompData[0]) ? 0xFF : 0;
+ UNSAFE_TODO({
+ if (HasPalette()) {
+ for (int col = 0; col < m_Width; col++) {
+ uint8_t index = *pSrcPixel++;
+ *pDestPixel++ = FXARGB_B(palette[index]);
+ *pDestPixel++ = FXARGB_G(palette[index]);
+ *pDestPixel++ = FXARGB_R(palette[index]);
+ *pDestPixel++ =
+ IsColorIndexOutOfBounds(index, m_CompData[0]) ? 0xFF : 0;
+ }
+ } else {
+ for (int col = 0; col < m_Width; col++) {
+ uint8_t index = *pSrcPixel++;
+ *pDestPixel++ = index;
+ *pDestPixel++ = index;
+ *pDestPixel++ = index;
+ *pDestPixel++ =
+ IsColorIndexOutOfBounds(index, m_CompData[0]) ? 0xFF : 0;
+ }
}
- } else {
- for (int col = 0; col < m_Width; col++) {
- uint8_t index = *pSrcPixel++;
- *pDestPixel++ = index;
- *pDestPixel++ = index;
- *pDestPixel++ = index;
- *pDestPixel++ =
- IsColorIndexOutOfBounds(index, m_CompData[0]) ? 0xFF : 0;
- }
- }
+ });
return pdfium::make_span(m_MaskBuf).first(4 * m_Width);
}
if (m_bColorKey) {
if (m_nComponents == 3 && m_bpc == 8) {
- uint8_t* alpha_channel = m_MaskBuf.data() + 3;
- for (int col = 0; col < m_Width; col++) {
- const uint8_t* pPixel = pSrcLine.data() + col * 3;
- alpha_channel[col * 4] =
- AreColorIndicesOutOfBounds(pPixel, m_CompData.data(), 3) ? 0xFF : 0;
- }
+ UNSAFE_TODO({
+ uint8_t* alpha_channel = m_MaskBuf.data() + 3;
+ for (int col = 0; col < m_Width; col++) {
+ const uint8_t* pPixel = pSrcLine.data() + col * 3;
+ alpha_channel[col * 4] =
+ AreColorIndicesOutOfBounds(pPixel, m_CompData.data(), 3) ? 0xFF
+ : 0;
+ }
+ });
} else {
fxcrt::spanset(pdfium::make_span(m_MaskBuf), 0xFF);
}
@@ -1263,12 +1283,14 @@
// TODO(tsepez): Bounds check if cost is acceptable.
const uint8_t* pSrcPixel = pSrcLine.data();
uint8_t* pDestPixel = m_MaskBuf.data();
- for (int col = 0; col < m_Width; col++) {
- *pDestPixel++ = *pSrcPixel++;
- *pDestPixel++ = *pSrcPixel++;
- *pDestPixel++ = *pSrcPixel++;
- pDestPixel++;
- }
+ UNSAFE_TODO({
+ for (int col = 0; col < m_Width; col++) {
+ *pDestPixel++ = *pSrcPixel++;
+ *pDestPixel++ = *pSrcPixel++;
+ *pDestPixel++ = *pSrcPixel++;
+ pDestPixel++;
+ }
+ });
return pdfium::make_span(m_MaskBuf).first(4 * m_Width);
}
diff --git a/core/fpdfapi/page/cpdf_transferfuncdib.cpp b/core/fpdfapi/page/cpdf_transferfuncdib.cpp
index cfc168a..7d21975 100644
--- a/core/fpdfapi/page/cpdf_transferfuncdib.cpp
+++ b/core/fpdfapi/page/cpdf_transferfuncdib.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/page/cpdf_transferfuncdib.h"
#include <utility>
@@ -17,8 +12,15 @@
#include "core/fpdfapi/page/cpdf_transferfunc.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fxcrt/check.h"
+#include "core/fxcrt/compiler_specific.h"
#include "core/fxge/calculate_pitch.h"
+#if BUILDFLAG(IS_APPLE)
+#define INCR_ON_APPLE(x) ++x
+#else
+#define INCR_ON_APPLE(x)
+#endif
+
CPDF_TransferFuncDIB::CPDF_TransferFuncDIB(
RetainPtr<CFX_DIBBase> pSrc,
RetainPtr<CPDF_TransferFunc> pTransferFunc)
@@ -60,72 +62,78 @@
int g1 = m_RampG[255];
int b1 = m_RampB[255];
int index = 0;
- for (int i = 0; i < m_Width; i++) {
- if (src_buf[i / 8] & (1 << (7 - i % 8))) {
- m_Scanline[index++] = b1;
- m_Scanline[index++] = g1;
- m_Scanline[index++] = r1;
- } else {
- m_Scanline[index++] = b0;
- m_Scanline[index++] = g0;
- m_Scanline[index++] = r0;
+ UNSAFE_TODO({
+ for (int i = 0; i < m_Width; i++) {
+ if (src_buf[i / 8] & (1 << (7 - i % 8))) {
+ m_Scanline[index++] = b1;
+ m_Scanline[index++] = g1;
+ m_Scanline[index++] = r1;
+ } else {
+ m_Scanline[index++] = b0;
+ m_Scanline[index++] = g0;
+ m_Scanline[index++] = r0;
+ }
+ INCR_ON_APPLE(index);
}
-#if BUILDFLAG(IS_APPLE)
- index++;
-#endif
- }
+ });
break;
}
case FXDIB_Format::k1bppMask: {
int m0 = m_RampR[0];
int m1 = m_RampR[255];
int index = 0;
- for (int i = 0; i < m_Width; i++) {
- if (src_buf[i / 8] & (1 << (7 - i % 8)))
- m_Scanline[index++] = m1;
- else
- m_Scanline[index++] = m0;
- }
+ UNSAFE_TODO({
+ for (int i = 0; i < m_Width; i++) {
+ if (src_buf[i / 8] & (1 << (7 - i % 8))) {
+ m_Scanline[index++] = m1;
+ } else {
+ m_Scanline[index++] = m0;
+ }
+ }
+ });
break;
}
case FXDIB_Format::k8bppRgb: {
pdfium::span<const uint32_t> src_palette = m_pSrc->GetPaletteSpan();
int index = 0;
- for (int i = 0; i < m_Width; i++) {
- if (m_pSrc->HasPalette()) {
- FX_ARGB src_argb = src_palette[*src_buf];
- m_Scanline[index++] = m_RampB[FXARGB_R(src_argb)];
- m_Scanline[index++] = m_RampG[FXARGB_G(src_argb)];
- m_Scanline[index++] = m_RampR[FXARGB_B(src_argb)];
- } else {
- uint32_t src_byte = *src_buf;
- m_Scanline[index++] = m_RampB[src_byte];
- m_Scanline[index++] = m_RampG[src_byte];
- m_Scanline[index++] = m_RampR[src_byte];
+ UNSAFE_TODO({
+ for (int i = 0; i < m_Width; i++) {
+ if (m_pSrc->HasPalette()) {
+ FX_ARGB src_argb = src_palette[*src_buf];
+ m_Scanline[index++] = m_RampB[FXARGB_R(src_argb)];
+ m_Scanline[index++] = m_RampG[FXARGB_G(src_argb)];
+ m_Scanline[index++] = m_RampR[FXARGB_B(src_argb)];
+ } else {
+ uint32_t src_byte = *src_buf;
+ m_Scanline[index++] = m_RampB[src_byte];
+ m_Scanline[index++] = m_RampG[src_byte];
+ m_Scanline[index++] = m_RampR[src_byte];
+ }
+ src_buf++;
+ INCR_ON_APPLE(index);
}
- src_buf++;
-#if BUILDFLAG(IS_APPLE)
- index++;
-#endif
- }
+ });
break;
}
case FXDIB_Format::k8bppMask: {
int index = 0;
- for (int i = 0; i < m_Width; i++)
- m_Scanline[index++] = m_RampR[*(src_buf++)];
+ UNSAFE_TODO({
+ for (int i = 0; i < m_Width; i++) {
+ m_Scanline[index++] = m_RampR[*(src_buf++)];
+ }
+ });
break;
}
case FXDIB_Format::kRgb: {
int index = 0;
- for (int i = 0; i < m_Width; i++) {
- m_Scanline[index++] = m_RampB[*(src_buf++)];
- m_Scanline[index++] = m_RampG[*(src_buf++)];
- m_Scanline[index++] = m_RampR[*(src_buf++)];
-#if BUILDFLAG(IS_APPLE)
- index++;
-#endif
- }
+ UNSAFE_TODO({
+ for (int i = 0; i < m_Width; i++) {
+ m_Scanline[index++] = m_RampB[*(src_buf++)];
+ m_Scanline[index++] = m_RampG[*(src_buf++)];
+ m_Scanline[index++] = m_RampR[*(src_buf++)];
+ INCR_ON_APPLE(index);
+ }
+ });
break;
}
case FXDIB_Format::kRgb32:
@@ -133,19 +141,19 @@
[[fallthrough]];
case FXDIB_Format::kArgb: {
int index = 0;
- for (int i = 0; i < m_Width; i++) {
- m_Scanline[index++] = m_RampB[*(src_buf++)];
- m_Scanline[index++] = m_RampG[*(src_buf++)];
- m_Scanline[index++] = m_RampR[*(src_buf++)];
- if (!bSkip) {
- m_Scanline[index++] = *src_buf;
-#if BUILDFLAG(IS_APPLE)
- } else {
- index++;
-#endif
+ UNSAFE_TODO({
+ for (int i = 0; i < m_Width; i++) {
+ m_Scanline[index++] = m_RampB[*(src_buf++)];
+ m_Scanline[index++] = m_RampG[*(src_buf++)];
+ m_Scanline[index++] = m_RampR[*(src_buf++)];
+ if (!bSkip) {
+ m_Scanline[index++] = *src_buf;
+ } else {
+ INCR_ON_APPLE(index);
+ }
+ src_buf++;
}
- src_buf++;
- }
+ });
break;
}
default: