From 1b17adb0f8bb19445aa66754a5dce9629f7ac560 Mon Sep 17 00:00:00 2001 From: Ben Wagner Date: Thu, 10 May 2018 23:00:51 -0400 Subject: Avoid possible memory leak with inner blurs. If the inner blur dst is too big, SkBlurMask::BoxBlur can return without freeing the intermediate blur mask. Fix this by using SkAutoMaskFreeImage. Use SkAutoMaskFreeImage instead of custom SkAutoTCallVProc in SkBlurMask::BlurGroundTruth. Make SkAutoMaskFreeImage a special kind of std::unique_ptr. Change-Id: I93dc54265416ca69254633b00f14be75009d990f Reviewed-on: https://skia-review.googlesource.com/127402 Reviewed-by: Florin Malita Commit-Queue: Ben Wagner --- src/core/SkBlurMask.cpp | 6 +++--- src/core/SkMask.h | 24 ++++-------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/core/SkBlurMask.cpp b/src/core/SkBlurMask.cpp index 04fd92292b..f4fa100961 100644 --- a/src/core/SkBlurMask.cpp +++ b/src/core/SkBlurMask.cpp @@ -205,6 +205,7 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src, SkScalar sigma, SkBlurS case kInner_SkBlurStyle: { // now we allocate the "real" dst, mirror the size of src SkMask blur = *dst; + SkAutoMaskFreeImage autoFreeBlurMask(blur.fImage); dst->fBounds = src.fBounds; dst->fRowBytes = dst->fBounds.width(); size_t dstSize = dst->computeImageSize(); @@ -247,7 +248,6 @@ bool SkBlurMask::BoxBlur(SkMask* dst, const SkMask& src, SkScalar sigma, SkBlurS default: SK_ABORT("Unhandled format."); }; - SkMask::FreeImage(blur.fImage); } break; } @@ -547,7 +547,7 @@ bool SkBlurMask::BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src, const uint8_t* srcPixels = src.fImage; uint8_t* dstPixels = SkMask::AllocImage(dstSize); - SkAutoTCallVProc autoCall(dstPixels); + SkAutoMaskFreeImage autoFreeDstPixels(dstPixels); // do the actual blur. First, make a padded copy of the source. // use double pad so we never have to check if we're outside anything @@ -637,7 +637,7 @@ bool SkBlurMask::BlurGroundTruth(SkScalar sigma, SkMask* dst, const SkMask& src, SkMask::FreeImage(dstPixels); } break; }; - (void)autoCall.release(); + autoFreeDstPixels.release(); } if (style == kInner_SkBlurStyle) { diff --git a/src/core/SkMask.h b/src/core/SkMask.h index 395eecc44b..337664d9da 100644 --- a/src/core/SkMask.h +++ b/src/core/SkMask.h @@ -14,6 +14,8 @@ #include "SkRect.h" #include "SkTemplates.h" +#include + /** \class SkMask SkMask is used to describe alpha bitmaps, either 1bit, 8bit, or the 3-channel 3D format. These are passed to SkMaskFilter objects. @@ -229,30 +231,12 @@ template <> struct SkMask::AlphaIter { /////////////////////////////////////////////////////////////////////////////// /** - * \class SkAutoMaskImage + * \using SkAutoMaskImage * * Stack class used to manage the fImage buffer in a SkMask. * When this object loses scope, the buffer is freed with SkMask::FreeImage(). */ -class SkAutoMaskFreeImage { -public: - SkAutoMaskFreeImage(uint8_t* maskImage) { - fImage = maskImage; - } - - ~SkAutoMaskFreeImage() { - SkMask::FreeImage(fImage); - } - - uint8_t* release() { - uint8_t* tmp = fImage; - fImage = nullptr; - return tmp; - } - -private: - uint8_t* fImage; -}; +using SkAutoMaskFreeImage = std::unique_ptr>; #define SkAutoMaskFreeImage(...) SK_REQUIRE_LOCAL_VAR(SkAutoMaskFreeImage) #endif -- cgit v1.2.3