diff options
-rw-r--r-- | src/pathops/SkOpSegment.cpp | 18 | ||||
-rw-r--r-- | src/pathops/SkOpSegment.h | 2 | ||||
-rw-r--r-- | tests/PathOpsOpTest.cpp | 27 |
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), |