From c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cf Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Wed, 23 Oct 2013 17:06:21 +0000 Subject: [PATCH] Initial error handling code I made it as simple as possible. The impact seems minimal and it should do what's necessary to make this code secure. BUG= Committed: http://code.google.com/p/skia/source/detail?r=11247 R=reed@google.com, scroggo@google.com, djsollen@google.com, sugoi@google.com, bsalomon@google.com, mtklein@google.com, senorblanco@google.com, senorblanco@chromium.org Author: sugoi@chromium.org Review URL: https://codereview.chromium.org/23021015 git-svn-id: http://skia.googlecode.com/svn/trunk@11922 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gm/imagefiltersbase.cpp | 6 +- gyp/core.gypi | 1 + include/core/SkColorFilter.h | 2 + include/core/SkDrawLooper.h | 1 + include/core/SkFlattenable.h | 38 +++- include/core/SkFlattenableBuffers.h | 86 ++++---- include/core/SkImageFilter.h | 2 + include/core/SkMaskFilter.h | 1 + include/core/SkPathEffect.h | 2 + include/core/SkPixelRef.h | 2 + include/core/SkRasterizer.h | 2 + include/core/SkShader.h | 2 + include/core/SkUnitMapper.h | 2 + include/core/SkXfermode.h | 2 + include/effects/SkArithmeticMode.h | 9 +- src/core/SkBitmap.cpp | 12 +- src/core/SkFlattenable.cpp | 52 +++-- src/core/SkFlattenableBuffers.cpp | 55 ++++++ src/core/SkFlattenableSerialization.cpp | 3 +- src/core/SkGraphics.cpp | 1 - src/core/SkImageFilter.cpp | 2 + src/core/SkOrderedReadBuffer.cpp | 4 +- src/core/SkOrderedReadBuffer.h | 2 +- src/core/SkOrderedWriteBuffer.cpp | 9 +- src/core/SkScalerContext.cpp | 16 +- src/core/SkValidatingReadBuffer.cpp | 259 +++++++++++++++++++++++++ src/core/SkValidatingReadBuffer.h | 80 ++++++++ src/core/SkValidationUtils.h | 47 +++++ src/effects/SkBicubicImageFilter.cpp | 4 + src/effects/SkBlurImageFilter.cpp | 4 + src/effects/SkColorFilters.cpp | 2 + src/effects/SkColorMatrixFilter.cpp | 3 + src/effects/SkDisplacementMapEffect.cpp | 17 ++ src/effects/SkDropShadowImageFilter.cpp | 3 + src/effects/SkLightingImageFilter.cpp | 13 +- src/effects/SkMagnifierImageFilter.cpp | 3 + src/effects/SkMatrixConvolutionImageFilter.cpp | 15 ++ src/effects/SkMergeImageFilter.cpp | 7 +- src/effects/SkMorphologyImageFilter.cpp | 2 + src/effects/SkOffsetImageFilter.cpp | 2 + src/effects/SkTestImageFilters.cpp | 1 + src/effects/SkTileImageFilter.cpp | 2 + src/pipe/SkGPipeRead.cpp | 22 +-- src/ports/SkGlobalInitialization_chromium.cpp | 94 ++++++++- src/ports/SkGlobalInitialization_default.cpp | 12 +- 45 files changed, 791 insertions(+), 115 deletions(-) create mode 100644 src/core/SkValidatingReadBuffer.cpp create mode 100644 src/core/SkValidatingReadBuffer.h create mode 100644 src/core/SkValidationUtils.h diff --git a/gm/imagefiltersbase.cpp b/gm/imagefiltersbase.cpp index ca45eaf..2c8fceb 100644 --- a/gm/imagefiltersbase.cpp +++ b/gm/imagefiltersbase.cpp @@ -35,7 +35,8 @@ private: // register the filter with the flattenable registry static SkFlattenable::Registrar gFailImageFilterReg("FailImageFilter", - FailImageFilter::CreateProc); + FailImageFilter::CreateProc, + FailImageFilter::GetFlattenableType()); class IdentityImageFilter : public SkImageFilter { public: @@ -57,7 +58,8 @@ private: // register the filter with the flattenable registry static SkFlattenable::Registrar gIdentityImageFilterReg("IdentityImageFilter", - IdentityImageFilter::CreateProc); + IdentityImageFilter::CreateProc, + IdentityImageFilter::GetFlattenableType()); /////////////////////////////////////////////////////////////////////////////// diff --git a/gyp/core.gypi b/gyp/core.gypi index e6a7a44..5be1ead 100644 --- a/gyp/core.gypi +++ b/gyp/core.gypi @@ -195,6 +195,7 @@ '<(skia_src_path)/core/SkTypefaceCache.h', '<(skia_src_path)/core/SkUnPreMultiply.cpp', '<(skia_src_path)/core/SkUtils.cpp', + '<(skia_src_path)/core/SkValidatingReadBuffer.cpp', '<(skia_src_path)/core/SkWriter32.cpp', '<(skia_src_path)/core/SkXfermode.cpp', diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h index 46ecedc..106e5bb 100644 --- a/include/core/SkColorFilter.h +++ b/include/core/SkColorFilter.h @@ -131,6 +131,8 @@ public: SkDEVCODE(virtual void toString(SkString* str) const = 0;) SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() + SK_DEFINE_FLATTENABLE_TYPE(SkColorFilter) + protected: SkColorFilter() {} SkColorFilter(SkFlattenableReadBuffer& rb) : INHERITED(rb) {} diff --git a/include/core/SkDrawLooper.h b/include/core/SkDrawLooper.h index 2faf28b..d6028ff 100644 --- a/include/core/SkDrawLooper.h +++ b/include/core/SkDrawLooper.h @@ -64,6 +64,7 @@ public: const SkRect& src, SkRect* dst); SkDEVCODE(virtual void toString(SkString* str) const = 0;) + SK_DEFINE_FLATTENABLE_TYPE(SkDrawLooper) protected: SkDrawLooper() {} diff --git a/include/core/SkFlattenable.h b/include/core/SkFlattenable.h index 6cc76db..5a6e2ae 100644 --- a/include/core/SkFlattenable.h +++ b/include/core/SkFlattenable.h @@ -16,7 +16,8 @@ class SkFlattenableReadBuffer; class SkFlattenableWriteBuffer; #define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \ - SkFlattenable::Registrar(#flattenable, flattenable::CreateProc); + SkFlattenable::Registrar(#flattenable, flattenable::CreateProc, \ + flattenable::GetFlattenableType()); #define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables(); @@ -35,6 +36,14 @@ class SkFlattenableWriteBuffer; return SkNEW_ARGS(flattenable, (buffer)); \ } +/** For SkFlattenable derived objects with a valid type + This macro should only be used in base class objects in core + */ +#define SK_DEFINE_FLATTENABLE_TYPE(flattenable) \ + static Type GetFlattenableType() { \ + return k##flattenable##_Type; \ + } + /** \class SkFlattenable SkFlattenable is the base class for objects that need to be flattened @@ -43,6 +52,19 @@ class SkFlattenableWriteBuffer; */ class SK_API SkFlattenable : public SkRefCnt { public: + enum Type { + kSkColorFilter_Type, + kSkDrawLooper_Type, + kSkImageFilter_Type, + kSkMaskFilter_Type, + kSkPathEffect_Type, + kSkPixelRef_Type, + kSkRasterizer_Type, + kSkShader_Type, + kSkUnitMapper_Type, + kSkXfermode_Type, + }; + SK_DECLARE_INST_COUNT(SkFlattenable) typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&); @@ -55,14 +77,20 @@ public: */ virtual Factory getFactory() const = 0; + /** Returns the name of the object's class + */ + const char* getTypeName() const { return FactoryToName(getFactory()); } + static Factory NameToFactory(const char name[]); static const char* FactoryToName(Factory); - static void Register(const char name[], Factory); + static bool NameToType(const char name[], Type* type); + + static void Register(const char name[], Factory, Type); class Registrar { public: - Registrar(const char name[], Factory factory) { - SkFlattenable::Register(name, factory); + Registrar(const char name[], Factory factory, Type type) { + SkFlattenable::Register(name, factory, type); } }; @@ -75,7 +103,7 @@ protected: virtual void flatten(SkFlattenableWriteBuffer&) const; private: - static void InitializeFlattenables(); + static void InitializeFlattenablesIfNeeded(); friend class SkGraphics; friend class SkFlattenableWriteBuffer; diff --git a/include/core/SkFlattenableBuffers.h b/include/core/SkFlattenableBuffers.h index d71f7c0..6e44550 100644 --- a/include/core/SkFlattenableBuffers.h +++ b/include/core/SkFlattenableBuffers.h @@ -24,7 +24,6 @@ class SkOrderedWriteBuffer; class SkPath; class SkPixelRef; struct SkRect; -class SkRefCnt; class SkRegion; class SkStream; class SkString; @@ -32,19 +31,6 @@ class SkTypeface; class SkUnitMapper; class SkWStream; -enum SkEffectType { - kColorFilter_SkEffectType, - kDrawLooper_SkEffectType, - kImageFilter_SkEffectType, - kMaskFilter_SkEffectType, - kPathEffect_SkEffectType, - kPixelRef_SkEffectType, - kRasterizer_SkEffectType, - kShader_SkEffectType, - kUnitMapper_SkEffectType, - kXfermode_SkEffectType, -}; - class SkFlattenableReadBuffer { public: SkFlattenableReadBuffer(); @@ -57,14 +43,20 @@ public: kCrossProcess_Flag = 1 << 0, kScalarIsFloat_Flag = 1 << 1, kPtrIs64Bit_Flag = 1 << 2, + /** The kValidation_Flag is used to force stream validations (by making + * sure that no operation reads past the end of the stream, for example) + * and error handling if any reading operation yields an invalid value. + */ + kValidation_Flag = 1 << 3, }; void setFlags(uint32_t flags) { fFlags = flags; } uint32_t getFlags() const { return fFlags; } - bool isCrossProcess() const { return SkToBool(fFlags & kCrossProcess_Flag); } + bool isCrossProcess() const { return SkToBool(fFlags & (kCrossProcess_Flag | kValidation_Flag)); } bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); } bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); } + bool isValidating() const { return SkToBool(fFlags & kValidation_Flag); } // primitives virtual bool readBool() = 0; @@ -79,38 +71,24 @@ public: virtual void readString(SkString* string) = 0; virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) = 0; - virtual SkFlattenable* readFlattenable(SkEffectType) = 0; - - SkColorFilter* readColorFilter() { - return (SkColorFilter*)this->readFlattenable(kColorFilter_SkEffectType); - } - SkDrawLooper* readDrawLooper() { - return (SkDrawLooper*)this->readFlattenable(kDrawLooper_SkEffectType); - } - SkImageFilter* readImageFilter() { - return (SkImageFilter*)this->readFlattenable(kImageFilter_SkEffectType); - } - SkMaskFilter* readMaskFilter() { - return (SkMaskFilter*)this->readFlattenable(kMaskFilter_SkEffectType); - } - SkPathEffect* readPathEffect() { - return (SkPathEffect*)this->readFlattenable(kPathEffect_SkEffectType); - } - SkPixelRef* readPixelRef() { - return (SkPixelRef*)this->readFlattenable(kPixelRef_SkEffectType); - } - SkRasterizer* readRasterizer() { - return (SkRasterizer*)this->readFlattenable(kRasterizer_SkEffectType); - } - SkShader* readShader() { - return (SkShader*)this->readFlattenable(kShader_SkEffectType); - } - SkUnitMapper* readUnitMapper() { - return (SkUnitMapper*)this->readFlattenable(kUnitMapper_SkEffectType); - } - SkXfermode* readXfermode() { - return (SkXfermode*)this->readFlattenable(kXfermode_SkEffectType); - } + /** + @param type This parameter is only used when using SkValidatingReadBuffer. It will verify + that the object about to be deserialized is of the given type or early return + NULL otherwise. The type provided here is the type of the base class of the + object to deserialize. + */ + virtual SkFlattenable* readFlattenable(SkFlattenable::Type type) = 0; + + SkColorFilter* readColorFilter(); + SkDrawLooper* readDrawLooper(); + SkImageFilter* readImageFilter(); + SkMaskFilter* readMaskFilter(); + SkPathEffect* readPathEffect(); + SkPixelRef* readPixelRef(); + SkRasterizer* readRasterizer(); + SkShader* readShader(); + SkUnitMapper* readUnitMapper(); + SkXfermode* readXfermode(); // common data structures virtual void readPoint(SkPoint* point) = 0; @@ -153,7 +131,10 @@ public: return SkData::NewFromMalloc(buffer, len); } + virtual void validate(bool isValid) {} + private: + template T* readFlattenableT(); uint32_t fFlags; }; @@ -205,13 +186,22 @@ public: enum Flags { kCrossProcess_Flag = 0x01, + /** The kValidation_Flag is used here to make sure the write operation + * is symmetric with the read operation using the equivalent flag + * SkFlattenableReadBuffer::kValidation_Flag. + */ + kValidation_Flag = 0x02, }; uint32_t getFlags() const { return fFlags; } void setFlags(uint32_t flags) { fFlags = flags; } bool isCrossProcess() const { - return SkToBool(fFlags & kCrossProcess_Flag); + return SkToBool(fFlags & (kCrossProcess_Flag | kValidation_Flag)); + } + + bool isValidating() const { + return SkToBool(fFlags & kValidation_Flag); } bool persistTypeface() const { return (fFlags & kCrossProcess_Flag) != 0; } diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h index a0602e4..56ebc2b 100644 --- a/include/core/SkImageFilter.h +++ b/include/core/SkImageFilter.h @@ -143,6 +143,8 @@ public: */ bool cropRectIsSet() const { return fCropRect.flags() != 0x0; } + SK_DEFINE_FLATTENABLE_TYPE(SkImageFilter) + protected: SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL); diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h index a2bc638..93e2d4b 100644 --- a/include/core/SkMaskFilter.h +++ b/include/core/SkMaskFilter.h @@ -125,6 +125,7 @@ public: virtual void computeFastBounds(const SkRect& src, SkRect* dest) const; SkDEVCODE(virtual void toString(SkString* str) const = 0;) + SK_DEFINE_FLATTENABLE_TYPE(SkMaskFilter) protected: // empty for now, but lets get our subclass to remember to init us for the future diff --git a/include/core/SkPathEffect.h b/include/core/SkPathEffect.h index 3b4541d..ed6d93b 100644 --- a/include/core/SkPathEffect.h +++ b/include/core/SkPathEffect.h @@ -106,6 +106,8 @@ public: const SkStrokeRec&, const SkMatrix&, const SkRect* cullR) const; + SK_DEFINE_FLATTENABLE_TYPE(SkPathEffect) + protected: SkPathEffect(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h index 64e0876..958e82f 100644 --- a/include/core/SkPixelRef.h +++ b/include/core/SkPixelRef.h @@ -207,6 +207,8 @@ public: virtual void globalUnref(); #endif + SK_DEFINE_FLATTENABLE_TYPE(SkPixelRef) + protected: /** Called when the lockCount goes from 0 to 1. The caller will have already acquire a mutex for thread safety, so this method need not do that. diff --git a/include/core/SkRasterizer.h b/include/core/SkRasterizer.h index 3e662ab..6e6224e 100644 --- a/include/core/SkRasterizer.h +++ b/include/core/SkRasterizer.h @@ -30,6 +30,8 @@ public: const SkIRect* clipBounds, SkMaskFilter* filter, SkMask* mask, SkMask::CreateMode mode) const; + SK_DEFINE_FLATTENABLE_TYPE(SkRasterizer) + protected: SkRasterizer(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} diff --git a/include/core/SkShader.h b/include/core/SkShader.h index 74f611d..11956ce 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -344,6 +344,8 @@ public: SkDEVCODE(virtual void toString(SkString* str) const;) + SK_DEFINE_FLATTENABLE_TYPE(SkShader) + protected: enum MatrixClass { kLinear_MatrixClass, // no perspective diff --git a/include/core/SkUnitMapper.h b/include/core/SkUnitMapper.h index 754be26..57a8b83 100644 --- a/include/core/SkUnitMapper.h +++ b/include/core/SkUnitMapper.h @@ -25,6 +25,8 @@ public: */ virtual uint16_t mapUnit16(uint16_t x) = 0; + SK_DEFINE_FLATTENABLE_TYPE(SkUnitMapper) + protected: SkUnitMapper(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {} diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h index 0cc430e..db9b0b0 100644 --- a/include/core/SkXfermode.h +++ b/include/core/SkXfermode.h @@ -220,6 +220,8 @@ public: SkDEVCODE(virtual void toString(SkString* str) const = 0;) SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() + SK_DEFINE_FLATTENABLE_TYPE(SkXfermode) + protected: SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {} diff --git a/include/effects/SkArithmeticMode.h b/include/effects/SkArithmeticMode.h index 9de332c..46b7121 100644 --- a/include/effects/SkArithmeticMode.h +++ b/include/effects/SkArithmeticMode.h @@ -8,9 +8,12 @@ #ifndef SkArithmeticMode_DEFINED #define SkArithmeticMode_DEFINED -#include "SkXfermode.h" +#include "SkFlattenable.h" +#include "SkScalar.h" -class SK_API SkArithmeticMode : public SkXfermode { +class SkXfermode; + +class SK_API SkArithmeticMode { public: /** * result = clamp[k1 * src * dst + k2 * src + k3 * dst + k4] @@ -28,7 +31,7 @@ public: SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP(); private: - typedef SkXfermode INHERITED; + SkArithmeticMode(); // can't be instantiated }; #endif diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index 05f5208..046e20a 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -19,6 +19,7 @@ #include "SkThread.h" #include "SkUnPreMultiply.h" #include "SkUtils.h" +#include "SkValidationUtils.h" #include "SkPackBits.h" #include @@ -268,7 +269,7 @@ void SkBitmap::getBounds(SkIRect* bounds) const { /////////////////////////////////////////////////////////////////////////////// static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType, - SkAlphaType* canonical) { + SkAlphaType* canonical = NULL) { switch (config) { case SkBitmap::kNo_Config: alphaType = kIgnore_SkAlphaType; @@ -1604,10 +1605,12 @@ void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { int width = buffer.readInt(); int height = buffer.readInt(); int rowBytes = buffer.readInt(); - int config = buffer.readInt(); - int alphaType = buffer.readInt(); + Config config = (Config)buffer.readInt(); + SkAlphaType alphaType = (SkAlphaType)buffer.readInt(); + buffer.validate((width >= 0) && (height >= 0) && (rowBytes >= 0) && + SkIsValidConfig(config) && validate_alphaType(config, alphaType)); - this->setConfig((Config)config, width, height, rowBytes, (SkAlphaType)alphaType); + this->setConfig(config, width, height, rowBytes, alphaType); int reftype = buffer.readInt(); switch (reftype) { @@ -1620,6 +1623,7 @@ void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { case SERIALIZE_PIXELTYPE_NONE: break; default: + buffer.validate(false); SkDEBUGFAIL("unrecognized pixeltype in serialized data"); sk_throw(); } diff --git a/src/core/SkFlattenable.cpp b/src/core/SkFlattenable.cpp index b4efe91..6cebb22 100644 --- a/src/core/SkFlattenable.cpp +++ b/src/core/SkFlattenable.cpp @@ -63,64 +63,84 @@ void SkRefCntSet::decPtr(void* ptr) { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -#define MAX_PAIR_COUNT 1024 +#define MAX_ENTRY_COUNT 1024 -struct Pair { +struct Entry { const char* fName; SkFlattenable::Factory fFactory; + SkFlattenable::Type fType; }; static int gCount; -static Pair gPairs[MAX_PAIR_COUNT]; +static Entry gEntries[MAX_ENTRY_COUNT]; -void SkFlattenable::Register(const char name[], Factory factory) { +void SkFlattenable::Register(const char name[], Factory factory, SkFlattenable::Type type) { SkASSERT(name); SkASSERT(factory); - static bool gOnce; + static bool gOnce = false; if (!gOnce) { gCount = 0; gOnce = true; } - SkASSERT(gCount < MAX_PAIR_COUNT); + SkASSERT(gCount < MAX_ENTRY_COUNT); - gPairs[gCount].fName = name; - gPairs[gCount].fFactory = factory; + gEntries[gCount].fName = name; + gEntries[gCount].fFactory = factory; + gEntries[gCount].fType = type; gCount += 1; } #ifdef SK_DEBUG static void report_no_entries(const char* functionName) { if (!gCount) { - SkDebugf("%s has no registered name/factory pairs." - " Call SkGraphics::Init() at process initialization time.", + SkDebugf("%s has no registered name/factory/type entries." + " Call SkFlattenable::InitializeFlattenablesIfNeeded() before using gEntries", functionName); } } #endif SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) { + InitializeFlattenablesIfNeeded(); #ifdef SK_DEBUG report_no_entries(__FUNCTION__); #endif - const Pair* pairs = gPairs; + const Entry* entries = gEntries; for (int i = gCount - 1; i >= 0; --i) { - if (strcmp(pairs[i].fName, name) == 0) { - return pairs[i].fFactory; + if (strcmp(entries[i].fName, name) == 0) { + return entries[i].fFactory; } } return NULL; } +bool SkFlattenable::NameToType(const char name[], SkFlattenable::Type* type) { + SkASSERT(NULL != type); + InitializeFlattenablesIfNeeded(); +#ifdef SK_DEBUG + report_no_entries(__FUNCTION__); +#endif + const Entry* entries = gEntries; + for (int i = gCount - 1; i >= 0; --i) { + if (strcmp(entries[i].fName, name) == 0) { + *type = entries[i].fType; + return true; + } + } + return false; +} + const char* SkFlattenable::FactoryToName(Factory fact) { + InitializeFlattenablesIfNeeded(); #ifdef SK_DEBUG report_no_entries(__FUNCTION__); #endif - const Pair* pairs = gPairs; + const Entry* entries = gEntries; for (int i = gCount - 1; i >= 0; --i) { - if (pairs[i].fFactory == fact) { - return pairs[i].fName; + if (entries[i].fFactory == fact) { + return entries[i].fName; } } return NULL; diff --git a/src/core/SkFlattenableBuffers.cpp b/src/core/SkFlattenableBuffers.cpp index 5167c2e..dbf66da 100644 --- a/src/core/SkFlattenableBuffers.cpp +++ b/src/core/SkFlattenableBuffers.cpp @@ -9,6 +9,17 @@ #include "SkPaint.h" #include "SkTypeface.h" +#include "SkColorFilter.h" +#include "SkDrawLooper.h" +#include "SkImageFilter.h" +#include "SkMaskFilter.h" +#include "SkPathEffect.h" +#include "SkPixelRef.h" +#include "SkRasterizer.h" +#include "SkShader.h" +#include "SkUnitMapper.h" +#include "SkXfermode.h" + SkFlattenableReadBuffer::SkFlattenableReadBuffer() { // Set default values. These should be explicitly set by our client // via setFlags() if the buffer came from serialization. @@ -34,6 +45,50 @@ void SkFlattenableReadBuffer::readPaint(SkPaint* paint) { paint->unflatten(*this); } +template T* SkFlattenableReadBuffer::readFlattenableT() { + return static_cast(this->readFlattenable(T::GetFlattenableType())); +} + +SkColorFilter* SkFlattenableReadBuffer::readColorFilter() { + return this->readFlattenableT(); +} + +SkDrawLooper* SkFlattenableReadBuffer::readDrawLooper() { + return this->readFlattenableT(); +} + +SkImageFilter* SkFlattenableReadBuffer::readImageFilter() { + return this->readFlattenableT(); +} + +SkMaskFilter* SkFlattenableReadBuffer::readMaskFilter() { + return this->readFlattenableT(); +} + +SkPathEffect* SkFlattenableReadBuffer::readPathEffect() { + return this->readFlattenableT(); +} + +SkPixelRef* SkFlattenableReadBuffer::readPixelRef() { + return this->readFlattenableT(); +} + +SkRasterizer* SkFlattenableReadBuffer::readRasterizer() { + return this->readFlattenableT(); +} + +SkShader* SkFlattenableReadBuffer::readShader() { + return this->readFlattenableT(); +} + +SkUnitMapper* SkFlattenableReadBuffer::readUnitMapper() { + return this->readFlattenableT(); +} + +SkXfermode* SkFlattenableReadBuffer::readXfermode() { + return this->readFlattenableT(); +} + /////////////////////////////////////////////////////////////////////////////// SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() { diff --git a/src/core/SkFlattenableSerialization.cpp b/src/core/SkFlattenableSerialization.cpp index cda3182..c687074 100644 --- a/src/core/SkFlattenableSerialization.cpp +++ b/src/core/SkFlattenableSerialization.cpp @@ -23,8 +23,7 @@ SkData* SkSerializeFlattenable(SkFlattenable* flattenable) { return SkData::NewFromMalloc(data, size); } -// TODO: this guy should be renamed to ImageFilter, or take SkEffectType as -// a parameter. +// TODO: this guy should be renamed to ImageFilter, or take SkFlattenable::Type as a parameter. SkFlattenable* SkDeserializeFlattenable(const void* data, size_t size) { SkOrderedReadBuffer buffer(data, size); return buffer.readImageFilter(); diff --git a/src/core/SkGraphics.cpp b/src/core/SkGraphics.cpp index 453c30d..51521e4 100644 --- a/src/core/SkGraphics.cpp +++ b/src/core/SkGraphics.cpp @@ -59,7 +59,6 @@ void SkGraphics::Init() { skRTConfRegistry().printNonDefault( ); #endif - SkFlattenable::InitializeFlattenables(); #ifdef BUILD_EMBOSS_TABLE SkEmbossMask_BuildTable(); #endif diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 6ec982b..9bf3925 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -10,6 +10,7 @@ #include "SkBitmap.h" #include "SkFlattenableBuffers.h" #include "SkRect.h" +#include "SkValidationUtils.h" #if SK_SUPPORT_GPU #include "GrContext.h" #include "GrTexture.h" @@ -65,6 +66,7 @@ SkImageFilter::SkImageFilter(SkFlattenableReadBuffer& buffer) buffer.readRect(&rect); uint32_t flags = buffer.readUInt(); fCropRect = CropRect(rect, flags); + buffer.validate(SkIsValidRect(rect)); } void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { diff --git a/src/core/SkOrderedReadBuffer.cpp b/src/core/SkOrderedReadBuffer.cpp index aff6e20..d9aa8bd 100644 --- a/src/core/SkOrderedReadBuffer.cpp +++ b/src/core/SkOrderedReadBuffer.cpp @@ -268,9 +268,9 @@ SkTypeface* SkOrderedReadBuffer::readTypeface() { } } -SkFlattenable* SkOrderedReadBuffer::readFlattenable(SkEffectType et) { +SkFlattenable* SkOrderedReadBuffer::readFlattenable(SkFlattenable::Type ft) { // - // TODO: confirm that et matches the factory we decide to use + // TODO: confirm that ft matches the factory we decide to use // SkFlattenable::Factory factory = NULL; diff --git a/src/core/SkOrderedReadBuffer.h b/src/core/SkOrderedReadBuffer.h index b29f310..d864465 100644 --- a/src/core/SkOrderedReadBuffer.h +++ b/src/core/SkOrderedReadBuffer.h @@ -52,7 +52,7 @@ public: virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) SK_OVERRIDE; // common data structures - virtual SkFlattenable* readFlattenable(SkEffectType) SK_OVERRIDE; + virtual SkFlattenable* readFlattenable(SkFlattenable::Type) SK_OVERRIDE; virtual void readPoint(SkPoint* point) SK_OVERRIDE; virtual void readMatrix(SkMatrix* matrix) SK_OVERRIDE; virtual void readIRect(SkIRect* rect) SK_OVERRIDE; diff --git a/src/core/SkOrderedWriteBuffer.cpp b/src/core/SkOrderedWriteBuffer.cpp index 9c31b4c..1c15e43 100644 --- a/src/core/SkOrderedWriteBuffer.cpp +++ b/src/core/SkOrderedWriteBuffer.cpp @@ -270,7 +270,10 @@ void SkOrderedWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) { factory = flattenable->getFactory(); } if (NULL == factory) { - if (fFactorySet != NULL || fNamedFactorySet != NULL) { + if (this->isValidating()) { + this->writeString(""); + SkASSERT(NULL == flattenable); // We shouldn't get in here in this scenario + } else if (fFactorySet != NULL || fNamedFactorySet != NULL) { this->write32(0); } else { this->writeFunctionPtr(NULL); @@ -290,7 +293,9 @@ void SkOrderedWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) { * name. SkGPipe uses this technique so it can write the name to its * stream before writing the flattenable. */ - if (fFactorySet) { + if (this->isValidating()) { + this->writeString(flattenable->getTypeName()); + } else if (fFactorySet) { this->write32(fFactorySet->add(factory)); } else if (fNamedFactorySet) { int32_t index = fNamedFactorySet->find(factory); diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index 83cf8f8..88e3f06 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -67,14 +67,14 @@ void SkGlyph::zeroMetrics() { #endif static SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag, - SkEffectType et) { + SkFlattenable::Type ft) { SkFlattenable* obj = NULL; uint32_t len; const void* data = desc->findEntry(tag, &len); - + if (data) { SkOrderedReadBuffer buffer(data, len); - obj = buffer.readFlattenable(et); + obj = buffer.readFlattenable(ft); SkASSERT(buffer.offset() == buffer.size()); } return obj; @@ -85,10 +85,12 @@ SkScalerContext::SkScalerContext(SkTypeface* typeface, const SkDescriptor* desc) , fBaseGlyphCount(0) , fTypeface(SkRef(typeface)) - , fPathEffect(static_cast(load_flattenable(desc, kPathEffect_SkDescriptorTag, kPathEffect_SkEffectType))) - , fMaskFilter(static_cast(load_flattenable(desc, kMaskFilter_SkDescriptorTag, kMaskFilter_SkEffectType))) - , fRasterizer(static_cast(load_flattenable(desc, kRasterizer_SkDescriptorTag, kRasterizer_SkEffectType))) - + , fPathEffect(static_cast(load_flattenable(desc, kPathEffect_SkDescriptorTag, + SkFlattenable::kSkPathEffect_Type))) + , fMaskFilter(static_cast(load_flattenable(desc, kMaskFilter_SkDescriptorTag, + SkFlattenable::kSkMaskFilter_Type))) + , fRasterizer(static_cast(load_flattenable(desc, kRasterizer_SkDescriptorTag, + SkFlattenable::kSkRasterizer_Type))) // Initialize based on our settings. Subclasses can also force this. , fGenerateImageFromPath(fRec.fFrameWidth > 0 || fPathEffect != NULL || fRasterizer != NULL) diff --git a/src/core/SkValidatingReadBuffer.cpp b/src/core/SkValidatingReadBuffer.cpp new file mode 100644 index 0000000..0ffe650 --- /dev/null +++ b/src/core/SkValidatingReadBuffer.cpp @@ -0,0 +1,259 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkBitmap.h" +#include "SkErrorInternals.h" +#include "SkValidatingReadBuffer.h" +#include "SkStream.h" +#include "SkTypeface.h" + +SkValidatingReadBuffer::SkValidatingReadBuffer(const void* data, size_t size) { + this->setMemory(data, size); + fError = false; + + this->setFlags(SkFlattenableReadBuffer::kValidation_Flag); +} + +SkValidatingReadBuffer::~SkValidatingReadBuffer() { +} + +void SkValidatingReadBuffer::setMemory(const void* data, size_t size) { + fError = fError || !IsPtrAlign4(data) || (SkAlign4(size) != size); + if (!fError) { + fReader.setMemory(data, size); + } +} + +const void* SkValidatingReadBuffer::skip(size_t size) { + size_t inc = SkAlign4(size); + const void* addr = fReader.peek(); + fError = fError || !IsPtrAlign4(addr) || !fReader.isAvailable(inc); + if (!fError) { + fReader.skip(size); + } + return addr; +} + +// All the methods in this file funnel down into either readInt(), readScalar() or skip(), +// followed by a memcpy. So we've got all our validation in readInt(), readScalar() and skip(); +// if they fail they'll return a zero value or skip nothing, respectively, and set fError to +// true, which the caller should check to see if an error occurred during the read operation. + +bool SkValidatingReadBuffer::readBool() { + return this->readInt() != 0; +} + +SkColor SkValidatingReadBuffer::readColor() { + return this->readInt(); +} + +SkFixed SkValidatingReadBuffer::readFixed() { + return this->readInt(); +} + +int32_t SkValidatingReadBuffer::readInt() { + const size_t inc = sizeof(int32_t); + fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc); + return fError ? 0 : fReader.readInt(); +} + +SkScalar SkValidatingReadBuffer::readScalar() { + const size_t inc = sizeof(SkScalar); + fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc); + return fError ? 0 : fReader.readScalar(); +} + +uint32_t SkValidatingReadBuffer::readUInt() { + return this->readInt(); +} + +int32_t SkValidatingReadBuffer::read32() { + return this->readInt(); +} + +void SkValidatingReadBuffer::readString(SkString* string) { + const size_t len = this->readInt(); + const void* ptr = fReader.peek(); + const char* cptr = (const char*)ptr; + + // skip over the string + '\0' and then pad to a multiple of 4 + const size_t alignedSize = SkAlign4(len + 1); + this->skip(alignedSize); + fError = fError || (cptr[len] != '\0'); + if (!fError) { + string->set(cptr, len); + } +} + +void* SkValidatingReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) { + const int32_t encodingType = fReader.readInt(); + fError = fError || (encodingType != encoding); + *length = this->readInt(); + const void* ptr = this->skip(SkAlign4(*length)); + void* data = NULL; + if (!fError) { + data = sk_malloc_throw(*length); + memcpy(data, ptr, *length); + } + return data; +} + +void SkValidatingReadBuffer::readPoint(SkPoint* point) { + point->fX = fReader.readScalar(); + point->fY = fReader.readScalar(); +} + +void SkValidatingReadBuffer::readMatrix(SkMatrix* matrix) { + const size_t size = matrix->readFromMemory(fReader.peek()); + fError = fError || (SkAlign4(size) != size); + if (!fError) { + (void)this->skip(size); + } +} + +void SkValidatingReadBuffer::readIRect(SkIRect* rect) { + const void* ptr = this->skip(sizeof(SkIRect)); + if (!fError) { + memcpy(rect, ptr, sizeof(SkIRect)); + } +} + +void SkValidatingReadBuffer::readRect(SkRect* rect) { + const void* ptr = this->skip(sizeof(SkRect)); + if (!fError) { + memcpy(rect, ptr, sizeof(SkRect)); + } +} + +void SkValidatingReadBuffer::readRegion(SkRegion* region) { + const size_t size = region->readFromMemory(fReader.peek()); + fError = fError || (SkAlign4(size) != size); + if (!fError) { + (void)this->skip(size); + } +} + +void SkValidatingReadBuffer::readPath(SkPath* path) { + const size_t size = path->readFromMemory(fReader.peek()); + fError = fError || (SkAlign4(size) != size); + if (!fError) { + (void)this->skip(size); + } +} + +uint32_t SkValidatingReadBuffer::readByteArray(void* value) { + const uint32_t length = this->readUInt(); + const void* ptr = this->skip(SkAlign4(length)); + if (!fError) { + memcpy(value, ptr, length); + return length; + } + return 0; +} + +uint32_t SkValidatingReadBuffer::readColorArray(SkColor* colors) { + const uint32_t count = this->readUInt(); + const uint32_t byteLength = count * sizeof(SkColor); + const void* ptr = this->skip(SkAlign4(byteLength)); + if (!fError) { + memcpy(colors, ptr, byteLength); + return count; + } + return 0; +} + +uint32_t SkValidatingReadBuffer::readIntArray(int32_t* values) { + const uint32_t count = this->readUInt(); + const uint32_t byteLength = count * sizeof(int32_t); + const void* ptr = this->skip(SkAlign4(byteLength)); + if (!fError) { + memcpy(values, ptr, byteLength); + return count; + } + return 0; +} + +uint32_t SkValidatingReadBuffer::readPointArray(SkPoint* points) { + const uint32_t count = this->readUInt(); + const uint32_t byteLength = count * sizeof(SkPoint); + const void* ptr = this->skip(SkAlign4(byteLength)); + if (!fError) { + memcpy(points, ptr, byteLength); + return count; + } + return 0; +} + +uint32_t SkValidatingReadBuffer::readScalarArray(SkScalar* values) { + const uint32_t count = this->readUInt(); + const uint32_t byteLength = count * sizeof(SkScalar); + const void* ptr = this->skip(SkAlign4(byteLength)); + if (!fError) { + memcpy(values, ptr, byteLength); + return count; + } + return 0; +} + +uint32_t SkValidatingReadBuffer::getArrayCount() { + return *(uint32_t*)fReader.peek(); +} + +void SkValidatingReadBuffer::readBitmap(SkBitmap* bitmap) { + const int width = this->readInt(); + const int height = this->readInt(); + const size_t length = this->readUInt(); + // A size of zero means the SkBitmap was simply flattened. + fError = fError || (length != 0); + if (fError) { + return; + } + bitmap->unflatten(*this); + fError = fError || (bitmap->width() != width) || (bitmap->height() != height); +} + +SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type) { + SkString name; + this->readString(&name); + if (fError) { + return NULL; + } + + // Is this the type we wanted ? + const char* cname = name.c_str(); + SkFlattenable::Type baseType; + if (!SkFlattenable::NameToType(cname, &baseType) || (baseType != type)) { + return NULL; + } + + SkFlattenable::Factory factory = SkFlattenable::NameToFactory(cname); + if (NULL == factory) { + return NULL; // writer failed to give us the flattenable + } + + // if we get here, factory may still be null, but if that is the case, the + // failure was ours, not the writer. + SkFlattenable* obj = NULL; + uint32_t sizeRecorded = this->readUInt(); + if (factory) { + uint32_t offset = fReader.offset(); + obj = (*factory)(*this); + // check that we read the amount we expected + uint32_t sizeRead = fReader.offset() - offset; + fError = fError || (sizeRecorded != sizeRead); + if (fError) { + // we could try to fix up the offset... + delete obj; + obj = NULL; + } + } else { + // we must skip the remaining data + this->skip(sizeRecorded); + SkASSERT(false); + } + return obj; +} diff --git a/src/core/SkValidatingReadBuffer.h b/src/core/SkValidatingReadBuffer.h new file mode 100644 index 0000000..c854b0a --- /dev/null +++ b/src/core/SkValidatingReadBuffer.h @@ -0,0 +1,80 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkValidatingReadBuffer_DEFINED +#define SkValidatingReadBuffer_DEFINED + +#include "SkRefCnt.h" +#include "SkBitmapHeap.h" +#include "SkFlattenableBuffers.h" +#include "SkPath.h" +#include "SkPicture.h" +#include "SkReader32.h" + +class SkBitmap; + +class SkValidatingReadBuffer : public SkFlattenableReadBuffer { +public: + SkValidatingReadBuffer(const void* data, size_t size); + virtual ~SkValidatingReadBuffer(); + + const void* skip(size_t size); + + // primitives + virtual bool readBool() SK_OVERRIDE; + virtual SkColor readColor() SK_OVERRIDE; + virtual SkFixed readFixed() SK_OVERRIDE; + virtual int32_t readInt() SK_OVERRIDE; + virtual SkScalar readScalar() SK_OVERRIDE; + virtual uint32_t readUInt() SK_OVERRIDE; + virtual int32_t read32() SK_OVERRIDE; + + // strings -- the caller is responsible for freeing the string contents + virtual void readString(SkString* string) SK_OVERRIDE; + virtual void* readEncodedString(size_t* length, SkPaint::TextEncoding encoding) SK_OVERRIDE; + + // common data structures + virtual SkFlattenable* readFlattenable(SkFlattenable::Type type) SK_OVERRIDE; + virtual void readPoint(SkPoint* point) SK_OVERRIDE; + virtual void readMatrix(SkMatrix* matrix) SK_OVERRIDE; + virtual void readIRect(SkIRect* rect) SK_OVERRIDE; + virtual void readRect(SkRect* rect) SK_OVERRIDE; + virtual void readRegion(SkRegion* region) SK_OVERRIDE; + virtual void readPath(SkPath* path) SK_OVERRIDE; + + // binary data and arrays + virtual uint32_t readByteArray(void* value) SK_OVERRIDE; + virtual uint32_t readColorArray(SkColor* colors) SK_OVERRIDE; + virtual uint32_t readIntArray(int32_t* values) SK_OVERRIDE; + virtual uint32_t readPointArray(SkPoint* points) SK_OVERRIDE; + virtual uint32_t readScalarArray(SkScalar* values) SK_OVERRIDE; + + // helpers to get info about arrays and binary data + virtual uint32_t getArrayCount() SK_OVERRIDE; + + virtual void readBitmap(SkBitmap* bitmap) SK_OVERRIDE; + // TODO: Implement this (securely) when needed + virtual SkTypeface* readTypeface() SK_OVERRIDE { return NULL; } + + virtual void validate(bool isValid) SK_OVERRIDE { + fError = fError || !isValid; + } + +private: + void setMemory(const void* data, size_t size); + + static bool IsPtrAlign4(const void* ptr) { + return SkIsAlign4((uintptr_t)ptr); + } + + SkReader32 fReader; + bool fError; + + typedef SkFlattenableReadBuffer INHERITED; +}; + +#endif // SkValidatingReadBuffer_DEFINED diff --git a/src/core/SkValidationUtils.h b/src/core/SkValidationUtils.h new file mode 100644 index 0000000..683da29 --- /dev/null +++ b/src/core/SkValidationUtils.h @@ -0,0 +1,47 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkValidationUtils_DEFINED +#define SkValidationUtils_DEFINED + +#include "SkBitmap.h" +#include "SkXfermode.h" + +/** Returns true if coeff's value is in the SkXfermode::Coeff enum. + */ +static inline bool SkIsValidCoeff(SkXfermode::Coeff coeff) { + return coeff >= 0 && coeff < SkXfermode::kCoeffCount; +} + +/** Returns true if mode's value is in the SkXfermode::Mode enum. + */ +static inline bool SkIsValidMode(SkXfermode::Mode mode) { + return (mode >= 0) && (mode <= SkXfermode::kLastMode); +} + +/** Returns true if config's value is in the SkBitmap::Config enum. + */ +static inline bool SkIsValidConfig(SkBitmap::Config config) { + return (config >= 0) && (config <= static_cast(SkBitmap::kConfigCount)); +} + +/** Returns true if the rect's dimensions are between 0 and SK_MaxS32 + */ +static inline bool SkIsValidIRect(const SkIRect& rect) { + return rect.width() >= 0 && rect.height() >= 0; +} + +/** Returns true if the rect's dimensions are between 0 and SK_ScalarMax + */ +static inline bool SkIsValidRect(const SkRect& rect) { + return (rect.fLeft <= rect.fRight) && + (rect.fTop <= rect.fBottom) && + SkScalarIsFinite(rect.width()) && + SkScalarIsFinite(rect.height()); +} + +#endif diff --git a/src/effects/SkBicubicImageFilter.cpp b/src/effects/SkBicubicImageFilter.cpp index 02e706f..778df3f 100644 --- a/src/effects/SkBicubicImageFilter.cpp +++ b/src/effects/SkBicubicImageFilter.cpp @@ -45,6 +45,10 @@ SkBicubicImageFilter::SkBicubicImageFilter(SkFlattenableReadBuffer& buffer) : IN SkASSERT(readSize == 16); fScale.fWidth = buffer.readScalar(); fScale.fHeight = buffer.readScalar(); + buffer.validate(SkScalarIsFinite(fScale.fWidth) && + SkScalarIsFinite(fScale.fHeight) && + (fScale.fWidth >= 0) && + (fScale.fHeight >= 0)); } void SkBicubicImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp index abbf971..a820152 100644 --- a/src/effects/SkBlurImageFilter.cpp +++ b/src/effects/SkBlurImageFilter.cpp @@ -19,6 +19,10 @@ SkBlurImageFilter::SkBlurImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { fSigma.fWidth = buffer.readScalar(); fSigma.fHeight = buffer.readScalar(); + buffer.validate(SkScalarIsFinite(fSigma.fWidth) && + SkScalarIsFinite(fSigma.fHeight) && + (fSigma.fWidth >= 0) && + (fSigma.fHeight >= 0)); } SkBlurImageFilter::SkBlurImageFilter(SkScalar sigmaX, diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp index 66ddb02..d53e20c 100644 --- a/src/effects/SkColorFilters.cpp +++ b/src/effects/SkColorFilters.cpp @@ -13,6 +13,7 @@ #include "SkFlattenableBuffers.h" #include "SkUtils.h" #include "SkString.h" +#include "SkValidationUtils.h" #define ILLEGAL_XFERMODE_MODE ((SkXfermode::Mode)-1) @@ -101,6 +102,7 @@ protected: fColor = buffer.readColor(); fMode = (SkXfermode::Mode)buffer.readUInt(); this->updateCache(); + buffer.validate(SkIsValidMode(fMode)); } private: diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp index 1e3c779..f7b283e 100644 --- a/src/effects/SkColorMatrixFilter.cpp +++ b/src/effects/SkColorMatrixFilter.cpp @@ -310,6 +310,9 @@ SkColorMatrixFilter::SkColorMatrixFilter(SkFlattenableReadBuffer& buffer) SkASSERT(buffer.getArrayCount() == 20); buffer.readScalarArray(fMatrix.fMat); this->initState(fMatrix.fMat); + for (int i = 0; i < 20; ++i) { + buffer.validate(SkScalarIsFinite(fMatrix.fMat[i])); + } } bool SkColorMatrixFilter::asColorMatrix(SkScalar matrix[20]) const { diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp index ff2e837..15ac627 100644 --- a/src/effects/SkDisplacementMapEffect.cpp +++ b/src/effects/SkDisplacementMapEffect.cpp @@ -126,6 +126,20 @@ void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSe } } +bool channel_selector_type_is_valid(SkDisplacementMapEffect::ChannelSelectorType cst) { + switch (cst) { + case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: + case SkDisplacementMapEffect::kR_ChannelSelectorType: + case SkDisplacementMapEffect::kG_ChannelSelectorType: + case SkDisplacementMapEffect::kB_ChannelSelectorType: + case SkDisplacementMapEffect::kA_ChannelSelectorType: + return true; + default: + break; + } + return false; +} + } // end namespace /////////////////////////////////////////////////////////////////////////////// @@ -152,6 +166,9 @@ SkDisplacementMapEffect::SkDisplacementMapEffect(SkFlattenableReadBuffer& buffer fXChannelSelector = (SkDisplacementMapEffect::ChannelSelectorType) buffer.readInt(); fYChannelSelector = (SkDisplacementMapEffect::ChannelSelectorType) buffer.readInt(); fScale = buffer.readScalar(); + buffer.validate(channel_selector_type_is_valid(fXChannelSelector) && + channel_selector_type_is_valid(fYChannelSelector) && + SkScalarIsFinite(fScale)); } void SkDisplacementMapEffect::flatten(SkFlattenableWriteBuffer& buffer) const { diff --git a/src/effects/SkDropShadowImageFilter.cpp b/src/effects/SkDropShadowImageFilter.cpp index 75a8668..4fc29ba 100644 --- a/src/effects/SkDropShadowImageFilter.cpp +++ b/src/effects/SkDropShadowImageFilter.cpp @@ -29,6 +29,9 @@ SkDropShadowImageFilter::SkDropShadowImageFilter(SkFlattenableReadBuffer& buffer fDy = buffer.readScalar(); fSigma = buffer.readScalar(); fColor = buffer.readColor(); + buffer.validate(SkScalarIsFinite(fDx) && + SkScalarIsFinite(fDy) && + SkScalarIsFinite(fSigma)); } void SkDropShadowImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp index 4f05d25..dd23532 100644 --- a/src/effects/SkLightingImageFilter.cpp +++ b/src/effects/SkLightingImageFilter.cpp @@ -248,6 +248,9 @@ SkPoint3 readPoint3(SkFlattenableReadBuffer& buffer) { point.fX = buffer.readScalar(); point.fY = buffer.readScalar(); point.fZ = buffer.readScalar(); + buffer.validate(SkScalarIsFinite(point.fX) && + SkScalarIsFinite(point.fY) && + SkScalarIsFinite(point.fZ)); return point; }; @@ -732,6 +735,10 @@ public: fCosInnerConeAngle = buffer.readScalar(); fConeScale = buffer.readScalar(); fS = readPoint3(buffer); + buffer.validate(SkScalarIsFinite(fSpecularExponent) && + SkScalarIsFinite(fCosOuterConeAngle) && + SkScalarIsFinite(fCosInnerConeAngle) && + SkScalarIsFinite(fConeScale)); } protected: SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cosOuterConeAngle, SkScalar cosInnerConeAngle, SkScalar coneScale, const SkPoint3& s, const SkPoint3& color) @@ -876,13 +883,14 @@ SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular( } SkLightingImageFilter::~SkLightingImageFilter() { - fLight->unref(); + SkSafeUnref(fLight); } SkLightingImageFilter::SkLightingImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { fLight = SkLight::UnflattenLight(buffer); fSurfaceScale = buffer.readScalar(); + buffer.validate(SkScalarIsFinite(fSurfaceScale)); } void SkLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { @@ -903,6 +911,7 @@ SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkFlattenableReadBuff : INHERITED(buffer) { fKD = buffer.readScalar(); + buffer.validate(SkScalarIsFinite(fKD)); } void SkDiffuseLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { @@ -986,6 +995,8 @@ SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkFlattenableReadBu { fKS = buffer.readScalar(); fShininess = buffer.readScalar(); + buffer.validate(SkScalarIsFinite(fKS) && + SkScalarIsFinite(fShininess)); } void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { diff --git a/src/effects/SkMagnifierImageFilter.cpp b/src/effects/SkMagnifierImageFilter.cpp index 8b16516..7ac5249 100644 --- a/src/effects/SkMagnifierImageFilter.cpp +++ b/src/effects/SkMagnifierImageFilter.cpp @@ -9,6 +9,7 @@ #include "SkMagnifierImageFilter.h" #include "SkColorPriv.h" #include "SkFlattenableBuffers.h" +#include "SkValidationUtils.h" //////////////////////////////////////////////////////////////////////////////// #if SK_SUPPORT_GPU @@ -238,6 +239,8 @@ SkMagnifierImageFilter::SkMagnifierImageFilter(SkFlattenableReadBuffer& buffer) float height = buffer.readScalar(); fSrcRect = SkRect::MakeXYWH(x, y, width, height); fInset = buffer.readScalar(); + + buffer.validate(SkIsValidRect(fSrcRect) && SkScalarIsFinite(fInset)); } // FIXME: implement single-input semantics diff --git a/src/effects/SkMatrixConvolutionImageFilter.cpp b/src/effects/SkMatrixConvolutionImageFilter.cpp index c89b9dc..909facb 100644 --- a/src/effects/SkMatrixConvolutionImageFilter.cpp +++ b/src/effects/SkMatrixConvolutionImageFilter.cpp @@ -20,6 +20,18 @@ #include "SkMatrix.h" #endif +static bool tile_mode_is_valid(SkMatrixConvolutionImageFilter::TileMode tileMode) { + switch (tileMode) { + case SkMatrixConvolutionImageFilter::kClamp_TileMode: + case SkMatrixConvolutionImageFilter::kRepeat_TileMode: + case SkMatrixConvolutionImageFilter::kClampToBlack_TileMode: + return true; + default: + break; + } + return false; +} + SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter( const SkISize& kernelSize, const SkScalar* kernel, @@ -59,6 +71,9 @@ SkMatrixConvolutionImageFilter::SkMatrixConvolutionImageFilter(SkFlattenableRead fTarget.fY = buffer.readInt(); fTileMode = (TileMode) buffer.readInt(); fConvolveAlpha = buffer.readBool(); + buffer.validate(SkScalarIsFinite(fGain) && + SkScalarIsFinite(fBias) && + tile_mode_is_valid(fTileMode)); } void SkMatrixConvolutionImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { diff --git a/src/effects/SkMergeImageFilter.cpp b/src/effects/SkMergeImageFilter.cpp index 7d12ebe..a5c32ac 100755 --- a/src/effects/SkMergeImageFilter.cpp +++ b/src/effects/SkMergeImageFilter.cpp @@ -9,6 +9,7 @@ #include "SkCanvas.h" #include "SkDevice.h" #include "SkFlattenableBuffers.h" +#include "SkValidationUtils.h" /////////////////////////////////////////////////////////////////////////////// @@ -159,8 +160,12 @@ SkMergeImageFilter::SkMergeImageFilter(SkFlattenableReadBuffer& buffer) : INHERI bool hasModes = buffer.readBool(); if (hasModes) { this->initAllocModes(); - SkASSERT(buffer.getArrayCount() == countInputs() * sizeof(fModes[0])); + int nbInputs = countInputs(); + SkASSERT(buffer.getArrayCount() == nbInputs * sizeof(fModes[0])); buffer.readByteArray(fModes); + for (int i = 0; i < nbInputs; ++i) { + buffer.validate(SkIsValidMode((SkXfermode::Mode)fModes[i])); + } } else { fModes = 0; } diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp index d02e8ca..08e0ab2 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -23,6 +23,8 @@ SkMorphologyImageFilter::SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer : INHERITED(buffer) { fRadius.fWidth = buffer.readInt(); fRadius.fHeight = buffer.readInt(); + buffer.validate((fRadius.fWidth >= 0) && + (fRadius.fHeight >= 0)); } SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const CropRect* cropRect) diff --git a/src/effects/SkOffsetImageFilter.cpp b/src/effects/SkOffsetImageFilter.cpp index d684ded..fc8e71c 100644 --- a/src/effects/SkOffsetImageFilter.cpp +++ b/src/effects/SkOffsetImageFilter.cpp @@ -77,4 +77,6 @@ SkOffsetImageFilter::SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter SkOffsetImageFilter::SkOffsetImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { buffer.readPoint(&fOffset); + buffer.validate(SkScalarIsFinite(fOffset.fX) && + SkScalarIsFinite(fOffset.fY)); } diff --git a/src/effects/SkTestImageFilters.cpp b/src/effects/SkTestImageFilters.cpp index 788c33a..d0e21a3 100755 --- a/src/effects/SkTestImageFilters.cpp +++ b/src/effects/SkTestImageFilters.cpp @@ -78,4 +78,5 @@ void SkDownSampleImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { SkDownSampleImageFilter::SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { fScale = buffer.readScalar(); + buffer.validate(SkScalarIsFinite(fScale)); } diff --git a/src/effects/SkTileImageFilter.cpp b/src/effects/SkTileImageFilter.cpp index a7374ad..8cc096c 100644 --- a/src/effects/SkTileImageFilter.cpp +++ b/src/effects/SkTileImageFilter.cpp @@ -13,6 +13,7 @@ #include "SkMatrix.h" #include "SkPaint.h" #include "SkShader.h" +#include "SkValidationUtils.h" bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, SkBitmap* dst, SkIPoint* offset) { @@ -56,6 +57,7 @@ bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, const S SkTileImageFilter::SkTileImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { buffer.readRect(&fSrcRect); buffer.readRect(&fDstRect); + buffer.validate(SkIsValidRect(fSrcRect) && SkIsValidRect(fDstRect)); } void SkTileImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp index 619e3fd..789c3ed 100644 --- a/src/pipe/SkGPipeRead.cpp +++ b/src/pipe/SkGPipeRead.cpp @@ -28,20 +28,20 @@ #include "SkTypeface.h" #include "SkXfermode.h" -static SkEffectType paintflat_to_effecttype(PaintFlats pf) { +static SkFlattenable::Type paintflat_to_flattype(PaintFlats pf) { static const uint8_t gEffectTypesInPaintFlatsOrder[] = { - kColorFilter_SkEffectType, - kDrawLooper_SkEffectType, - kImageFilter_SkEffectType, - kMaskFilter_SkEffectType, - kPathEffect_SkEffectType, - kRasterizer_SkEffectType, - kShader_SkEffectType, - kXfermode_SkEffectType, + SkFlattenable::kSkColorFilter_Type, + SkFlattenable::kSkDrawLooper_Type, + SkFlattenable::kSkImageFilter_Type, + SkFlattenable::kSkMaskFilter_Type, + SkFlattenable::kSkPathEffect_Type, + SkFlattenable::kSkRasterizer_Type, + SkFlattenable::kSkShader_Type, + SkFlattenable::kSkXfermode_Type, }; SkASSERT((size_t)pf < SK_ARRAY_COUNT(gEffectTypesInPaintFlatsOrder)); - return (SkEffectType)gEffectTypesInPaintFlatsOrder[pf]; + return (SkFlattenable::Type)gEffectTypesInPaintFlatsOrder[pf]; } static void set_paintflat(SkPaint* paint, SkFlattenable* obj, unsigned paintFlat) { @@ -122,7 +122,7 @@ public: void defFlattenable(PaintFlats pf, int index) { index--; - SkFlattenable* obj = fReader->readFlattenable(paintflat_to_effecttype(pf)); + SkFlattenable* obj = fReader->readFlattenable(paintflat_to_flattype(pf)); if (fFlatArray.count() == index) { *fFlatArray.append() = obj; } else { diff --git a/src/ports/SkGlobalInitialization_chromium.cpp b/src/ports/SkGlobalInitialization_chromium.cpp index 3dd79c0..d402c02 100644 --- a/src/ports/SkGlobalInitialization_chromium.cpp +++ b/src/ports/SkGlobalInitialization_chromium.cpp @@ -5,32 +5,116 @@ * found in the LICENSE file. */ +#include "SkTypes.h" + #include "SkBitmapProcShader.h" +#include "SkMallocPixelRef.h" +#include "SkPathEffect.h" +#include "SkPixelRef.h" +#include "SkXfermode.h" + +#include "Sk1DPathEffect.h" +#include "Sk2DPathEffect.h" +#include "SkArithmeticMode.h" +#include "SkAvoidXfermode.h" +#include "SkBicubicImageFilter.h" +#include "SkBitmapSource.h" +#include "SkBlurDrawLooper.h" #include "SkBlurImageFilter.h" #include "SkBlurMaskFilter.h" #include "SkColorFilter.h" +#include "SkColorFilterImageFilter.h" +#include "SkColorMatrixFilter.h" +#include "SkColorShader.h" +#include "SkComposeImageFilter.h" +#include "SkComposeShader.h" #include "SkCornerPathEffect.h" #include "SkDashPathEffect.h" +#include "SkDiscretePathEffect.h" +#include "SkDisplacementMapEffect.h" +#include "SkDropShadowImageFilter.h" +#include "SkEmptyShader.h" +#include "SkEmbossMaskFilter.h" +#include "SkFlattenable.h" #include "SkGradientShader.h" +#include "SkImages.h" #include "SkLayerDrawLooper.h" +#include "SkLayerRasterizer.h" +#include "SkLerpXfermode.h" +#include "SkLightingImageFilter.h" #include "SkLumaColorFilter.h" -#include "SkMallocPixelRef.h" -#include "SkXfermode.h" #include "SkMagnifierImageFilter.h" +#include "SkMatrixConvolutionImageFilter.h" +#include "SkMergeImageFilter.h" +#include "SkMorphologyImageFilter.h" +#include "SkOffsetImageFilter.h" +#include "SkOnce.h" +#include "SkPerlinNoiseShader.h" +#include "SkPixelXorXfermode.h" +#include "SkRectShaderImageFilter.h" +#include "SkStippleMaskFilter.h" +#include "SkTableColorFilter.h" +#include "SkTestImageFilters.h" +#include "SkTileImageFilter.h" +#include "SkXfermodeImageFilter.h" -void SkFlattenable::InitializeFlattenables() { - +static void InitializeFlattenables(int*) { + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAvoidXfermode) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBicubicImageFilter) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapProcShader) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapSource) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurDrawLooper) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBlurImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkColorMatrixFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkColorShader) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposePathEffect) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeShader) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkCornerPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDashPathEffect) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDilateImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiscretePathEffect) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDisplacementMapEffect) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDropShadowImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkEmbossMaskFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkEmptyShader) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkErodeImageFilter) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerDrawLooper) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLayerRasterizer) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLerpXfermode) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaColorFilter) - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMallocPixelRef) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Sk2DPathEffect) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPixelXorXfermode) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRectShaderImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkStippleMaskFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSumPathEffect) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTileImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkXfermodeImageFilter) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMagnifierImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMatrixConvolutionImageFilter) + + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOffsetImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMergeImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkColorFilterImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDownSampleImageFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkMallocPixelRef) + SkArithmeticMode::InitializeFlattenables(); SkBlurMaskFilter::InitializeFlattenables(); SkColorFilter::InitializeFlattenables(); SkGradientShader::InitializeFlattenables(); + SkImages::InitializeFlattenables(); + SkLightingImageFilter::InitializeFlattenables(); + SkTableColorFilter::InitializeFlattenables(); SkXfermode::InitializeFlattenables(); } + +void SkFlattenable::InitializeFlattenablesIfNeeded() { + int dummy; + SK_DECLARE_STATIC_ONCE(once); + SkOnce(&once, InitializeFlattenables, &dummy); +} diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp index 1c22f23..d402c02 100644 --- a/src/ports/SkGlobalInitialization_default.cpp +++ b/src/ports/SkGlobalInitialization_default.cpp @@ -15,7 +15,6 @@ #include "Sk1DPathEffect.h" #include "Sk2DPathEffect.h" -#include "SkAnnotation.h" #include "SkArithmeticMode.h" #include "SkAvoidXfermode.h" #include "SkBicubicImageFilter.h" @@ -31,7 +30,6 @@ #include "SkComposeShader.h" #include "SkCornerPathEffect.h" #include "SkDashPathEffect.h" -#include "SkData.h" #include "SkDiscretePathEffect.h" #include "SkDisplacementMapEffect.h" #include "SkDropShadowImageFilter.h" @@ -50,6 +48,7 @@ #include "SkMergeImageFilter.h" #include "SkMorphologyImageFilter.h" #include "SkOffsetImageFilter.h" +#include "SkOnce.h" #include "SkPerlinNoiseShader.h" #include "SkPixelXorXfermode.h" #include "SkRectShaderImageFilter.h" @@ -59,8 +58,7 @@ #include "SkTileImageFilter.h" #include "SkXfermodeImageFilter.h" -void SkFlattenable::InitializeFlattenables() { - +static void InitializeFlattenables(int*) { SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkAvoidXfermode) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBicubicImageFilter) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkBitmapProcShader) @@ -114,3 +112,9 @@ void SkFlattenable::InitializeFlattenables() { SkTableColorFilter::InitializeFlattenables(); SkXfermode::InitializeFlattenables(); } + +void SkFlattenable::InitializeFlattenablesIfNeeded() { + int dummy; + SK_DECLARE_STATIC_ONCE(once); + SkOnce(&once, InitializeFlattenables, &dummy); +} -- 2.7.4