Mass suppress unsafe buffers in fxge drivers. Bug: 42271175 Change-Id: I419a299ef88c870563621bff96c031a3eb8819a9 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/120210 Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Thomas Sepez <tsepez@google.com> Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp index 76d8ea1..908a129 100644 --- a/core/fxge/agg/fx_agg_driver.cpp +++ b/core/fxge/agg/fx_agg_driver.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/fxge/agg/fx_agg_driver.h" #include <math.h> @@ -20,6 +15,7 @@ #include "build/build_config.h" #include "core/fxcrt/check.h" #include "core/fxcrt/check_op.h" +#include "core/fxcrt/compiler_specific.h" #include "core/fxcrt/fx_2d_size.h" #include "core/fxcrt/fx_safe_types.h" #include "core/fxcrt/notreached.h" @@ -80,58 +76,61 @@ int Bpp = pBitmap->GetBPP() / 8; int dib_argb = FXARGB_TOBGRORDERDIB(argb); pdfium::span<uint8_t> pBuffer = pBitmap->GetWritableBuffer(); - if (src_alpha == 255) { + UNSAFE_TODO({ + if (src_alpha == 255) { + for (int row = rect.top; row < rect.bottom; row++) { + uint8_t* dest_scan = + pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data(); + if (Bpp == 4) { + std::fill_n(reinterpret_cast<uint32_t*>(dest_scan), width, dib_argb); + } else { + for (int col = 0; col < width; col++) { + *dest_scan++ = src_r; + *dest_scan++ = src_g; + *dest_scan++ = src_b; + } + } + } + return; + } + bool bAlpha = pBitmap->IsAlphaFormat(); for (int row = rect.top; row < rect.bottom; row++) { uint8_t* dest_scan = pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data(); - if (Bpp == 4) { - std::fill_n(reinterpret_cast<uint32_t*>(dest_scan), width, dib_argb); - } else { + if (bAlpha) { for (int col = 0; col < width; col++) { - *dest_scan++ = src_r; - *dest_scan++ = src_g; - *dest_scan++ = src_b; + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SetRGBOrderDIB(dest_scan, argb); + dest_scan += 4; + continue; + } + uint8_t dest_alpha = + back_alpha + src_alpha - back_alpha * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); + dest_scan += 2; } + continue; } - } - return; - } - bool bAlpha = pBitmap->IsAlphaFormat(); - for (int row = rect.top; row < rect.bottom; row++) { - uint8_t* dest_scan = - pBuffer.subspan(row * pBitmap->GetPitch() + rect.left * Bpp).data(); - if (bAlpha) { for (int col = 0; col < width; col++) { - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SetRGBOrderDIB(dest_scan, argb); - dest_scan += 4; - continue; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); + dest_scan++; + if (Bpp == 4) { + dest_scan++; } - uint8_t dest_alpha = - back_alpha + src_alpha - back_alpha * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, alpha_ratio); - dest_scan += 2; } - continue; } - for (int col = 0; col < width; col++) { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_r, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_g, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, src_b, src_alpha); - dest_scan++; - if (Bpp == 4) - dest_scan++; - } - } + }); } void RgbByteOrderTransferBitmap(RetainPtr<CFX_DIBitmap> pBitmap, @@ -159,59 +158,79 @@ pdfium::span<uint8_t> dest_span = pBitmap->GetWritableBuffer() .subspan(dest_y_offset) .subspan(dest_x_offset); - if (dest_format == src_format) { - const size_t src_x_offset = Fx2DSizeOrDie(src_left, Bpp); - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_span.data(); - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data(); - if (Bpp == 4) { - for (int col = 0; col < width; col++) { - FXARGB_SetRGBOrderDIB(dest_scan, - *reinterpret_cast<const uint32_t*>(src_scan)); - dest_scan += 4; - src_scan += 4; + UNSAFE_TODO({ + if (dest_format == src_format) { + const size_t src_x_offset = Fx2DSizeOrDie(src_left, Bpp); + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = dest_span.data(); + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data(); + if (Bpp == 4) { + for (int col = 0; col < width; col++) { + FXARGB_SetRGBOrderDIB(dest_scan, + *reinterpret_cast<const uint32_t*>(src_scan)); + dest_scan += 4; + src_scan += 4; + } + } else { + for (int col = 0; col < width; col++) { + *dest_scan++ = src_scan[2]; + *dest_scan++ = src_scan[1]; + *dest_scan++ = src_scan[0]; + src_scan += 3; + } } - } else { + dest_span = dest_span.subspan(dest_pitch); + } + return; + } + + if (dest_format == FXDIB_Format::kRgb) { + DCHECK_EQ(src_format, FXDIB_Format::kRgb32); + const size_t src_x_offset = Fx2DSizeOrDie(src_left, 4); + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = dest_span.data(); + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data(); for (int col = 0; col < width; col++) { *dest_scan++ = src_scan[2]; *dest_scan++ = src_scan[1]; *dest_scan++ = src_scan[0]; - src_scan += 3; + src_scan += 4; + } + if (row < height - 1) { + // Since `dest_scan` was initialized in a way that takes + // `dest_x_offset` and `dest_y_offset` into account, it may go past + // the end of the span after processing the last row. + dest_span = dest_span.subspan(dest_pitch); } } - dest_span = dest_span.subspan(dest_pitch); + return; } - return; - } - if (dest_format == FXDIB_Format::kRgb) { - DCHECK_EQ(src_format, FXDIB_Format::kRgb32); - const size_t src_x_offset = Fx2DSizeOrDie(src_left, 4); - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_span.data(); - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data(); - for (int col = 0; col < width; col++) { - *dest_scan++ = src_scan[2]; - *dest_scan++ = src_scan[1]; - *dest_scan++ = src_scan[0]; - src_scan += 4; - } - if (row < height - 1) { - // Since `dest_scan` was initialized in a way that takes `dest_x_offset` - // and `dest_y_offset` into account, it may go past the end of the span - // after processing the last row. + DCHECK(dest_format == FXDIB_Format::kArgb || + dest_format == FXDIB_Format::kRgb32); + if (src_format == FXDIB_Format::kRgb) { + const size_t src_x_offset = Fx2DSizeOrDie(src_left, 3); + for (int row = 0; row < height; row++) { + uint8_t* dest_scan = dest_span.data(); + const uint8_t* src_scan = + pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data(); + for (int col = 0; col < width; col++) { + FXARGB_SetDIB(dest_scan, ArgbEncode(0xff, src_scan[0], src_scan[1], + src_scan[2])); + dest_scan += 4; + src_scan += 3; + } dest_span = dest_span.subspan(dest_pitch); } + return; } - return; - } - - DCHECK(dest_format == FXDIB_Format::kArgb || - dest_format == FXDIB_Format::kRgb32); - if (src_format == FXDIB_Format::kRgb) { - const size_t src_x_offset = Fx2DSizeOrDie(src_left, 3); + if (src_format != FXDIB_Format::kRgb32) { + return; + } + DCHECK_EQ(dest_format, FXDIB_Format::kArgb); + const size_t src_x_offset = Fx2DSizeOrDie(src_left, 4); for (int row = 0; row < height; row++) { uint8_t* dest_scan = dest_span.data(); const uint8_t* src_scan = @@ -219,29 +238,12 @@ for (int col = 0; col < width; col++) { FXARGB_SetDIB(dest_scan, ArgbEncode(0xff, src_scan[0], src_scan[1], src_scan[2])); + src_scan += 4; dest_scan += 4; - src_scan += 3; } dest_span = dest_span.subspan(dest_pitch); } - return; - } - if (src_format != FXDIB_Format::kRgb32) - return; - DCHECK_EQ(dest_format, FXDIB_Format::kArgb); - const size_t src_x_offset = Fx2DSizeOrDie(src_left, 4); - for (int row = 0; row < height; row++) { - uint8_t* dest_scan = dest_span.data(); - const uint8_t* src_scan = - pSrcBitmap->GetScanline(src_top + row).subspan(src_x_offset).data(); - for (int col = 0; col < width; col++) { - FXARGB_SetDIB(dest_scan, - ArgbEncode(0xff, src_scan[0], src_scan[1], src_scan[2])); - src_scan += 4; - dest_scan += 4; - } - dest_span = dest_span.subspan(dest_pitch); - } + }); } void RasterizeStroke(agg::rasterizer_scanline_aa* rasterizer, @@ -421,14 +423,15 @@ } inline int GetSrcAlpha(const uint8_t* clip_scan, int col) const { - return clip_scan ? m_Alpha * clip_scan[col] / 255 : m_Alpha; + return clip_scan ? m_Alpha * UNSAFE_TODO(clip_scan[col]) / 255 : m_Alpha; } inline int GetSourceAlpha(const uint8_t* cover_scan, const uint8_t* clip_scan, int col) const { - return clip_scan ? m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255 - : m_Alpha * cover_scan[col] / 255; + return UNSAFE_TODO(clip_scan ? m_Alpha * cover_scan[col] * clip_scan[col] / + 255 / 255 + : m_Alpha * cover_scan[col] / 255); } inline int GetColStart(int span_left, int clip_left) const { @@ -468,136 +471,139 @@ const uint8_t* clip_scan) { int col_start = GetColStart(span_left, clip_left); int col_end = GetColEnd(span_left, span_len, clip_right); - if (Bpp) { - dest_scan += col_start * Bpp; - backdrop_scan += col_start * Bpp; - } else { - dest_scan += col_start / 8; - backdrop_scan += col_start / 8; - } - if (m_bRgbByteOrder) { - if (Bpp == 4 && bDestAlpha) { - for (int col = col_start; col < col_end; col++) { - int src_alpha = GetSrcAlpha(clip_scan, col); - uint8_t dest_alpha = - backdrop_scan[3] + src_alpha - backdrop_scan[3] * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - if (m_bFullCover) { - *dest_scan++ = - FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio); - *dest_scan++ = - FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio); - *dest_scan++ = - FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio); - dest_scan++; - backdrop_scan++; - } else { - int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio); - int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio); - int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio); - backdrop_scan++; + UNSAFE_TODO({ + if (Bpp) { + dest_scan += col_start * Bpp; + backdrop_scan += col_start * Bpp; + } else { + dest_scan += col_start / 8; + backdrop_scan += col_start / 8; + } + if (m_bRgbByteOrder) { + if (Bpp == 4 && bDestAlpha) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSrcAlpha(clip_scan, col); + uint8_t dest_alpha = + backdrop_scan[3] + src_alpha - backdrop_scan[3] * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + if (m_bFullCover) { + *dest_scan++ = + FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio); + *dest_scan++ = + FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio); + *dest_scan++ = + FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio); + dest_scan++; + backdrop_scan++; + } else { + int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio); + int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio); + int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio); + backdrop_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); + dest_scan += 2; + } + } + return; + } + if (Bpp == 3 || Bpp == 4) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSrcAlpha(clip_scan, col); + int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, src_alpha); + int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha); + int b = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Blue, src_alpha); + backdrop_scan += Bpp - 2; *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); dest_scan++; *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); dest_scan++; *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); - dest_scan += 2; + dest_scan += Bpp - 2; } } return; } + if (Bpp == 4 && bDestAlpha) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSrcAlpha(clip_scan, col); + int src_alpha_covered = src_alpha * cover_scan[col] / 255; + if (src_alpha_covered == 0) { + dest_scan += 4; + continue; + } + if (cover_scan[col] == 255) { + dest_scan[3] = src_alpha_covered; + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan = m_Red; + dest_scan += 2; + continue; + } + if (dest_scan[3] == 0) { + dest_scan[3] = src_alpha_covered; + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan = m_Red; + dest_scan += 2; + continue; + } + uint8_t cover = cover_scan[col]; + dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover); + dest_scan += 2; + } + return; + } if (Bpp == 3 || Bpp == 4) { for (int col = col_start; col < col_end; col++) { int src_alpha = GetSrcAlpha(clip_scan, col); - int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, src_alpha); + if (m_bFullCover) { + *dest_scan++ = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha); + *dest_scan++ = + FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha); + dest_scan += Bpp - 2; + backdrop_scan += Bpp - 2; + continue; + } + int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha); int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha); - int b = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Blue, src_alpha); + int r = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha); backdrop_scan += Bpp - 2; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); dest_scan++; *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); dest_scan += Bpp - 2; } + return; } - return; - } - if (Bpp == 4 && bDestAlpha) { - for (int col = col_start; col < col_end; col++) { - int src_alpha = GetSrcAlpha(clip_scan, col); - int src_alpha_covered = src_alpha * cover_scan[col] / 255; - if (src_alpha_covered == 0) { - dest_scan += 4; - continue; + if (Bpp == 1) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSrcAlpha(clip_scan, col); + if (m_bFullCover) { + *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha); + continue; + } + int gray = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]); + dest_scan++; } - if (cover_scan[col] == 255) { - dest_scan[3] = src_alpha_covered; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; - } - if (dest_scan[3] == 0) { - dest_scan[3] = src_alpha_covered; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; - } - uint8_t cover = cover_scan[col]; - dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover); - dest_scan += 2; + return; } - return; - } - if (Bpp == 3 || Bpp == 4) { - for (int col = col_start; col < col_end; col++) { - int src_alpha = GetSrcAlpha(clip_scan, col); - if (m_bFullCover) { - *dest_scan++ = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha); - *dest_scan++ = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha); - dest_scan += Bpp - 2; - backdrop_scan += Bpp - 2; - continue; - } - int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha); - int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha); - int r = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha); - backdrop_scan += Bpp - 2; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); - dest_scan += Bpp - 2; - } - return; - } - if (Bpp == 1) { - for (int col = col_start; col < col_end; col++) { - int src_alpha = GetSrcAlpha(clip_scan, col); - if (m_bFullCover) { - *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha); - continue; - } - int gray = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha); - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]); - dest_scan++; - } - return; - } - CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan, - span_left); + CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, + clip_scan, span_left); + }); } void CFX_Renderer::CompositeSpan1bpp(uint8_t* dest_scan, @@ -611,7 +617,7 @@ DCHECK(!m_bRgbByteOrder); int col_start = GetColStart(span_left, clip_left); int col_end = GetColEnd(span_left, span_len, clip_right); - dest_scan += col_start / 8; + UNSAFE_TODO(dest_scan += col_start / 8); CompositeSpan1bppHelper(dest_scan, col_start, col_end, cover_scan, clip_scan, span_left); } @@ -627,17 +633,20 @@ DCHECK(!m_bRgbByteOrder); int col_start = GetColStart(span_left, clip_left); int col_end = GetColEnd(span_left, span_len, clip_right); - dest_scan += col_start; - for (int col = col_start; col < col_end; col++) { - int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); - if (src_alpha) { - if (src_alpha == 255) - *dest_scan = m_Gray; - else - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); + UNSAFE_TODO({ + dest_scan += col_start; + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *dest_scan = m_Gray; + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); + } + } + dest_scan++; } - dest_scan++; - } + }); } void CFX_Renderer::CompositeSpanARGB(uint8_t* dest_scan, @@ -650,8 +659,34 @@ const uint8_t* clip_scan) { int col_start = GetColStart(span_left, clip_left); int col_end = GetColEnd(span_left, span_len, clip_right); - dest_scan += col_start * Bpp; - if (m_bRgbByteOrder) { + UNSAFE_TODO({ + dest_scan += col_start * Bpp; + if (m_bRgbByteOrder) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = m_bFullCover + ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + *(reinterpret_cast<uint32_t*>(dest_scan)) = m_Color; + } else { + uint8_t dest_alpha = + dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha * 255 / dest_alpha; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); + dest_scan += 2; + continue; + } + } + dest_scan += 4; + } + return; + } for (int col = col_start; col < col_end; col++) { int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) : GetSourceAlpha(cover_scan, clip_scan, col); @@ -659,53 +694,30 @@ if (src_alpha == 255) { *(reinterpret_cast<uint32_t*>(dest_scan)) = m_Color; } else { + if (dest_scan[3] == 0) { + dest_scan[3] = src_alpha; + *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan = m_Red; + dest_scan += 2; + continue; + } uint8_t dest_alpha = dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; dest_scan[3] = dest_alpha; int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); dest_scan++; *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); dest_scan += 2; continue; } } - dest_scan += 4; + dest_scan += Bpp; } - return; - } - for (int col = col_start; col < col_end; col++) { - int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) - : GetSourceAlpha(cover_scan, clip_scan, col); - if (src_alpha) { - if (src_alpha == 255) { - *(reinterpret_cast<uint32_t*>(dest_scan)) = m_Color; - } else { - if (dest_scan[3] == 0) { - dest_scan[3] = src_alpha; - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan = m_Red; - dest_scan += 2; - continue; - } - uint8_t dest_alpha = - dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha * 255 / dest_alpha; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); - dest_scan += 2; - continue; - } - } - dest_scan += Bpp; - } + }); } void CFX_Renderer::CompositeSpanRGB(uint8_t* dest_scan, @@ -718,59 +730,61 @@ const uint8_t* clip_scan) { int col_start = GetColStart(span_left, clip_left); int col_end = GetColEnd(span_left, span_len, clip_right); - dest_scan += col_start * Bpp; - if (m_bRgbByteOrder) { + UNSAFE_TODO({ + dest_scan += col_start * Bpp; + if (m_bRgbByteOrder) { + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (src_alpha == 255) { + if (Bpp == 4) { + *(uint32_t*)dest_scan = m_Color; + } else if (Bpp == 3) { + *dest_scan++ = m_Red; + *dest_scan++ = m_Green; + *dest_scan++ = m_Blue; + continue; + } + } else { + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); + dest_scan++; + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); + dest_scan += Bpp - 2; + continue; + } + } + dest_scan += Bpp; + } + return; + } for (int col = col_start; col < col_end; col++) { - int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) + : GetSourceAlpha(cover_scan, clip_scan, col); if (src_alpha) { if (src_alpha == 255) { if (Bpp == 4) { *(uint32_t*)dest_scan = m_Color; } else if (Bpp == 3) { - *dest_scan++ = m_Red; - *dest_scan++ = m_Green; *dest_scan++ = m_Blue; + *dest_scan++ = m_Green; + *dest_scan++ = m_Red; continue; } } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); dest_scan++; *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); + *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); dest_scan += Bpp - 2; continue; } } dest_scan += Bpp; } - return; - } - for (int col = col_start; col < col_end; col++) { - int src_alpha = m_bFullCover ? GetSrcAlpha(clip_scan, col) - : GetSourceAlpha(cover_scan, clip_scan, col); - if (src_alpha) { - if (src_alpha == 255) { - if (Bpp == 4) { - *(uint32_t*)dest_scan = m_Color; - } else if (Bpp == 3) { - *dest_scan++ = m_Blue; - *dest_scan++ = m_Green; - *dest_scan++ = m_Red; - continue; - } - } else { - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); - dest_scan++; - *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); - dest_scan += Bpp - 2; - continue; - } - } - dest_scan += Bpp; - } + }); } CFX_Renderer::CFX_Renderer(const RetainPtr<CFX_DIBitmap>& pDevice, @@ -819,39 +833,43 @@ bool bDestAlpha = m_pDevice->IsAlphaFormat() || m_pDevice->IsMaskFormat(); unsigned num_spans = sl.num_spans(); typename Scanline::const_iterator span = sl.begin(); - while (true) { - if (span->len <= 0) - break; + UNSAFE_TODO({ + while (true) { + if (span->len <= 0) { + break; + } - int x = span->x; - uint8_t* dest_pos = nullptr; - const uint8_t* backdrop_pos = nullptr; - if (Bpp) { - backdrop_pos = backdrop_scan ? backdrop_scan + x * Bpp : nullptr; - dest_pos = dest_scan + x * Bpp; - } else { - dest_pos = dest_scan + x / 8; - backdrop_pos = backdrop_scan ? backdrop_scan + x / 8 : nullptr; - } - const uint8_t* clip_pos = nullptr; - if (m_pClipMask) { - // TODO(crbug.com/1382604): use subspan arithmetic. - clip_pos = m_pClipMask->GetBuffer().data() + - (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x - - m_ClipBox.left; - } - if (backdrop_pos) { - CompositeSpan(dest_pos, backdrop_pos, Bpp, bDestAlpha, x, span->len, - span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos); - } else { - (this->*m_CompositeSpanFunc)(dest_pos, Bpp, x, span->len, span->covers, - m_ClipBox.left, m_ClipBox.right, clip_pos); - } - if (--num_spans == 0) - break; + int x = span->x; + uint8_t* dest_pos = nullptr; + const uint8_t* backdrop_pos = nullptr; + if (Bpp) { + backdrop_pos = backdrop_scan ? backdrop_scan + x * Bpp : nullptr; + dest_pos = dest_scan + x * Bpp; + } else { + dest_pos = dest_scan + x / 8; + backdrop_pos = backdrop_scan ? backdrop_scan + x / 8 : nullptr; + } + const uint8_t* clip_pos = nullptr; + if (m_pClipMask) { + // TODO(crbug.com/1382604): use subspan arithmetic. + clip_pos = m_pClipMask->GetBuffer().data() + + (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x - + m_ClipBox.left; + } + if (backdrop_pos) { + CompositeSpan(dest_pos, backdrop_pos, Bpp, bDestAlpha, x, span->len, + span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos); + } else { + (this->*m_CompositeSpanFunc)(dest_pos, Bpp, x, span->len, span->covers, + m_ClipBox.left, m_ClipBox.right, clip_pos); + } + if (--num_spans == 0) { + break; + } - ++span; - } + ++span; + } + }); } void CFX_Renderer::CompositeSpan1bppHelper(uint8_t* dest_scan, @@ -870,16 +888,19 @@ index = (static_cast<uint8_t>(m_Color) == 0xff) ? 1 : 0; } uint8_t* dest_scan1 = dest_scan; - for (int col = col_start; col < col_end; col++) { - int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); - if (src_alpha) { - if (!index) - *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); - else - *dest_scan1 |= 1 << (7 - (col + span_left) % 8); + UNSAFE_TODO({ + for (int col = col_start; col < col_end; col++) { + int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col); + if (src_alpha) { + if (!index) { + *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); + } else { + *dest_scan1 |= 1 << (7 - (col + span_left) % 8); + } + } + dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; } - dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; - } + }); } template <class BaseRenderer> @@ -909,7 +930,7 @@ if (--num_spans == 0) break; - ++span; + UNSAFE_TODO(++span); } }
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp index ff349e4..7620c7e 100644 --- a/core/fxge/skia/fx_skia_device.cpp +++ b/core/fxge/skia/fx_skia_device.cpp
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#if defined(UNSAFE_BUFFERS_BUILD) -// TODO(crbug.com/pdfium/2154): resolve buffer safety issues. -#pragma allow_unsafe_buffers -#endif - #include "core/fxge/skia/fx_skia_device.h" #include <math.h> @@ -349,25 +344,28 @@ float colors_min[3]; float colors_max[3]; - for (int i = 0; i < 3; ++i) { - colors_min[i] = func->GetRange(i * 2); - colors_max[i] = func->GetRange(i * 2 + 1); - } - pdfium::span<const uint8_t> sample_data = func->GetSampleStream()->GetSpan(); - CFX_BitStream bitstream(sample_data); - for (uint32_t i = 0; i < sample_count; ++i) { - float float_colors[3]; - for (uint32_t j = 0; j < 3; ++j) { - float sample = static_cast<float>(bitstream.GetBits(sample_size)); - float interp = sample / (sample_count - 1); - float_colors[j] = - colors_min[j] + (colors_max[j] - colors_min[j]) * interp; + UNSAFE_TODO({ + for (int i = 0; i < 3; ++i) { + colors_min[i] = func->GetRange(i * 2); + colors_max[i] = func->GetRange(i * 2 + 1); } - colors.push_back(SkPackARGB32NoCheck(0xFF, FloatToByte(float_colors[0]), - FloatToByte(float_colors[1]), - FloatToByte(float_colors[2]))); - pos.push_back(static_cast<float>(i) / (sample_count - 1)); - } + pdfium::span<const uint8_t> sample_data = + func->GetSampleStream()->GetSpan(); + CFX_BitStream bitstream(sample_data); + for (uint32_t i = 0; i < sample_count; ++i) { + float float_colors[3]; + for (uint32_t j = 0; j < 3; ++j) { + float sample = static_cast<float>(bitstream.GetBits(sample_size)); + float interp = sample / (sample_count - 1); + float_colors[j] = + colors_min[j] + (colors_max[j] - colors_min[j]) * interp; + } + colors.push_back(SkPackARGB32NoCheck(0xFF, FloatToByte(float_colors[0]), + FloatToByte(float_colors[1]), + FloatToByte(float_colors[2]))); + pos.push_back(static_cast<float>(i) / (sample_count - 1)); + } + }); return true; } @@ -399,8 +397,9 @@ // see https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line SkScalar LineSide(const SkPoint line[2], const SkPoint& pt) { - return (line[1].fY - line[0].fY) * pt.fX - (line[1].fX - line[0].fX) * pt.fY + - line[1].fX * line[0].fY - line[1].fY * line[0].fX; + return UNSAFE_TODO((line[1].fY - line[0].fY) * pt.fX - + (line[1].fX - line[0].fX) * pt.fY + + line[1].fX * line[0].fY - line[1].fY * line[0].fX); } SkPoint IntersectSides(const SkPoint& parallelPt, @@ -430,74 +429,83 @@ SkScalar maxPerpDist = SK_ScalarMin; int minPerpPtIndex = -1; int maxPerpPtIndex = -1; - SkVector slope = pts[1] - pts[0]; - SkPoint startPerp[2] = {pts[0], {pts[0].fX + slope.fY, pts[0].fY - slope.fX}}; - SkPoint endPerp[2] = {pts[1], {pts[1].fX + slope.fY, pts[1].fY - slope.fX}}; - for (int i = 0; i < 4; ++i) { - SkScalar sDist = LineSide(startPerp, rectPts[i]); - SkScalar eDist = LineSide(endPerp, rectPts[i]); - if (sDist * eDist <= 0) // if the signs are different, - continue; // the point is inside the gradient - if (sDist < 0) { - SkScalar smaller = std::min(sDist, eDist); - if (minPerpDist > smaller) { - minPerpDist = smaller; - minPerpPtIndex = i; + UNSAFE_TODO({ + SkVector slope = pts[1] - pts[0]; + SkPoint startPerp[2] = {pts[0], + {pts[0].fX + slope.fY, pts[0].fY - slope.fX}}; + SkPoint endPerp[2] = {pts[1], {pts[1].fX + slope.fY, pts[1].fY - slope.fX}}; + for (int i = 0; i < 4; ++i) { + SkScalar sDist = LineSide(startPerp, rectPts[i]); + SkScalar eDist = LineSide(endPerp, rectPts[i]); + if (sDist * eDist <= 0) { // if the signs are different, + continue; // the point is inside the gradient } - } else { - SkScalar larger = std::max(sDist, eDist); - if (maxPerpDist < larger) { - maxPerpDist = larger; - maxPerpPtIndex = i; + if (sDist < 0) { + SkScalar smaller = std::min(sDist, eDist); + if (minPerpDist > smaller) { + minPerpDist = smaller; + minPerpPtIndex = i; + } + } else { + SkScalar larger = std::max(sDist, eDist); + if (maxPerpDist < larger) { + maxPerpDist = larger; + maxPerpPtIndex = i; + } } } - } - if (minPerpPtIndex < 0 && maxPerpPtIndex < 0) // nothing's outside - return; - - // determine if negative distances are before start or after end - SkPoint beforeStart = {pts[0].fX * 2 - pts[1].fX, pts[0].fY * 2 - pts[1].fY}; - bool beforeNeg = LineSide(startPerp, beforeStart) < 0; - - int noClipStartIndex = maxPerpPtIndex; - int noClipEndIndex = minPerpPtIndex; - if (beforeNeg) - std::swap(noClipStartIndex, noClipEndIndex); - if ((!clipStart && noClipStartIndex < 0) || - (!clipEnd && noClipEndIndex < 0)) { - return; - } - - const SkPoint& startEdgePt = clipStart ? pts[0] : rectPts[noClipStartIndex]; - const SkPoint& endEdgePt = clipEnd ? pts[1] : rectPts[noClipEndIndex]; - - // find the corners that bound the gradient - SkScalar minDist = SK_ScalarMax; - SkScalar maxDist = SK_ScalarMin; - int minBounds = -1; - int maxBounds = -1; - for (int i = 0; i < 4; ++i) { - SkScalar dist = LineSide(pts, rectPts[i]); - if (minDist > dist) { - minDist = dist; - minBounds = i; + if (minPerpPtIndex < 0 && maxPerpPtIndex < 0) { // nothing's outside + return; } - if (maxDist < dist) { - maxDist = dist; - maxBounds = i; + + // determine if negative distances are before start or after end + SkPoint beforeStart = {pts[0].fX * 2 - pts[1].fX, + pts[0].fY * 2 - pts[1].fY}; + bool beforeNeg = LineSide(startPerp, beforeStart) < 0; + + int noClipStartIndex = maxPerpPtIndex; + int noClipEndIndex = minPerpPtIndex; + if (beforeNeg) { + std::swap(noClipStartIndex, noClipEndIndex); } - } - if (minBounds < 0 || maxBounds < 0) - return; - if (minBounds == maxBounds) - return; - // construct a clip parallel to the gradient that goes through - // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the - // gradient that goes through startEdgePt, endEdgePt. - clip->moveTo(IntersectSides(rectPts[minBounds], slope, startEdgePt)); - clip->lineTo(IntersectSides(rectPts[minBounds], slope, endEdgePt)); - clip->lineTo(IntersectSides(rectPts[maxBounds], slope, endEdgePt)); - clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt)); + if ((!clipStart && noClipStartIndex < 0) || + (!clipEnd && noClipEndIndex < 0)) { + return; + } + + const SkPoint& startEdgePt = clipStart ? pts[0] : rectPts[noClipStartIndex]; + const SkPoint& endEdgePt = clipEnd ? pts[1] : rectPts[noClipEndIndex]; + + // find the corners that bound the gradient + SkScalar minDist = SK_ScalarMax; + SkScalar maxDist = SK_ScalarMin; + int minBounds = -1; + int maxBounds = -1; + for (int i = 0; i < 4; ++i) { + SkScalar dist = LineSide(pts, rectPts[i]); + if (minDist > dist) { + minDist = dist; + minBounds = i; + } + if (maxDist < dist) { + maxDist = dist; + maxBounds = i; + } + } + if (minBounds < 0 || maxBounds < 0) { + return; + } + if (minBounds == maxBounds) { + return; + } + // construct a clip parallel to the gradient that goes through + // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the + // gradient that goes through startEdgePt, endEdgePt. + clip->moveTo(IntersectSides(rectPts[minBounds], slope, startEdgePt)); + clip->lineTo(IntersectSides(rectPts[minBounds], slope, endEdgePt)); + clip->lineTo(IntersectSides(rectPts[maxBounds], slope, endEdgePt)); + clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt)); + }); } // Converts a stroking path to scanlines @@ -1313,35 +1321,37 @@ if (!skClip.isEmpty()) m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true); m_pCanvas->concat(skMatrix); - while (!stream.IsEOF()) { - uint32_t flag = stream.ReadFlag(); - size_t start_point = flag ? 4 : 0; - size_t start_color = flag ? 2 : 0; - if (flag) { - SkPoint temp_cubics[4]; - for (size_t i = 0; i < std::size(temp_cubics); ++i) { - temp_cubics[i] = cubics[(flag * 3 + i) % 12]; + UNSAFE_TODO({ + while (!stream.IsEOF()) { + uint32_t flag = stream.ReadFlag(); + size_t start_point = flag ? 4 : 0; + size_t start_color = flag ? 2 : 0; + if (flag) { + SkPoint temp_cubics[4]; + for (size_t i = 0; i < std::size(temp_cubics); ++i) { + temp_cubics[i] = cubics[(flag * 3 + i) % 12]; + } + std::copy(std::begin(temp_cubics), std::end(temp_cubics), + std::begin(cubics)); + SkColor temp_colors[2] = {colors[flag % 4], colors[(flag + 1) % 4]}; + std::copy(std::begin(temp_colors), std::end(temp_colors), + std::begin(colors)); } - std::copy(std::begin(temp_cubics), std::end(temp_cubics), - std::begin(cubics)); - SkColor temp_colors[2] = {colors[flag % 4], colors[(flag + 1) % 4]}; - std::copy(std::begin(temp_colors), std::end(temp_colors), - std::begin(colors)); + for (size_t i = start_point; i < std::size(cubics); ++i) { + CFX_PointF point = stream.ReadCoords(); + cubics[i].fX = point.x; + cubics[i].fY = point.y; + } + for (size_t i = start_color; i < std::size(colors); ++i) { + FX_RGB_STRUCT<float> rgb = stream.ReadColor(); + colors[i] = + SkColorSetARGB(0xFF, (U8CPU)(rgb.red * 255), + (U8CPU)(rgb.green * 255), (U8CPU)(rgb.blue * 255)); + } + m_pCanvas->drawPatch(cubics, colors, /*texCoords=*/nullptr, + SkBlendMode::kDst, paint); } - for (size_t i = start_point; i < std::size(cubics); ++i) { - CFX_PointF point = stream.ReadCoords(); - cubics[i].fX = point.x; - cubics[i].fY = point.y; - } - for (size_t i = start_color; i < std::size(colors); ++i) { - FX_RGB_STRUCT<float> rgb = stream.ReadColor(); - colors[i] = - SkColorSetARGB(0xFF, (U8CPU)(rgb.red * 255), - (U8CPU)(rgb.green * 255), (U8CPU)(rgb.blue * 255)); - } - m_pCanvas->drawPatch(cubics, colors, /*texCoords=*/nullptr, - SkBlendMode::kDst, paint); - } + }); return true; } SkAutoCanvasRestore scoped_save_restore(m_pCanvas, /*doSave=*/true);