aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pathops/SkOpSegment.cpp
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@skia.org>2017-03-21 10:30:50 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-03-21 15:18:11 +0000
commit28da2837040cd116dd2d854dd3268723ca219f11 (patch)
tree9964e5452b2af80dfe6bf6275a6283395f798d5f /src/pathops/SkOpSegment.cpp
parent90960eb1face12f7855c98db0e4af11c03377829 (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.cpp28
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 {