Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(361)

Unified Diff: src/core/SkBlitter.cpp

Issue 1453163002: Fix array overrun and add test. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: had x and y swapped Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/BlitMaskClip.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkBlitter.cpp
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index 1bc9963eeb0db1a1d5007d812c77affe0f61807c..064dc16eda4fd98f4ed9de1f821ab2ec67a0567c 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -83,18 +83,18 @@ void SkBlitter::blitAntiRect(int x, int y, int width, int height,
static inline void bits_to_runs(SkBlitter* blitter, int x, int y,
const uint8_t bits[],
- U8CPU left_mask, int rowBytes,
- U8CPU right_mask) {
+ uint8_t left_mask, ptrdiff_t rowBytes,
+ uint8_t right_mask) {
int inFill = 0;
int pos = 0;
while (--rowBytes >= 0) {
- unsigned b = *bits++ & left_mask;
+ uint8_t b = *bits++ & left_mask;
if (rowBytes == 0) {
b &= right_mask;
}
- for (unsigned test = 0x80; test != 0; test >>= 1) {
+ for (uint8_t test = 0x80U; test != 0; test >>= 1) {
if (b & test) {
if (!inFill) {
pos = x;
@@ -108,7 +108,7 @@ static inline void bits_to_runs(SkBlitter* blitter, int x, int y,
}
x += 1;
}
- left_mask = 0xFF;
+ left_mask = 0xFFU;
}
// final cleanup
@@ -117,6 +117,11 @@ static inline void bits_to_runs(SkBlitter* blitter, int x, int y,
}
}
+// maskBitCount is the number of 1's to place in the mask. It must be in the range between 1 and 8.
+static uint8_t generate_right_mask(int maskBitCount) {
+ return static_cast<uint8_t>(0xFF00U >> maskBitCount);
+}
+
void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
SkASSERT(mask.fBounds.contains(clip));
@@ -124,54 +129,55 @@ void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
int cx = clip.fLeft;
int cy = clip.fTop;
int maskLeft = mask.fBounds.fLeft;
- int mask_rowBytes = mask.fRowBytes;
+ int maskRowBytes = mask.fRowBytes;
int height = clip.height();
const uint8_t* bits = mask.getAddr1(cx, cy);
+ SkDEBUGCODE(const uint8_t* endOfImage =
+ mask.fImage + (mask.fBounds.height() - 1) * maskRowBytes
+ + ((mask.fBounds.width() + 7) >> 3));
+
if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
while (--height >= 0) {
- bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF);
- bits += mask_rowBytes;
+ int affectedRightBit = mask.fBounds.width() - 1;
+ ptrdiff_t rowBytes = (affectedRightBit >> 3) + 1;
+ SkASSERT(bits + rowBytes <= endOfImage);
+ U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
+ bits_to_runs(this, cx, cy, bits, 0xFF, rowBytes, rightMask);
+ bits += maskRowBytes;
cy += 1;
}
} else {
- int left_edge = cx - maskLeft;
- SkASSERT(left_edge >= 0);
- int rite_edge = clip.fRight - maskLeft;
- SkASSERT(rite_edge > left_edge);
-
- int left_mask = 0xFF >> (left_edge & 7);
- int rite_mask = 0xFF << (8 - (rite_edge & 7));
- int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
-
- // check for empty right mask, so we don't read off the end (or go slower than we need to)
- if (rite_mask == 0) {
- SkASSERT(full_runs >= 0);
- full_runs -= 1;
- rite_mask = 0xFF;
- }
- if (left_mask == 0xFF) {
- full_runs -= 1;
- }
-
- // back up manually so we can keep in sync with our byte-aligned src
- // have cx reflect our actual starting x-coord
- cx -= left_edge & 7;
+ // Bits is calculated as the offset into the mask at the point {cx, cy} therfore, all
+ // addressing into the bit mask is relative to that point. Since this is an address
+ // calculated from a arbitrary bit in that byte, calculate the left most bit.
+ int bitsLeft = cx - ((cx - maskLeft) & 7);
+
+ // Everything is relative to the bitsLeft.
+ int leftEdge = cx - bitsLeft;
+ SkASSERT(leftEdge >= 0);
+ int rightEdge = clip.fRight - bitsLeft;
+ SkASSERT(rightEdge > leftEdge);
+
+ // Calculate left byte and mask
+ const uint8_t* leftByte = bits;
+ U8CPU leftMask = 0xFFU >> (leftEdge & 7);
+
+ // Calculate right byte and mask
+ int affectedRightBit = rightEdge - 1;
+ const uint8_t* rightByte = bits + (affectedRightBit >> 3);
+ U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
+
+ // leftByte and rightByte are byte locations therefore, to get a count of bytes the
+ // code must add one.
+ ptrdiff_t rowBytes = rightByte - leftByte + 1;
- if (full_runs < 0) {
- SkASSERT((left_mask & rite_mask) != 0);
- while (--height >= 0) {
- bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask);
- bits += mask_rowBytes;
- cy += 1;
- }
- } else {
- while (--height >= 0) {
- bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask);
- bits += mask_rowBytes;
- cy += 1;
- }
+ while (--height >= 0) {
+ SkASSERT(bits + rowBytes <= endOfImage);
+ bits_to_runs(this, bitsLeft, cy, bits, leftMask, rowBytes, rightMask);
+ bits += maskRowBytes;
+ cy += 1;
}
}
} else {
« no previous file with comments | « no previous file | tests/BlitMaskClip.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698