Harden degenerate gradient context handling

Certain inputs produce degenerate values at context creation time only.

Detect such cases after context creation, and abort drawing by returning
a null shader context instead.

BUG=skia:5821
R=reed@google.com,brianosman@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2397473003

Review-Url: https://codereview.chromium.org/2397473003
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h
index 1910384..f565a53 100644
--- a/include/core/SkMatrix.h
+++ b/include/core/SkMatrix.h
@@ -736,6 +736,11 @@
         this->setTypeMask(mask | kRectStaysRect_Mask);
     }
     
+    /**
+     *  Are all elements of the matrix finite?
+     */
+    bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }
+
 private:
     enum {
         /** Set if the matrix will map a rectangle to another rectangle. This
@@ -768,10 +773,6 @@
     SkScalar         fMat[9];
     mutable uint32_t fTypeMask;
 
-    /** Are all elements of the matrix finite?
-     */
-    bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }
-
     static void ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp);
 
     uint8_t computeTypeMask() const;
diff --git a/src/effects/gradients/Sk4fGradientBase.cpp b/src/effects/gradients/Sk4fGradientBase.cpp
index a221368..8994db3 100644
--- a/src/effects/gradients/Sk4fGradientBase.cpp
+++ b/src/effects/gradients/Sk4fGradientBase.cpp
@@ -158,6 +158,11 @@
         || shader.fColorsAreOpaque;
 }
 
+bool SkGradientShaderBase::
+GradientShaderBase4fContext::isValid() const {
+    return fDstToPos.isFinite();
+}
+
 void SkGradientShaderBase::
 GradientShaderBase4fContext::buildIntervals(const SkGradientShaderBase& shader,
                                             const ContextRec& rec, bool reverse) {
diff --git a/src/effects/gradients/Sk4fGradientBase.h b/src/effects/gradients/Sk4fGradientBase.h
index 17f9563..fd6d656 100644
--- a/src/effects/gradients/Sk4fGradientBase.h
+++ b/src/effects/gradients/Sk4fGradientBase.h
@@ -28,6 +28,8 @@
     void shadeSpan(int x, int y, SkPMColor dst[], int count) override;
     void shadeSpan4f(int x, int y, SkPM4f dst[], int count) override;
 
+    bool isValid() const;
+
 protected:
     struct Interval {
         Interval(const Sk4f& c0, SkScalar p0,
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index 4ee8203..17302d9 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -397,6 +397,10 @@
     }
 }
 
+bool SkGradientShaderBase::GradientShaderBaseContext::isValid() const {
+    return fDstToIndex.isFinite();
+}
+
 SkGradientShaderBase::GradientShaderCache::GradientShaderCache(
         U8CPU alpha, bool dither, const SkGradientShaderBase& shader)
     : fCacheAlpha(alpha)
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index f850994..61a4418 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -115,7 +115,6 @@
         SkAutoMalloc fDynamicStorage;
     };
 
-public:
     SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
     virtual ~SkGradientShaderBase();
 
@@ -159,6 +158,8 @@
 
         uint32_t getFlags() const override { return fFlags; }
 
+        bool isValid() const;
+
     protected:
         SkMatrix    fDstToIndex;
         SkMatrix::MapXYProc fDstToIndexProc;
@@ -233,6 +234,16 @@
                                    SkColor* colorSrc, Rec* recSrc,
                                    int count);
 
+    template <typename T, typename... Args>
+    static Context* CheckedCreateContext(void* storage, Args&&... args) {
+        auto* ctx = new (storage) T(std::forward<Args>(args)...);
+        if (!ctx->isValid()) {
+            ctx->~T();
+            return nullptr;
+        }
+        return ctx;
+    }
+
 private:
     enum {
         kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp
index be29540..a249ae4 100644
--- a/src/effects/gradients/SkLinearGradient.cpp
+++ b/src/effects/gradients/SkLinearGradient.cpp
@@ -82,8 +82,8 @@
 
 SkShader::Context* SkLinearGradient::onCreateContext(const ContextRec& rec, void* storage) const {
     return use_4f_context(rec, fGradFlags)
-        ? static_cast<SkShader::Context*>(new (storage) LinearGradient4fContext(*this, rec))
-        : static_cast<SkShader::Context*>(new (storage) LinearGradientContext(*this, rec));
+        ? CheckedCreateContext<LinearGradient4fContext>(storage, *this, rec)
+        : CheckedCreateContext<  LinearGradientContext>(storage, *this, rec);
 }
 
 // This swizzles SkColor into the same component order as SkPMColor, but does not actually
diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp
index b0ef205..18ef376 100644
--- a/src/effects/gradients/SkRadialGradient.cpp
+++ b/src/effects/gradients/SkRadialGradient.cpp
@@ -44,7 +44,7 @@
 }
 
 SkShader::Context* SkRadialGradient::onCreateContext(const ContextRec& rec, void* storage) const {
-    return new (storage) RadialGradientContext(*this, rec);
+    return CheckedCreateContext<RadialGradientContext>(storage, *this, rec);
 }
 
 SkRadialGradient::RadialGradientContext::RadialGradientContext(
diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp
index d99d979..d1fe269 100644
--- a/src/effects/gradients/SkSweepGradient.cpp
+++ b/src/effects/gradients/SkSweepGradient.cpp
@@ -50,7 +50,7 @@
 }
 
 SkShader::Context* SkSweepGradient::onCreateContext(const ContextRec& rec, void* storage) const {
-    return new (storage) SweepGradientContext(*this, rec);
+    return CheckedCreateContext<SweepGradientContext>(storage, *this, rec);
 }
 
 SkSweepGradient::SweepGradientContext::SweepGradientContext(
diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp
index fd48a62..599fd4c 100644
--- a/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -216,7 +216,7 @@
 
 SkShader::Context* SkTwoPointConicalGradient::onCreateContext(const ContextRec& rec,
                                                               void* storage) const {
-    return new (storage) TwoPointConicalGradientContext(*this, rec);
+    return CheckedCreateContext<TwoPointConicalGradientContext>(storage, *this, rec);
 }
 
 SkTwoPointConicalGradient::TwoPointConicalGradientContext::TwoPointConicalGradientContext(