From 3f0260d0f7692f28057cfcf7121829285e972e28 Mon Sep 17 00:00:00 2001 From: "wjmaclean@chromium.org" Date: Tue, 22 Feb 2011 22:32:14 +0000 Subject: [PATCH] Cleanup issues related to SkBitmap getSize()/extractSubset(). Some minor revisions to do cleanup regarding getSize() and extractSubset(). All are related to avoid read/write past end of the pixel buffer when getSize() is used on a bitmap that is the result of a call to extractSubset(). git-svn-id: http://skia.googlecode.com/svn/trunk@835 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkBitmap.cpp | 17 +++++++++++++---- src/utils/win/SkOSWindow_Win.cpp | 6 ++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index 3e26639..a0ab52d 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -1321,7 +1321,14 @@ void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { } else { buffer.write8(SERIALIZE_PIXELTYPE_RAW_NO_CTABLE); } - buffer.writePad(fPixels, this->getSize()); + buffer.writePad(fPixels, this->getSafeSize()); + // There is no writeZeroPad() fcn, so write individual bytes. + if (this->getSize() > this->getSafeSize()) { + size_t deltaSize = this->getSize() - this->getSafeSize(); + // Need aligned pointer to write into due to internal implementa- + // tion of SkWriter32. + memset(buffer.reserve(SkAlign4(deltaSize)), 0, deltaSize); + } } else { buffer.write8(SERIALIZE_PIXELTYPE_NONE); } @@ -1338,7 +1345,6 @@ void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { this->setConfig((Config)config, width, height, rowBytes); this->setIsOpaque(buffer.readBool()); - size_t size = this->getSize(); int reftype = buffer.readU8(); switch (reftype) { case SERIALIZE_PIXELTYPE_REF_PTR: { @@ -1360,10 +1366,13 @@ void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { if (SERIALIZE_PIXELTYPE_RAW_WITH_CTABLE == reftype) { ctable = SkNEW_ARGS(SkColorTable, (buffer)); } + size_t size = this->getSize(); if (this->allocPixels(ctable)) { this->lockPixels(); - buffer.read(this->getPixels(), this->getSafeSize()); // Just read what we need. - buffer.skip(size - this->getSafeSize()); // Keep aligned for subsequent reads. + // Just read what we need. + buffer.read(this->getPixels(), this->getSafeSize()); + // Keep aligned for subsequent reads. + buffer.skip(size - this->getSafeSize()); this->unlockPixels(); } else { buffer.skip(size); // Still skip the full-sized buffer though. diff --git a/src/utils/win/SkOSWindow_Win.cpp b/src/utils/win/SkOSWindow_Win.cpp index d0e6cc3..3594c2f 100644 --- a/src/utils/win/SkOSWindow_Win.cpp +++ b/src/utils/win/SkOSWindow_Win.cpp @@ -149,6 +149,12 @@ void SkOSWindow::doPaint(void* ctx) { // // Do the SetDIBitsToDevice. // + // TODO(wjmaclean): + // Fix this call to handle SkBitmaps that have rowBytes != width, + // i.e. may have padding at the end of lines. The SkASSERT below + // may be ignored by builds, and the only obviously safe option + // seems to be to copy the bitmap to a temporary (contiguous) + // buffer before passing to SetDIBitsToDevice(). SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes()); bitmap.lockPixels(); int iRet = SetDIBitsToDevice(hdc, -- 2.7.4