diff options
author | caryclark <caryclark@google.com> | 2014-10-03 05:36:27 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-03 05:36:27 -0700 |
commit | d751ac01a3a887bc2d71146fc7353a5f33730043 (patch) | |
tree | 714cb383cc2947e4e5f15306c49f7163fd5742d4 | |
parent | d012877a6d30ae768f9ccf3239ba09d730cbb6a5 (diff) |
abort op early if path isn't parseable
TBR=
BUG=419649
Review URL: https://codereview.chromium.org/623943002
-rw-r--r-- | src/pathops/SkOpEdgeBuilder.h | 9 | ||||
-rw-r--r-- | src/pathops/SkPathOpsOp.cpp | 3 | ||||
-rw-r--r-- | tests/PathOpsOpTest.cpp | 23 |
3 files changed, 30 insertions, 5 deletions
diff --git a/src/pathops/SkOpEdgeBuilder.h b/src/pathops/SkOpEdgeBuilder.h index df0795b0c8..fd0744572d 100644 --- a/src/pathops/SkOpEdgeBuilder.h +++ b/src/pathops/SkOpEdgeBuilder.h @@ -27,6 +27,8 @@ public: init(); } + void addOperand(const SkPath& path); + void complete() { if (fCurrentContour && fCurrentContour->segments().count()) { fCurrentContour->complete(); @@ -34,13 +36,10 @@ public: } } - SkPathOpsMask xorMask() const { - return fXorMask[fOperand]; - } - - void addOperand(const SkPath& path); bool finish(); void init(); + bool unparseable() const { return fUnparseable; } + SkPathOpsMask xorMask() const { return fXorMask[fOperand]; } private: void closeContour(const SkPoint& curveEnd, const SkPoint& curveStart); diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp index 4c6923abb6..72efb89d10 100644 --- a/src/pathops/SkPathOpsOp.cpp +++ b/src/pathops/SkPathOpsOp.cpp @@ -270,6 +270,9 @@ bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { SkTArray<SkOpContour> contours; // FIXME: add self-intersecting cubics' T values to segment SkOpEdgeBuilder builder(*minuend, contours); + if (builder.unparseable()) { + return false; + } const int xorMask = builder.xorMask(); builder.addOperand(*subtrahend); if (!builder.finish()) { diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp index f0fea767fe..00c02e8a3d 100644 --- a/tests/PathOpsOpTest.cpp +++ b/tests/PathOpsOpTest.cpp @@ -3925,7 +3925,30 @@ path.close(); testPathFailOp(reporter, path1, path2, (SkPathOp) 2, filename); } +static void fuzz1(skiatest::Reporter* reporter, const char* filename) { + SkPath path; + path.setFillType((SkPath::FillType) 0); +path.moveTo(SkBits2Float(0x7f800000), SkBits2Float(0x7f800000)); +path.quadTo(SkBits2Float(0x7f800000), SkBits2Float(0x7f800000), SkBits2Float(0x7f800000), SkBits2Float(0x7f800000)); +path.quadTo(SkBits2Float(0x7f800000), SkBits2Float(0x7f800000), SkBits2Float(0x7f800000), SkBits2Float(0x7f800000)); +path.quadTo(SkBits2Float(0xffc00000), SkBits2Float(0x7f800000), SkBits2Float(0xffc00000), SkBits2Float(0x7f800000)); +path.quadTo(SkBits2Float(0xff000001), SkBits2Float(0x7f800000), SkBits2Float(0xff000001), SkBits2Float(0x7f800000)); +path.quadTo(SkBits2Float(0xff000001), SkBits2Float(0xffc00000), SkBits2Float(0xffc00000), SkBits2Float(0xffc00000)); +path.quadTo(SkBits2Float(0xffc00000), SkBits2Float(0xff000001), SkBits2Float(0x7f800000), SkBits2Float(0xff000001)); +path.quadTo(SkBits2Float(0x7f800000), SkBits2Float(0xff000001), SkBits2Float(0x7f800000), SkBits2Float(0xffc00000)); +path.quadTo(SkBits2Float(0x7f800000), SkBits2Float(0xffc00000), SkBits2Float(0x7f800000), SkBits2Float(0x7f800000)); +path.close(); + + SkPath path1(path); + path.reset(); + path.setFillType((SkPath::FillType) 0); + + SkPath path2(path); + testPathFailOp(reporter, path1, path2, (SkPathOp) 2, filename); +} + static struct TestDesc failTests[] = { + TEST(fuzz1), TEST(fuzz714), TEST(fuzz487a), TEST(fuzz487b), |