aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@skia.org>2018-03-09 07:38:47 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-09 14:54:30 +0000
commit74b429086122e19e82fe090fc999120ed48d3532 (patch)
tree0e9ee4be41ba35dafbd82c42ac7d40213de81250 /src
parentb537879c7214efd87840c9a7267ab3b3facda873 (diff)
some fuzzer fixes
should fix three or four of the PathOp asserts triggered by the fuzzer tool. R=kjlubick@google.com Bug: skia: Change-Id: I470895addf1e922da6a7c41d44d54eca92e68fb6 Reviewed-on: https://skia-review.googlesource.com/113163 Reviewed-by: Kevin Lubick <kjlubick@google.com> Commit-Queue: Cary Clark <caryclark@skia.org>
Diffstat (limited to 'src')
-rw-r--r--src/pathops/SkIntersections.cpp29
-rw-r--r--src/pathops/SkOpCoincidence.cpp3
-rw-r--r--src/pathops/SkOpEdgeBuilder.cpp4
-rw-r--r--src/pathops/SkOpSpan.cpp9
-rw-r--r--src/pathops/SkOpSpan.h1
-rw-r--r--src/pathops/SkPathOpsCubic.cpp3
-rw-r--r--src/pathops/SkPathOpsOp.cpp3
-rw-r--r--src/pathops/SkPathOpsTSect.h17
8 files changed, 38 insertions, 31 deletions
diff --git a/src/pathops/SkIntersections.cpp b/src/pathops/SkIntersections.cpp
index f17e5dbc38..541cfb0ab6 100644
--- a/src/pathops/SkIntersections.cpp
+++ b/src/pathops/SkIntersections.cpp
@@ -45,23 +45,32 @@ int SkIntersections::insert(double one, double two, const SkDPoint& pt) {
return -1;
}
if (more_roughly_equal(oldOne, one) && more_roughly_equal(oldTwo, two)) {
- if ((precisely_zero(one) && !precisely_zero(oldOne))
- || (precisely_equal(one, 1) && !precisely_equal(oldOne, 1))
- || (precisely_zero(two) && !precisely_zero(oldTwo))
- || (precisely_equal(two, 1) && !precisely_equal(oldTwo, 1))) {
- SkASSERT(one >= 0 && one <= 1);
- SkASSERT(two >= 0 && two <= 1);
- fT[0][index] = one;
- fT[1][index] = two;
- fPt[index] = pt;
+ if ((!precisely_zero(one) || precisely_zero(oldOne))
+ && (!precisely_equal(one, 1) || precisely_equal(oldOne, 1))
+ && (!precisely_zero(two) || precisely_zero(oldTwo))
+ && (!precisely_equal(two, 1) || precisely_equal(oldTwo, 1))) {
+ return -1;
}
- return -1;
+ SkASSERT(one >= 0 && one <= 1);
+ SkASSERT(two >= 0 && two <= 1);
+ // remove this and reinsert below in case replacing would make list unsorted
+ int remaining = fUsed - index - 1;
+ memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining);
+ memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining);
+ memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining);
+ int clearMask = ~((1 << index) - 1);
+ fIsCoincident[0] -= (fIsCoincident[0] >> 1) & clearMask;
+ fIsCoincident[1] -= (fIsCoincident[1] >> 1) & clearMask;
+ --fUsed;
+ break;
}
#if ONE_OFF_DEBUG
if (pt.roughlyEqual(fPt[index])) {
SkDebugf("%s t=%1.9g pts roughly equal\n", __FUNCTION__, one);
}
#endif
+ }
+ for (index = 0; index < fUsed; ++index) {
if (fT[0][index] > one) {
break;
}
diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp
index 2f9d28f9ee..8e5c6c1d4d 100644
--- a/src/pathops/SkOpCoincidence.cpp
+++ b/src/pathops/SkOpCoincidence.cpp
@@ -694,7 +694,7 @@ bool SkOpCoincidence::addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg,
SkASSERT(!cs || !cs->deleted());
SkASSERT(!os || !os->deleted());
SkASSERT(!ce || !ce->deleted());
- SkASSERT(!oe || !oe->deleted());
+ FAIL_IF(oe && oe->deleted());
const SkOpPtT* csExisting = !cs ? coinSeg->existing(coinTs, nullptr) : nullptr;
const SkOpPtT* ceExisting = !ce ? coinSeg->existing(coinTe, nullptr) : nullptr;
FAIL_IF(csExisting && csExisting == ceExisting);
@@ -723,6 +723,7 @@ bool SkOpCoincidence::addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg,
csWritable->span()->addOpp(osWritable->span());
cs = csWritable;
os = osWritable->active();
+ FAIL_IF(!os);
FAIL_IF((ce && ce->deleted()) || (oe && oe->deleted()));
}
if (!ce || !oe) {
diff --git a/src/pathops/SkOpEdgeBuilder.cpp b/src/pathops/SkOpEdgeBuilder.cpp
index cda6850701..16cbfc410c 100644
--- a/src/pathops/SkOpEdgeBuilder.cpp
+++ b/src/pathops/SkOpEdgeBuilder.cpp
@@ -323,7 +323,9 @@ bool SkOpEdgeBuilder::walk() {
}
SkPoint* curve = SkPath::kCubic_Verb == split->fVerb
? split->fPts : split->fReduced;
- SkAssertResult(can_add_curve(split->fVerb, curve));
+ if (!can_add_curve(split->fVerb, curve)) {
+ return false;
+ }
fContourBuilder.addCurve(split->fVerb, curve);
}
}
diff --git a/src/pathops/SkOpSpan.cpp b/src/pathops/SkOpSpan.cpp
index 28989d9511..f5195edb38 100644
--- a/src/pathops/SkOpSpan.cpp
+++ b/src/pathops/SkOpSpan.cpp
@@ -24,8 +24,7 @@ const SkOpPtT* SkOpPtT::active() const {
return ptT;
}
}
- SkASSERT(0); // should never return deleted
- return this;
+ return nullptr; // should never return deleted; caller must abort
}
bool SkOpPtT::contains(const SkOpPtT* check) const {
@@ -269,12 +268,6 @@ tryNextRemainder:
fSpanAdds += span->fSpanAdds;
}
-SkOpSpanBase* SkOpSpanBase::active() {
- SkOpSpanBase* result = fPrev ? fPrev->next() : upCast()->next()->prev();
- SkASSERT(this == result || fDebugDeleted);
- return result;
-}
-
// please keep in sync with debugCheckForCollapsedCoincidence()
void SkOpSpanBase::checkForCollapsedCoincidence() {
SkOpCoincidence* coins = this->globalState()->coincidence();
diff --git a/src/pathops/SkOpSpan.h b/src/pathops/SkOpSpan.h
index fea3309598..af1481e920 100644
--- a/src/pathops/SkOpSpan.h
+++ b/src/pathops/SkOpSpan.h
@@ -177,7 +177,6 @@ protected:
class SkOpSpanBase {
public:
- SkOpSpanBase* active();
void addOpp(SkOpSpanBase* opp);
void bumpSpanAdds() {
diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp
index 33229fa8ae..eb2ddb7c7d 100644
--- a/src/pathops/SkPathOpsCubic.cpp
+++ b/src/pathops/SkPathOpsCubic.cpp
@@ -35,8 +35,7 @@ double SkDCubic::binarySearch(double min, double max, double axisIntercept,
double calcPos = (&cubicAtT.fX)[xAxis];
double calcDist = calcPos - axisIntercept;
do {
- double priorT = t - step;
- SkOPASSERT(priorT >= min);
+ double priorT = std::max(min, t - step);
SkDPoint lessPt = ptAtT(priorT);
if (approximately_equal_half(lessPt.fX, cubicAtT.fX)
&& approximately_equal_half(lessPt.fY, cubicAtT.fY)) {
diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp
index 479b9a5c24..ee2b200f62 100644
--- a/src/pathops/SkPathOpsOp.cpp
+++ b/src/pathops/SkPathOpsOp.cpp
@@ -205,8 +205,7 @@ static const bool gOutInverse[kReverseDifference_SkPathOp + 1][2][2] = {
SK_DECLARE_STATIC_MUTEX(debugWorstLoop);
-SkOpGlobalState debugWorstState(nullptr, nullptr SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr)
- SkDEBUGPARAMS(nullptr));
+SkOpGlobalState debugWorstState(nullptr, nullptr SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
void ReportPathOpsDebugging() {
debugWorstState.debugLoopReport();
diff --git a/src/pathops/SkPathOpsTSect.h b/src/pathops/SkPathOpsTSect.h
index fb00d9abc9..833e735da6 100644
--- a/src/pathops/SkPathOpsTSect.h
+++ b/src/pathops/SkPathOpsTSect.h
@@ -272,7 +272,7 @@ private:
}
bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tStep, double* t,
- double* oppT);
+ double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst);
SkTSpan<TCurve, OppCurve>* boundsMax() const;
bool coincidentCheck(SkTSect<OppCurve, TCurve>* sect2);
void coincidentForce(SkTSect<OppCurve, TCurve>* sect2, double start1s, double start1e);
@@ -908,7 +908,7 @@ SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::addOne() {
template<typename TCurve, typename OppCurve>
bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect2, double tStart,
- double tStep, double* resultT, double* oppT) {
+ double tStep, double* resultT, double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst) {
SkTSpan<TCurve, OppCurve> work;
double result = work.fStartT = work.fEndT = tStart;
SkDEBUGCODE(work.fDebugSect = this);
@@ -916,7 +916,7 @@ bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect
SkDPoint oppPt;
bool flip = false;
bool contained = false;
- SkDEBUGCODE(bool down = tStep < 0);
+ bool down = tStep < 0;
const OppCurve& opp = sect2->fCurve;
do {
tStep *= 0.5;
@@ -943,7 +943,10 @@ bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect
*oppT = oppTTest;
oppPt = work.fCoinStart.perpPt();
contained = true;
- SkASSERT(down ? result > work.fStartT : result < work.fStartT);
+ if (down ? result <= work.fStartT : result >= work.fStartT) {
+ *oppFirst = nullptr; // signal caller to fail
+ return false;
+ }
result = work.fStartT;
continue;
}
@@ -1199,7 +1202,7 @@ bool SkTSect<TCurve, OppCurve>::extractCoincident(
SkTSpan<OppCurve, TCurve>* cutFirst;
if (prev && prev->fEndT == startT
&& this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &coinStart,
- &oppStartT)
+ &oppStartT, &oppFirst)
&& prev->fStartT < coinStart && coinStart < startT
&& (cutFirst = prev->oppT(oppStartT))) {
oppFirst = cutFirst;
@@ -1218,8 +1221,10 @@ bool SkTSect<TCurve, OppCurve>::extractCoincident(
}
}
} else {
+ if (!oppFirst) {
+ return false;
+ }
SkDEBUGCODE(coinStart = first->fStartT);
- FAIL_IF(!oppFirst);
SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT);
}
// FIXME: incomplete : if we're not at the end, find end of coin