fix fuzz bugs
authorcaryclark <caryclark@google.com>
Tue, 28 Jun 2016 16:23:57 +0000 (09:23 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 28 Jun 2016 16:23:57 +0000 (09:23 -0700)
Detect more places where the pathops numerics cause numbers
to become nearly identical and subsequently fail. These tests
have extreme inputs and cannot succeed.

Also remove the expectSuccess parameter from PathOpsDebug
and check instead in the test framework.

R=mbarbella@chromium.org
TBR=reed@google.com
BUG=623072,623022
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2103513002

Review-Url: https://codereview.chromium.org/2103513002

src/pathops/SkDConicLineIntersection.cpp
src/pathops/SkOpCoincidence.cpp
src/pathops/SkOpCoincidence.h
src/pathops/SkPathOpsCommon.cpp
src/pathops/SkPathOpsCommon.h
src/pathops/SkPathOpsConic.cpp
src/pathops/SkPathOpsOp.cpp
tests/PathOpsExtendedTest.cpp
tests/PathOpsExtendedTest.h
tests/PathOpsOpTest.cpp

index 2d906072fa549f79bca75a96a5323d234dd1df15..710647236cb56c2565ece34bba060c066bad7f35 100644 (file)
@@ -157,7 +157,9 @@ public:
             double conicT = roots[index];
             SkDPoint pt = fConic.ptAtT(conicT);
             SkDEBUGCODE_(double conicVals[] = { fConic[0].fX, fConic[1].fX, fConic[2].fX });
-            SkASSERT(close_to(pt.fX, axisIntercept, conicVals));
+            SkASSERT((fIntersections->debugGlobalState() &&
+                fIntersections->debugGlobalState()->debugSkipAssert()) ||
+                close_to(pt.fX, axisIntercept, conicVals));
             double lineT = (pt.fY - top) / (bottom - top);
             if (this->pinTs(&conicT, &lineT, &pt, kPointInitialized)
                     && this->uniqueAnswer(conicT, pt)) {
index b72bd6cb37232fdce2534e4479e6107e177de538..4b46e685ee838bdf50edc0e5f0b01ed03c4a8040 100755 (executable)
@@ -326,34 +326,41 @@ bool SkOpCoincidence::addMissing(SkChunkAlloc* allocator) {
     return added;
 }
 
-void SkOpCoincidence::addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegment* seg2,
+bool SkOpCoincidence::addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegment* seg2,
         SkOpSegment* seg2o, SkOpPtT* overS, SkOpPtT* overE, SkChunkAlloc* allocator) {
     SkOpPtT* s1 = overS->find(seg1);
     SkOpPtT* e1 = overE->find(seg1);
+    if (approximately_equal_half(s1->fT, e1->fT)) {
+        return false;
+    }
     if (!s1->starter(e1)->span()->upCast()->windValue()) {
         s1 = overS->find(seg1o);
         e1 = overE->find(seg1o);
         if (!s1->starter(e1)->span()->upCast()->windValue()) {
-            return;
+            return true;
         }
     }
     SkOpPtT* s2 = overS->find(seg2);
     SkOpPtT* e2 = overE->find(seg2);
+    if (approximately_equal_half(s2->fT, e2->fT)) {
+        return false;
+    }
     if (!s2->starter(e2)->span()->upCast()->windValue()) {
         s2 = overS->find(seg2o);
         e2 = overE->find(seg2o);
         if (!s2->starter(e2)->span()->upCast()->windValue()) {
-            return;
+            return true;
         }
     }
     if (s1->segment() == s2->segment()) {
-        return;
+        return true;
     }
     if (s1->fT > e1->fT) {
         SkTSwap(s1, e1);
         SkTSwap(s2, e2);
     }
     this->add(s1, e1, s2, e2, allocator);
+    return true;
 }
 
 bool SkOpCoincidence::contains(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd,
@@ -540,7 +547,7 @@ bool SkOpCoincidence::expand() {
     return expanded;
 }
 
-void SkOpCoincidence::findOverlaps(SkOpCoincidence* overlaps, SkChunkAlloc* allocator) const {
+bool SkOpCoincidence::findOverlaps(SkOpCoincidence* overlaps, SkChunkAlloc* allocator) const {
     overlaps->fHead = overlaps->fTop = nullptr;
     SkDEBUGCODE_(overlaps->debugSetGlobalState(fDebugState));
     SkCoincidentSpans* outer = fHead;
@@ -563,18 +570,21 @@ void SkOpCoincidence::findOverlaps(SkOpCoincidence* overlaps, SkChunkAlloc* allo
                     || (outerOpp == innerOpp && SkOpPtT::Overlaps(outer->fOppPtTStart,
                     outer->fOppPtTEnd, inner->fOppPtTStart, inner->fOppPtTEnd,
                     &overlapS, &overlapE))) {
-                overlaps->addOverlap(outerCoin, outerOpp, innerCoin, innerOpp,
-                        overlapS, overlapE, allocator);
+                if (!overlaps->addOverlap(outerCoin, outerOpp, innerCoin, innerOpp,
+                        overlapS, overlapE, allocator)) {
+                    return false;
+                }
             }
         }
         outer = outer->fNext;
     }
+    return true;
 }
 
-void SkOpCoincidence::fixAligned() {
+bool SkOpCoincidence::fixAligned() {
     SkCoincidentSpans* coin = fHead;
     if (!coin) {
-        return;
+        return true;
     }
     do {
         if (coin->fCoinPtTStart->deleted()) {
@@ -593,6 +603,12 @@ void SkOpCoincidence::fixAligned() {
     coin = fHead;
     SkCoincidentSpans** priorPtr = &fHead;
     do {
+        if (coin->fCoinPtTStart == coin->fCoinPtTEnd) {
+            return false;
+        }
+        if (coin->fOppPtTStart == coin->fOppPtTEnd) {
+            return false;
+        }
         if (coin->fCoinPtTStart->collapsed(coin->fCoinPtTEnd)
                 || coin->fOppPtTStart->collapsed(coin->fOppPtTEnd)) {
             *priorPtr = coin->fNext;
@@ -600,6 +616,7 @@ void SkOpCoincidence::fixAligned() {
         }
         priorPtr = &coin->fNext;
     } while ((coin = coin->fNext));
+    return true;
 }
 
 void SkOpCoincidence::fixUp(SkOpPtT* deleted, SkOpPtT* kept) {
index 344866ff3687cb301f645da6022938ed68530254..1efe6c0613a91bdca17a3486e7f97e3ced080f87 100644 (file)
@@ -84,8 +84,8 @@ public:
     bool expand();
     bool extend(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart,
         SkOpPtT* oppPtTEnd);
-    void findOverlaps(SkOpCoincidence* , SkChunkAlloc* allocator) const;
-    void fixAligned();
+    bool findOverlaps(SkOpCoincidence* , SkChunkAlloc* allocator) const;
+    bool fixAligned();
     void fixUp(SkOpPtT* deleted, SkOpPtT* kept);
 
     bool isEmpty() const {
@@ -103,7 +103,7 @@ private:
                       SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd,
                       SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd,
                       SkChunkAlloc* );
-    void addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegment* seg2, SkOpSegment* seg2o,
+    bool addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegment* seg2, SkOpSegment* seg2o,
                     SkOpPtT* overS, SkOpPtT* overE, SkChunkAlloc* );
     bool debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s, 
                            const SkOpPtT* over1e) const;
index 340b306d60fb84d48ee6faf74189b1ab37460537..ec8e78d0cb9acf3208a7ab0e7ccad8a29bcbf6ad 100644 (file)
@@ -466,7 +466,9 @@ bool HandleCoincidence(SkOpContourHead* contourList, SkOpCoincidence* coincidenc
     DEBUG_COINCIDENCE_HEALTH(contourList, "moveNearby");
     align(contourList);  // give all span members common values
     DEBUG_COINCIDENCE_HEALTH(contourList, "align");
-    coincidence->fixAligned();  // aligning may have marked a coincidence pt-t deleted
+    if (!coincidence->fixAligned()) { // aligning may have marked a coincidence pt-t deleted
+        return false;
+    }
     DEBUG_COINCIDENCE_HEALTH(contourList, "fixAligned");
 #if DEBUG_VALIDATE
     globalState->setPhase(SkOpGlobalState::kIntersecting);
@@ -480,7 +482,9 @@ bool HandleCoincidence(SkOpContourHead* contourList, SkOpCoincidence* coincidenc
         DEBUG_COINCIDENCE_HEALTH(contourList, "moveNearby2");
         align(contourList);  // give all span members common values
         DEBUG_COINCIDENCE_HEALTH(contourList, "align2");
-        coincidence->fixAligned();  // aligning may have marked a coincidence pt-t deleted
+        if (!coincidence->fixAligned()) {  // aligning may have marked a coincidence pt-t deleted
+            return false;
+        }
         DEBUG_COINCIDENCE_HEALTH(contourList, "fixAligned2");
     }
 #if DEBUG_VALIDATE
@@ -520,7 +524,9 @@ bool HandleCoincidence(SkOpContourHead* contourList, SkOpCoincidence* coincidenc
         DEBUG_COINCIDENCE_HEALTH(contourList, "pairs->apply");
         // For each coincident pair that overlaps another, when the receivers (the 1st of the pair)
         // are different, construct a new pair to resolve their mutual span
-        pairs->findOverlaps(&overlaps, allocator);
+        if (!pairs->findOverlaps(&overlaps, allocator)) {
+            return false;
+        }
         DEBUG_COINCIDENCE_HEALTH(contourList, "pairs->findOverlaps");
     } while (!overlaps.isEmpty());
     calcAngles(contourList, allocator);
index 856a984ce5d6daea306f47873caa228f6f899bbe..5b4902f53b51eb313f8d156c024572c8b5a1a1f4 100644 (file)
@@ -25,8 +25,8 @@ SkOpSegment* FindUndone(SkOpContourHead* , SkOpSpanBase** startPtr,
 bool FixWinding(SkPath* path);
 bool SortContourList(SkOpContourHead** , bool evenOdd, bool oppEvenOdd);
 bool HandleCoincidence(SkOpContourHead* , SkOpCoincidence* , SkChunkAlloc* );
-bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
-             bool expectSuccess  SkDEBUGPARAMS(bool skipAssert)
+bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result
+             SkDEBUGPARAMS(bool skipAssert)
              SkDEBUGPARAMS(const char* testName));
 #if DEBUG_ACTIVE_SPANS
 void DebugShowActiveSpans(SkOpContourHead* );
index 86bad262e32ba4f72ac7f9949f4556ab814efce9..dd523211de17817a7d8d1dad4a55b984baa5308d 100644 (file)
@@ -34,7 +34,10 @@ int SkDConic::FindExtrema(const double src[], SkScalar w, double t[1]) {
 
     double tValues[2];
     int roots = SkDQuad::RootsValidT(coeff[0], coeff[1], coeff[2], tValues);
-    SkASSERT(0 == roots || 1 == roots);
+    // In extreme cases, the number of roots returned can be 2. Pathops
+    // will fail later on, so there's no advantage to plumbing in an error
+    // return here.
+    // SkASSERT(0 == roots || 1 == roots);
 
     if (1 == roots) {
         t[0] = tValues[0];
index b71ca9e481e98a5a33ad5d49b31593635064d85b..25795047c80dbabd1782313988fbe8d20abdb87d 100644 (file)
@@ -245,8 +245,8 @@ extern void (*gVerboseFinalize)();
 
 #endif
 
-bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
-        bool expectSuccess  SkDEBUGPARAMS(bool skipAssert) SkDEBUGPARAMS(const char* testName)) {
+bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result
+        SkDEBUGPARAMS(bool skipAssert) SkDEBUGPARAMS(const char* testName)) {
     SkChunkAlloc allocator(4096);  // FIXME: add a constant expression here, tune
     SkOpContour contour;
     SkOpContourHead* contourList = static_cast<SkOpContourHead*>(&contour);
@@ -413,7 +413,7 @@ static int debug_paths_draw_the_same(const SkPath& one, const SkPath& two, SkBit
 
 bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) {
 #if DEBUG_VERIFY
-    if (!OpDebug(one, two, op, result, true  SkDEBUGPARAMS(nullptr))) {
+    if (!OpDebug(one, two, op, result  SkDEBUGPARAMS(nullptr))) {
         SkDebugf("%s did not expect failure\none: fill=%d\n", __FUNCTION__, one.getFillType());
         one.dumpHex();
         SkDebugf("two: fill=%d\n", two.getFillType());
@@ -455,6 +455,6 @@ bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) {
     }
     return true;
 #else
-    return OpDebug(one, two, op, result, true  SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
+    return OpDebug(one, two, op, result  SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
 #endif
 }
index 572766086ac0e7d5d5d7904e896e3b8ae01c14a1..b71b11543919d94a8b11e8add2d29bc732b3e359 100644 (file)
@@ -487,8 +487,8 @@ static void showName(const SkPath& a, const SkPath& b, const SkPathOp shapeOp) {
 }
 #endif
 
-bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
-             bool expectSuccess  SkDEBUGPARAMS(bool skipAssert)
+bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result
+             SkDEBUGPARAMS(bool skipAssert)
              SkDEBUGPARAMS(const char* testName));
 
 static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
@@ -497,10 +497,12 @@ static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkP
     showName(a, b, shapeOp);
 #endif
     SkPath out;
-    if (!OpDebug(a, b, shapeOp, &out, expectSuccess  SkDEBUGPARAMS(skipAssert)
+    if (!OpDebug(a, b, shapeOp, &out  SkDEBUGPARAMS(skipAssert)
             SkDEBUGPARAMS(testName))) {
-        SkDebugf("%s did not expect failure\n", __FUNCTION__);
-        REPORTER_ASSERT(reporter, 0);
+        if (expectSuccess) {
+            SkDebugf("%s did not expect failure\n", __FUNCTION__);
+            REPORTER_ASSERT(reporter, 0);
+        }
         return false;
     }
     if (!reporter->verbose()) {
@@ -556,6 +558,11 @@ bool testPathSkipAssertOp(skiatest::Reporter* reporter, const SkPath& a, const S
     return innerPathOp(reporter, a, b, shapeOp, testName, true, true);
 }
 
+bool testPathFailSkipAssertOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
+        const SkPathOp shapeOp, const char* testName) {
+    return innerPathOp(reporter, a, b, shapeOp, testName, false, true);
+}
+
 bool testPathFailOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
                  const SkPathOp shapeOp, const char* testName) {
 #if DEBUG_SHOW_TEST_NAME
index 0a6f4ab91fa669fd00461dba004d20718c392e33..1fadeb8ca4d839c3debe3d135f9bf35fecb4e695 100644 (file)
@@ -44,6 +44,8 @@ extern bool testPathOpFailCheck(skiatest::Reporter* reporter, const SkPath& a, c
                                 const SkPathOp , const char* testName);
 extern bool testPathFailOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
                            const SkPathOp , const char* testName);
+extern bool testPathFailSkipAssertOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
+                                 const SkPathOp , const char* testName);
 extern bool testPathSkipAssertOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
                                  const SkPathOp , const char* testName);
 extern bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& state,
index d75c9a6fb66c80c513774486ab576f503ae67fe0..a73bdcf37202aaec196486ffcc39f8c69b5d5aa3 100644 (file)
@@ -5884,7 +5884,70 @@ SkPath path2(path);
 testPathFailOp(reporter, path1, path2, kUnion_SkPathOp, filename);
 }
 
+static void fuzz763_9(skiatest::Reporter* reporter, const char* filename) {
+    SkPath path;
+    path.setFillType((SkPath::FillType) 1);
+
+    SkPath path1(path);
+    path.reset();
+    path.setFillType((SkPath::FillType) 0);
+path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000));  // 0, 0
+path.conicTo(SkBits2Float(0x2a8c555b), SkBits2Float(0x081f2a21), SkBits2Float(0x7bc00321), SkBits2Float(0xed7a6a4b), SkBits2Float(0x1f212a8c));  // 2.49282e-13f, 4.78968e-34f, 1.99397e+36f, -4.84373e+27f, 3.41283e-20f
+path.lineTo(SkBits2Float(0x7bc00321), SkBits2Float(0xed7a6a4b));  // 1.99397e+36f, -4.84373e+27f
+path.lineTo(SkBits2Float(0x282a3a21), SkBits2Float(0x3a21df28));  // 9.4495e-15f, 0.000617492f
+path.lineTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000));  // 0, 0
+path.close();
+path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000));  // 0, 0
+path.quadTo(SkBits2Float(0x8a284f9a), SkBits2Float(0x3ac23ab3), SkBits2Float(0x1d2a2928), SkBits2Float(0x63962be6));  // -8.10388e-33f, 0.00148185f, 2.25206e-21f, 5.54035e+21f
+path.moveTo(SkBits2Float(0x29272a81), SkBits2Float(0x2ab03a55));  // 3.71183e-14f, 3.13044e-13f
+path.quadTo(SkBits2Float(0x2720213b), SkBits2Float(0x3a214729), SkBits2Float(0xdf28282a), SkBits2Float(0x8a2f2121));  // 2.22225e-15f, 0.000615227f, -1.2117e+19f, -8.43217e-33f
+path.quadTo(SkBits2Float(0x373b3a27), SkBits2Float(0x201fc4c1), SkBits2Float(0x27576c2a), SkBits2Float(0x5921c25d));  // 1.11596e-05f, 1.35329e-19f, 2.98959e-15f, 2.8457e+15f
+path.quadTo(SkBits2Float(0x2720213b), SkBits2Float(0x3a214729), SkBits2Float(0xdf28282a), SkBits2Float(0x3a8a3a21));  // 2.22225e-15f, 0.000615227f, -1.2117e+19f, 0.00105459f
+path.cubicTo(SkBits2Float(0x373b3ac5), SkBits2Float(0x201fc422), SkBits2Float(0x523a702a), SkBits2Float(0x27576c51), SkBits2Float(0x5921c25d), SkBits2Float(0x51523a70));  // 1.11598e-05f, 1.35327e-19f, 2.00186e+11f, 2.9896e-15f, 2.8457e+15f, 5.64327e+10f
+path.quadTo(SkBits2Float(0xd912102a), SkBits2Float(0x284f9a28), SkBits2Float(0xb38a1f30), SkBits2Float(0x3a3ac23a));  // -2.56957e+15f, 1.15242e-14f, -6.4318e-08f, 0.000712428f
+path.lineTo(SkBits2Float(0xc809272a), SkBits2Float(0x29b02829));  // -140445, 7.82294e-14f
+
+    SkPath path2(path);
+    testPathFailOp(reporter, path1, path2, (SkPathOp) 1, filename);
+}
+
+
+static void fuzz763_4(skiatest::Reporter* reporter, const char* filename) {
+    SkPath path;
+    path.setFillType((SkPath::FillType) 1);
+
+    SkPath path1(path);
+    path.reset();
+    path.setFillType((SkPath::FillType) 0);
+path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000));  // 0, 0
+path.lineTo(SkBits2Float(0x555b3a2d), SkBits2Float(0x2a212a8c));  // 1.50652e+13f, 1.43144e-13f
+path.conicTo(SkBits2Float(0xc0032108), SkBits2Float(0x7a6a4b7b), SkBits2Float(0x212a8ced), SkBits2Float(0x0321081f), SkBits2Float(0x6a3a7bc0));  // -2.04889f, 3.04132e+35f, 5.77848e-19f, 4.7323e-37f, 5.63611e+25f
+path.conicTo(SkBits2Float(0x3a2147ed), SkBits2Float(0xdf28282a), SkBits2Float(0x3a8a3a21), SkBits2Float(0x8a284f9a), SkBits2Float(0x3ac2b33a));  // 0.000615238f, -1.2117e+19f, 0.00105459f, -8.10388e-33f, 0.00148544f
+path.cubicTo(SkBits2Float(0x1d2a2928), SkBits2Float(0x63962be6), SkBits2Float(0x295b2d2a), SkBits2Float(0x68295b2d), SkBits2Float(0x2d296855), SkBits2Float(0x2a8c275b));  // 2.25206e-21f, 5.54035e+21f, 4.86669e-14f, 3.19905e+24f, 9.6297e-12f, 2.48963e-13f
+path.lineTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000));  // 0, 0
+path.close();
+path.moveTo(SkBits2Float(0x55685b1f), SkBits2Float(0x5b2d2968));  // 1.59674e+13f, 4.87407e+16f
+path.lineTo(SkBits2Float(0x2a212a8c), SkBits2Float(0x2a21081f));  // 1.43144e-13f, 1.43025e-13f
+path.conicTo(SkBits2Float(0xde6a4b7b), SkBits2Float(0x2a8ced7a), SkBits2Float(0x21081f21), SkBits2Float(0x3a7bc003), SkBits2Float(0x47ed7a6a));  // -4.22068e+18f, 2.50338e-13f, 4.61198e-19f, 0.00096035f, 121589
+path.lineTo(SkBits2Float(0x55685b1f), SkBits2Float(0x5b2d2968));  // 1.59674e+13f, 4.87407e+16f
+path.close();
+path.moveTo(SkBits2Float(0x55685b1f), SkBits2Float(0x5b2d2968));  // 1.59674e+13f, 4.87407e+16f
+path.quadTo(SkBits2Float(0xdf28282a), SkBits2Float(0x3a8a3a21), SkBits2Float(0x8a284f9a), SkBits2Float(0x3ac23ab3));  // -1.2117e+19f, 0.00105459f, -8.10388e-33f, 0.00148185f
+path.lineTo(SkBits2Float(0x2928088c), SkBits2Float(0x2be61d2a));  // 3.73109e-14f, 1.63506e-12f
+path.conicTo(SkBits2Float(0x2a812a63), SkBits2Float(0x2d292a27), SkBits2Float(0x5568295b), SkBits2Float(0x5b2d2968), SkBits2Float(0x552d6829));  // 2.29444e-13f, 9.6159e-12f, 1.5954e+13f, 4.87407e+16f, 1.19164e+13f
+path.conicTo(SkBits2Float(0x395b2d5b), SkBits2Float(0x68552768), SkBits2Float(0x555b2df0), SkBits2Float(0x1f722a8c), SkBits2Float(0x082a212a));  // 0.000209024f, 4.02636e+24f, 1.50619e+13f, 5.12807e-20f, 5.11965e-34f
+path.lineTo(SkBits2Float(0x55685b1f), SkBits2Float(0x5b2d2968));  // 1.59674e+13f, 4.87407e+16f
+path.close();
+path.moveTo(SkBits2Float(0x212a8c55), SkBits2Float(0x21081f2a));  // 5.7784e-19f, 4.61198e-19f
+path.conicTo(SkBits2Float(0x6a4b7bc0), SkBits2Float(0x2147ed7a), SkBits2Float(0x28282a3a), SkBits2Float(0x21df212a), SkBits2Float(0x033a8a3a));  // 6.14991e+25f, 6.77381e-19f, 9.33503e-15f, 1.51198e-18f, 5.48192e-37f
+
+    SkPath path2(path);
+    testPathFailSkipAssertOp(reporter, path1, path2, (SkPathOp) 1, filename);
+}
+
 static struct TestDesc failTests[] = {
+    TEST(fuzz763_4),
+    TEST(fuzz763_9),
     TEST(fuzz1450_1),
     TEST(fuzz1450_0),
     TEST(bug597926_0),