diff options
author | Cary Clark <caryclark@skia.org> | 2017-03-21 10:30:50 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-03-21 15:18:11 +0000 |
commit | 28da2837040cd116dd2d854dd3268723ca219f11 (patch) | |
tree | 9964e5452b2af80dfe6bf6275a6283395f798d5f /src/pathops/SkOpSegment.cpp | |
parent | 90960eb1face12f7855c98db0e4af11c03377829 (diff) |
fix fuzz
corrupted intersection point lists
can loop forever. Add a safety
hatch to abort after a large number
of iterations.
TBR=kjlubick@google.com
BUG=700679
Change-Id: Ifd4b180b47ba3bbde38ade0bb13b16b8d645c1cb
Reviewed-on: https://skia-review.googlesource.com/9967
Reviewed-by: Cary Clark <caryclark@skia.org>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Cary Clark <caryclark@google.com>
Diffstat (limited to 'src/pathops/SkOpSegment.cpp')
-rw-r--r-- | src/pathops/SkOpSegment.cpp | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp index 58c71af437..5502688615 100644 --- a/src/pathops/SkOpSegment.cpp +++ b/src/pathops/SkOpSegment.cpp @@ -1301,7 +1301,8 @@ checkNextSpan: } // adjacent spans may have points close by -bool SkOpSegment::spansNearby(const SkOpSpanBase* refSpan, const SkOpSpanBase* checkSpan) const { +bool SkOpSegment::spansNearby(const SkOpSpanBase* refSpan, const SkOpSpanBase* checkSpan, + bool* found) const { const SkOpPtT* refHead = refSpan->ptT(); const SkOpPtT* checkHead = checkSpan->ptT(); // if the first pt pair from adjacent spans are far apart, assume that all are far enough apart @@ -1318,7 +1319,8 @@ bool SkOpSegment::spansNearby(const SkOpSpanBase* refSpan, const SkOpSpanBase* c dBugRef = dBugRef->next(); } while (dBugRef != refHead); #endif - return false; + *found = false; + return true; } // check only unique points SkScalar distSqBest = SK_ScalarMax; @@ -1337,6 +1339,7 @@ bool SkOpSegment::spansNearby(const SkOpSpanBase* refSpan, const SkOpSpanBase* c } const SkOpPtT* check = checkHead; const SkOpSegment* refSeg = ref->segment(); + int escapeHatch = 100000; // defend against infinite loops do { if (check->deleted()) { continue; @@ -1354,18 +1357,22 @@ bool SkOpSegment::spansNearby(const SkOpSpanBase* refSpan, const SkOpSpanBase* c refBest = ref; checkBest = check; } + if (--escapeHatch <= 0) { + return false; + } } while ((check = check->next()) != checkHead); -nextRef: + nextRef: ; } while ((ref = ref->next()) != refHead); doneCheckingDistance: - return checkBest && refBest->segment()->match(refBest, checkBest->segment(), checkBest->fT, + *found = checkBest && refBest->segment()->match(refBest, checkBest->segment(), checkBest->fT, checkBest->fPt); + return true; } // Please keep this function in sync with debugMoveNearby() // Move nearby t values and pts so they all hang off the same span. Alignment happens later. -void SkOpSegment::moveNearby() { +bool SkOpSegment::moveNearby() { debugValidate(); // release undeleted spans pointing to this seg that are linked to the primary span SkOpSpanBase* spanBase = &fHead; @@ -1379,7 +1386,7 @@ void SkOpSegment::moveNearby() { if (test->final()) { if (spanBase == &fHead) { this->clearAll(); - return; + return true; } spanBase->upCast()->release(ptT); } else if (test->prev()) { @@ -1395,13 +1402,17 @@ void SkOpSegment::moveNearby() { spanBase = &fHead; do { // iterate through all spans associated with start SkOpSpanBase* test = spanBase->upCast()->next(); - if (this->spansNearby(spanBase, test)) { + bool found; + if (!this->spansNearby(spanBase, test, &found)) { + return false; + } + if (found) { if (test->final()) { if (spanBase->prev()) { test->merge(spanBase->upCast()); } else { this->clearAll(); - return; + return true; } } else { spanBase->merge(test->upCast()); @@ -1410,6 +1421,7 @@ void SkOpSegment::moveNearby() { spanBase = test; } while (!spanBase->final()); debugValidate(); + return true; } bool SkOpSegment::operand() const { |