Commit c1c43a17 authored by Mike Reed's avatar Mike Reed
Browse files

fix overflow in fill_sequential quad case

compute max count from buffer size for bitmap shader
zero-init paint in constructor to account for padding so that our == works correctly using memcmp
parent 9a5843c9
......@@ -140,10 +140,10 @@ void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
return;
}
uint32_t buffer[BUF_MAX + 1];
uint32_t buffer[BUF_MAX];
SkBitmapProcState::MatrixProc mproc = state.fMatrixProc;
SkBitmapProcState::SampleProc32 sproc = state.fSampleProc32;
int max = fState.fDoFilter ? (BUF_MAX >> 1) : BUF_MAX;
int max = fState.maxCountForBufferSize(sizeof(buffer));
SkASSERT(state.fBitmap->getPixels());
SkASSERT(state.fBitmap->pixelRef() == NULL ||
......@@ -175,7 +175,7 @@ void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
uint32_t buffer[BUF_MAX];
SkBitmapProcState::MatrixProc mproc = state.fMatrixProc;
SkBitmapProcState::SampleProc16 sproc = state.fSampleProc16;
int max = fState.fDoFilter ? (BUF_MAX >> 1) : BUF_MAX;
int max = fState.maxCountForBufferSize(sizeof(buffer));
SkASSERT(state.fBitmap->getPixels());
SkASSERT(state.fBitmap->pixelRef() == NULL ||
......
......@@ -510,3 +510,31 @@ bool SkBitmapProcState::chooseProcs(const SkMatrix& inv, const SkPaint& paint) {
return true;
}
///////////////////////////////////////////////////////////////////////////////
/*
The storage requirements for the different matrix procs are as follows,
where each X or Y is 2 bytes, and N is the number of pixels/elements:
scale/translate nofilter Y(4bytes) + N * X
affine/perspective nofilter N * (X Y)
scale/translate filter Y Y + N * (X X)
affine/perspective filter N * (Y Y X X)
*/
int SkBitmapProcState::maxCountForBufferSize(size_t bufferSize) const {
int32_t size = static_cast<int32_t>(bufferSize);
int perElemShift;
size &= ~3; // only care about 4-byte aligned chunks
if (fInvType <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) {
size -= 4; // the shared Y (or YY) coordinate
if (size < 0) {
size = 0;
}
perElemShift = fDoFilter ? 2 : 1;
} else {
perElemShift = fDoFilter ? 3 : 2;
}
return size >> perElemShift;
}
......@@ -91,6 +91,16 @@ struct SkBitmapProcState {
*/
void platformProcs();
/** Given the size of a buffer, to be used for calling the matrix and
sample procs, this return the maximum count that can be stored in the
buffer, taking into account that filtering and scale-vs-affine affect
this value.
Only valid to call after chooseProcs (setContext) has been called. It is
safe to call this inside the shader's shadeSpan() method.
*/
int maxCountForBufferSize(size_t bufferSize) const;
private:
friend class SkBitmapProcShader;
......
......@@ -202,7 +202,7 @@ static void fill_sequential(uint16_t xptr[], int start, int count) {
pattern0 += 0x40004;
*xxptr++ = pattern1;
pattern1 += 0x40004;
} while (--qcount >= 0);
} while (--qcount != 0);
xptr = reinterpret_cast<uint16_t*>(xxptr);
count &= 3;
}
......
......@@ -33,13 +33,15 @@
#define SK_DefaultFlags 0 //(kNativeHintsText_Flag)
SkPaint::SkPaint()
{
SkPaint::SkPaint() {
// since we may have padding, we zero everything so that our memcmp() call
// in operator== will work correctly.
// with this, we can skip 0 and null individual initializations
sk_bzero(this, sizeof(*this));
#if 0 // not needed with the bzero call above
fTypeface = NULL;
fTextSize = SK_DefaultTextSize;
fTextScaleX = SK_Scalar1;
fTextSkewX = 0;
fPathEffect = NULL;
fShader = NULL;
fXfermode = NULL;
......@@ -47,9 +49,12 @@ SkPaint::SkPaint()
fColorFilter = NULL;
fRasterizer = NULL;
fLooper = NULL;
fWidth = 0;
#endif
fTextSize = SK_DefaultTextSize;
fTextScaleX = SK_Scalar1;
fColor = SK_ColorBLACK;
fWidth = 0;
fMiterLimit = SK_DefaultMiterLimit;
fFlags = SK_DefaultFlags;
fCapType = kDefault_Cap;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment