fix fuzzers

Many old pathops-related fuzz failures have built up while
the codebase was under a state a flux. Now that the code
is stable, address these failures.

Most of the CL plumbs the debug global state to downstream
routines so that, if the data is not trusted (ala fuzzed)
the function can safely exit without asserting.

TBR=reed@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2426173002

Review-Url: https://chromiumcodereview.appspot.com/2426173002
diff --git a/src/pathops/SkOpCoincidence.cpp b/src/pathops/SkOpCoincidence.cpp
index aa5f5bf..d16f6f8 100755
--- a/src/pathops/SkOpCoincidence.cpp
+++ b/src/pathops/SkOpCoincidence.cpp
@@ -128,11 +128,12 @@
 // A coincident span is unordered if the pairs of points in the main and opposite curves'
 // t values do not ascend or descend. For instance, if a tightly arced quadratic is
 // coincident with another curve, it may intersect it out of order.
-bool SkCoincidentSpans::ordered() const {
+bool SkCoincidentSpans::ordered(bool* result) const {
     const SkOpSpanBase* start = this->coinPtTStart()->span();
     const SkOpSpanBase* end = this->coinPtTEnd()->span();
     const SkOpSpanBase* next = start->upCast()->next();
     if (next == end) {
+        *result = true;
         return true;
     }
     bool flipped = this->flipped();
@@ -141,21 +142,24 @@
     do {
         const SkOpPtT* opp = next->contains(oppSeg);
         if (!opp) {
-            SkASSERT(0);  // may assert if coincident span isn't fully processed
-            continue;
+            SkOPOBJASSERT(start, 0);  // may assert if coincident span isn't fully processed
+            return false;
         }
         if ((oppLastT > opp->fT) != flipped) {
-            return false;
+            *result = false;
+            return true;
         }
         oppLastT = opp->fT;
         if (next == end) {
             break;
         }
         if (!next->upCastable()) {
-            return false;
+            *result = false;
+            return true;
         }
         next = next->upCast()->next();
     } while (true);
+    *result = true;
     return true;
 }
 
@@ -234,7 +238,7 @@
     coinPtTEnd = coinPtTEnd->span()->ptT();
     oppPtTStart = oppPtTStart->span()->ptT();
     oppPtTEnd = oppPtTEnd->span()->ptT();
-    SkASSERT(coinPtTStart->fT < coinPtTEnd->fT);
+    SkOPASSERT(coinPtTStart->fT < coinPtTEnd->fT);
     SkASSERT(oppPtTStart->fT != oppPtTEnd->fT);
     SkOPASSERT(!coinPtTStart->deleted());
     SkOPASSERT(!coinPtTEnd->deleted());
@@ -754,7 +758,7 @@
     // save head so that walker can iterate over old data unperturbed
     // addifmissing adds to head freely then add saved head in the end
         const SkOpPtT* ocs = outer->coinPtTStart();
-        SkASSERT(!ocs->deleted());
+        FAIL_IF(ocs->deleted());
         const SkOpSegment* outerCoin = ocs->segment();
         SkASSERT(!outerCoin->done());  // if it's done, should have already been removed from list
         const SkOpPtT* oos = outer->oppPtTStart();
@@ -772,9 +776,9 @@
             const SkOpPtT* ics = inner->coinPtTStart();
             FAIL_IF(ics->deleted());
             const SkOpSegment* innerCoin = ics->segment();
-            SkASSERT(!innerCoin->done());
+            FAIL_IF(innerCoin->done());
             const SkOpPtT* ios = inner->oppPtTStart();
-            SkASSERT(!ios->deleted());
+            FAIL_IF(ios->deleted());
             const SkOpSegment* innerOpp = ios->segment();
             SkASSERT(!innerOpp->done());
             SkOpSegment* innerCoinWritable = const_cast<SkOpSegment*>(innerCoin);
@@ -855,9 +859,11 @@
     }
     const SkOpPtT* s2 = overS->find(seg2);
     const SkOpPtT* e2 = overE->find(seg2);
+    FAIL_IF(!e2);
     if (!s2->starter(e2)->span()->upCast()->windValue()) {
         s2 = overS->find(seg2o);
         e2 = overE->find(seg2o);
+        FAIL_IF(!s2);
         if (!s2->starter(e2)->span()->upCast()->windValue()) {
             return true;
         }
@@ -956,11 +962,11 @@
 }
 
 // walk span sets in parallel, moving winding from one to the other
-void SkOpCoincidence::apply(DEBUG_COIN_DECLARE_ONLY_PARAMS()) {
+bool SkOpCoincidence::apply(DEBUG_COIN_DECLARE_ONLY_PARAMS()) {
     DEBUG_SET_PHASE();
     SkCoincidentSpans* coin = fHead;
     if (!coin) {
-        return;
+        return true;
     }
     do {
         SkOpSpan* start = coin->coinPtTStartWritable()->span()->upCast();
@@ -1055,6 +1061,7 @@
 #endif
             start->setWindValue(windValue);
             start->setOppValue(oppValue);
+            FAIL_IF(oWindValue == -1);
             oStart->setWindValue(oWindValue);
             oStart->setOppValue(oOppValue);
             if (!windValue && !oppValue) {
@@ -1076,6 +1083,7 @@
             oStart = oNext->upCast();
         } while (true);
     } while ((coin = coin->next()));
+    return true;
 }
 
 // Please keep this in sync with debugRelease()
@@ -1272,7 +1280,7 @@
         SkOpSpanBase* startBase = coin->coinPtTStartWritable()->span();
         FAIL_IF(!startBase->upCastable());
         SkOpSpan* start = startBase->upCast();
-        SkASSERT(!start->deleted());
+        FAIL_IF(start->deleted());
         SkOpSpanBase* end = coin->coinPtTEndWritable()->span();
         SkOPASSERT(!end->deleted());
         SkOpSpanBase* oStart = coin->oppPtTStartWritable()->span();
@@ -1291,7 +1299,8 @@
         const SkOpSegment* oSegment = oStart->segment();
         SkOpSpanBase* next = start;
         SkOpSpanBase* oNext = oStart;
-        bool ordered = coin->ordered();
+        bool ordered;
+        FAIL_IF(!coin->ordered(&ordered));
         while ((next = next->upCast()->next()) != end) {
             FAIL_IF(!next->upCastable());
             SkAssertResult(next->upCast()->insertCoincidence(oSegment, flipped, ordered));