aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/pathops/SkOpSegment.cpp18
-rw-r--r--src/pathops/SkOpSegment.h2
-rw-r--r--tests/PathOpsOpTest.cpp27
3 files changed, 42 insertions, 5 deletions
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp
index 2dda11a383..95046e2fd2 100644
--- a/src/pathops/SkOpSegment.cpp
+++ b/src/pathops/SkOpSegment.cpp
@@ -1211,7 +1211,7 @@ void SkOpSegment::bumpCoincidentBlind(bool binary, int index, int endIndex) {
} while (++index < endIndex);
}
-void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* indexPtr,
+bool SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* indexPtr,
SkTArray<SkPoint, true>* outsideTs) {
int index = *indexPtr;
int oWindValue = oTest.fWindValue;
@@ -1223,12 +1223,16 @@ void SkOpSegment::bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* in
SkOpSpan* end = test;
const SkPoint& oStartPt = oTest.fPt;
do {
+ if (end->fDone && !end->fTiny && !end->fSmall) { // extremely large paths trigger this
+ return false;
+ }
if (bumpSpan(end, oWindValue, oOppValue)) {
TrackOutside(outsideTs, oStartPt);
}
end = &fTs[++index];
} while ((end->fPt == test->fPt || precisely_equal(end->fT, test->fT)) && end->fT < 1);
*indexPtr = index;
+ return true;
}
void SkOpSegment::bumpCoincidentOBlind(int index, int endIndex) {
@@ -1329,10 +1333,14 @@ bool SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d
} while (*oTestPt == other->fTs[oIndex].fPt);
} else {
if (!binary || test->fWindValue + oTest->fOppValue >= 0) {
- bumpCoincidentThis(*oTest, binary, &index, &outsidePts);
+ if (!bumpCoincidentThis(*oTest, binary, &index, &outsidePts)) {
+ return false;
+ }
other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts);
} else {
- other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts);
+ if (!other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts)) {
+ return false;
+ }
bumpCoincidentOther(*oTest, &index, &outsidePts);
}
}
@@ -1396,7 +1404,9 @@ bool SkOpSegment::addTCoincident(const SkPoint& startPt, const SkPoint& endPt, d
if (!binary || test->fWindValue + oTest->fOppValue >= 0) {
other->bumpCoincidentOther(*test, &oIndex, &oOutsidePts);
} else {
- other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts);
+ if (!other->bumpCoincidentThis(*test, binary, &oIndex, &oOutsidePts)) {
+ return false;
+ }
}
oTest = &other->fTs[oIndex];
oTestPt = &oTest->fPt;
diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h
index 24d08bd814..4c35ac7e7e 100644
--- a/src/pathops/SkOpSegment.h
+++ b/src/pathops/SkOpSegment.h
@@ -407,7 +407,7 @@ private:
const SkOpSegment* other2, SkOpSpan* oSpan, SkTDArray<AlignedSpan>* );
bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) const;
void bumpCoincidentBlind(bool binary, int index, int last);
- void bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index,
+ bool bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index,
SkTArray<SkPoint, true>* outsideTs);
void bumpCoincidentOBlind(int index, int last);
void bumpCoincidentOther(const SkOpSpan& oTest, int* index,
diff --git a/tests/PathOpsOpTest.cpp b/tests/PathOpsOpTest.cpp
index 4977b28c30..f0fea767fe 100644
--- a/tests/PathOpsOpTest.cpp
+++ b/tests/PathOpsOpTest.cpp
@@ -3899,7 +3899,34 @@ path.close();
testPathFailOp(reporter, path1, path2, (SkPathOp) 2, filename);
}
+static void fuzz714(skiatest::Reporter* reporter, const char* filename) {
+ SkPath path;
+ path.setFillType((SkPath::FillType) 1);
+path.moveTo(SkBits2Float(0x430c0000), SkBits2Float(0x42200000));
+path.lineTo(SkBits2Float(0x43480000), SkBits2Float(0x43520000));
+path.lineTo(SkBits2Float(0x42200000), SkBits2Float(0x42c80000));
+path.lineTo(SkBits2Float(0x64969569), SkBits2Float(0x42c80000));
+path.lineTo(SkBits2Float(0x64969569), SkBits2Float(0x43520000));
+path.lineTo(SkBits2Float(0x430c0000), SkBits2Float(0x42200000));
+path.close();
+
+ SkPath path1(path);
+ path.reset();
+ path.setFillType((SkPath::FillType) 0);
+path.moveTo(SkBits2Float(0x43200000), SkBits2Float(0x42700000));
+path.lineTo(SkBits2Float(0x435c0000), SkBits2Float(0x43660000));
+path.lineTo(SkBits2Float(0x42700000), SkBits2Float(0x42f00000));
+path.lineTo(SkBits2Float(0x64969569), SkBits2Float(0x42f00000));
+path.lineTo(SkBits2Float(0x64969569), SkBits2Float(0x43660000));
+path.lineTo(SkBits2Float(0x43200000), SkBits2Float(0x42700000));
+path.close();
+
+ SkPath path2(path);
+ testPathFailOp(reporter, path1, path2, (SkPathOp) 2, filename);
+}
+
static struct TestDesc failTests[] = {
+ TEST(fuzz714),
TEST(fuzz487a),
TEST(fuzz487b),
TEST(fuzz433b),