aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2014-10-03 05:36:27 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-03 05:36:27 -0700
commitd751ac01a3a887bc2d71146fc7353a5f33730043 (patch)
tree714cb383cc2947e4e5f15306c49f7163fd5742d4
parentd012877a6d30ae768f9ccf3239ba09d730cbb6a5 (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.h9
-rw-r--r--src/pathops/SkPathOpsOp.cpp3
-rw-r--r--tests/PathOpsOpTest.cpp23
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),