aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar caryclark <caryclark@google.com>2016-02-24 09:03:07 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-02-24 09:03:07 -0800
commitd78c088b6136590371fddd4cab67bfb4bf692fd3 (patch)
tree7b928823d239ea0c5089b9696af635f694873188 /src
parentd9381acb0efc84e5b54627de554c6cefc43ca97d (diff)
fix path ops fuzz bug
If one path is empty and the other has extreme values, the intermediate coincident paths cannot be resolved, but triggers an assert that a data structure unexpectedly has zero-length. Tunnel this failure back up to the top and return that the entire path op fails. A future optimization could detect the empty path and avoid this, allowing the op to succeed -- not sure that it's worth the additional logic though. TBR=reed@google.com BUG=535151 GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1730293002 Review URL: https://codereview.chromium.org/1730293002
Diffstat (limited to 'src')
-rw-r--r--src/pathops/SkOpContour.h4
-rw-r--r--src/pathops/SkOpSegment.cpp7
-rw-r--r--src/pathops/SkOpSegment.h2
-rw-r--r--src/pathops/SkPathOpsCommon.cpp11
4 files changed, 17 insertions, 7 deletions
diff --git a/src/pathops/SkOpContour.h b/src/pathops/SkOpContour.h
index d0e09a3a70..b9f0b85af5 100644
--- a/src/pathops/SkOpContour.h
+++ b/src/pathops/SkOpContour.h
@@ -269,7 +269,9 @@ public:
SkASSERT(fCount > 0);
SkOpSegment* segment = &fHead;
do {
- segment->moveMultiples();
+ if (!segment->moveMultiples()) {
+ return false;
+ }
} while ((segment = segment->next()));
return true;
}
diff --git a/src/pathops/SkOpSegment.cpp b/src/pathops/SkOpSegment.cpp
index 67f172e58a..2ba7d79b30 100644
--- a/src/pathops/SkOpSegment.cpp
+++ b/src/pathops/SkOpSegment.cpp
@@ -1297,12 +1297,14 @@ bool SkOpSegment::missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc
}
// if a span has more than one intersection, merge the other segments' span as needed
-void SkOpSegment::moveMultiples() {
+bool SkOpSegment::moveMultiples() {
debugValidate();
SkOpSpanBase* test = &fHead;
do {
int addCount = test->spanAddsCount();
- SkASSERT(addCount >= 1);
+ if (addCount < 1) {
+ return false;
+ }
if (addCount == 1) {
continue;
}
@@ -1393,6 +1395,7 @@ checkNextSpan:
;
} while ((test = test->final() ? nullptr : test->upCast()->next()));
debugValidate();
+ return true;
}
// Move nearby t values and pts so they all hang off the same span. Alignment happens later.
diff --git a/src/pathops/SkOpSegment.h b/src/pathops/SkOpSegment.h
index 06649aa2be..40a50c5fe0 100644
--- a/src/pathops/SkOpSegment.h
+++ b/src/pathops/SkOpSegment.h
@@ -271,7 +271,7 @@ public:
bool markWinding(SkOpSpan* , int winding, int oppWinding);
bool match(const SkOpPtT* span, const SkOpSegment* parent, double t, const SkPoint& pt) const;
bool missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc* allocator);
- void moveMultiples();
+ bool moveMultiples();
void moveNearby();
SkOpSegment* next() const {
diff --git a/src/pathops/SkPathOpsCommon.cpp b/src/pathops/SkPathOpsCommon.cpp
index 0060db2f30..829f8a50d5 100644
--- a/src/pathops/SkPathOpsCommon.cpp
+++ b/src/pathops/SkPathOpsCommon.cpp
@@ -425,11 +425,14 @@ static bool missingCoincidence(SkOpContourHead* contourList,
return result;
}
-static void moveMultiples(SkOpContourHead* contourList) {
+static bool moveMultiples(SkOpContourHead* contourList) {
SkOpContour* contour = contourList;
do {
- contour->moveMultiples();
+ if (!contour->moveMultiples()) {
+ return false;
+ }
} while ((contour = contour->next()));
+ return true;
}
static void moveNearby(SkOpContourHead* contourList) {
@@ -451,7 +454,9 @@ bool HandleCoincidence(SkOpContourHead* contourList, SkOpCoincidence* coincidenc
SkOpGlobalState* globalState = contourList->globalState();
// combine t values when multiple intersections occur on some segments but not others
DEBUG_COINCIDENCE_HEALTH(contourList, "start");
- moveMultiples(contourList);
+ if (!moveMultiples(contourList)) {
+ return false;
+ }
DEBUG_COINCIDENCE_HEALTH(contourList, "moveMultiples");
findCollapsed(contourList);
DEBUG_COINCIDENCE_HEALTH(contourList, "findCollapsed");