diff options
author | Cary Clark <caryclark@skia.org> | 2018-03-09 07:38:47 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-03-09 14:54:30 +0000 |
commit | 74b429086122e19e82fe090fc999120ed48d3532 (patch) | |
tree | 0e9ee4be41ba35dafbd82c42ac7d40213de81250 /src | |
parent | b537879c7214efd87840c9a7267ab3b3facda873 (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.cpp | 29 | ||||
-rw-r--r-- | src/pathops/SkOpCoincidence.cpp | 3 | ||||
-rw-r--r-- | src/pathops/SkOpEdgeBuilder.cpp | 4 | ||||
-rw-r--r-- | src/pathops/SkOpSpan.cpp | 9 | ||||
-rw-r--r-- | src/pathops/SkOpSpan.h | 1 | ||||
-rw-r--r-- | src/pathops/SkPathOpsCubic.cpp | 3 | ||||
-rw-r--r-- | src/pathops/SkPathOpsOp.cpp | 3 | ||||
-rw-r--r-- | src/pathops/SkPathOpsTSect.h | 17 |
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 |