abort really big path fuzzing
This adds a couple of special cases
to stop the fuzzer from timing out.
The first occurs when the fuzzer generates
a very large path with very large quads.
Count the subdivisions and stop after a while.
The second occurs with a normal path and
1D path effect with a very small advance.
Count the points and stop after a while.
R=reed@google.com,bsalomon@google.com,kjlubick@google.com
Bug: oss-fuzz:8349,oss-fuzz:8805
Change-Id: I86130e3f512f48e5a39335412435eabc245ed193
Reviewed-on: https://skia-review.googlesource.com/135709
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
Auto-Submit: Cary Clark <caryclark@skia.org>
diff --git a/include/core/SkPathMeasure.h b/include/core/SkPathMeasure.h
index 287c292..e506c42 100644
--- a/include/core/SkPathMeasure.h
+++ b/include/core/SkPathMeasure.h
@@ -90,7 +90,9 @@
unsigned fFirstPtIndex; // relative to the current contour
bool fIsClosed; // relative to the current contour
bool fForceClosed;
-
+#if defined(IS_FUZZING_WITH_LIBFUZZER)
+ int fSubdivisionsMax;
+#endif
struct Segment {
SkScalar fDistance; // total distance up to this point
unsigned fPtIndex; // index into the fPts array
diff --git a/src/core/SkPathMeasure.cpp b/src/core/SkPathMeasure.cpp
index 905c176..e69ea49 100644
--- a/src/core/SkPathMeasure.cpp
+++ b/src/core/SkPathMeasure.cpp
@@ -231,6 +231,9 @@
SkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3],
SkScalar distance, int mint, int maxt, unsigned ptIndex) {
+#if defined(IS_FUZZING_WITH_LIBFUZZER)
+ --fSubdivisionsMax;
+#endif
if (tspan_big_enough(maxt - mint) && quad_too_curvy(pts)) {
SkPoint tmp[5];
int halft = (mint + maxt) >> 1;
@@ -256,6 +259,9 @@
SkScalar SkPathMeasure::compute_conic_segs(const SkConic& conic, SkScalar distance,
int mint, const SkPoint& minPt,
int maxt, const SkPoint& maxPt, unsigned ptIndex) {
+#if defined(IS_FUZZING_WITH_LIBFUZZER)
+ --fSubdivisionsMax;
+#endif
int halft = (mint + maxt) >> 1;
SkPoint halfPt = conic.evalAt(tValue2Scalar(halft));
if (!halfPt.isFinite()) {
@@ -281,6 +287,9 @@
SkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4],
SkScalar distance, int mint, int maxt, unsigned ptIndex) {
+#if defined(IS_FUZZING_WITH_LIBFUZZER)
+ --fSubdivisionsMax;
+#endif
if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) {
SkPoint tmp[7];
int halft = (mint + maxt) >> 1;
@@ -320,6 +329,9 @@
*/
fSegments.reset();
bool done = false;
+ #if defined(IS_FUZZING_WITH_LIBFUZZER)
+ fSubdivisionsMax = 10000000;
+#endif
do {
switch (fIter.next(pts)) {
case SkPath::kMove_Verb:
@@ -401,6 +413,13 @@
done = true;
break;
}
+#if defined(IS_FUZZING_WITH_LIBFUZZER)
+ if (fSubdivisionsMax < 0) {
+ fLength = 0;
+ return;
+ }
+#endif
+
} while (!done);
fLength = distance;
@@ -681,6 +700,11 @@
*/
bool SkPathMeasure::nextContour() {
(void)this->getLength(); // make sure we measure the current contour
+#if defined(IS_FUZZING_WITH_LIBFUZZER)
+ if (fSubdivisionsMax < 0) {
+ return false;
+ }
+#endif
fLength = -1; // now signal that we should build the next set of segments
return this->getLength() > 0;
}
diff --git a/src/effects/Sk1DPathEffect.cpp b/src/effects/Sk1DPathEffect.cpp
index 1837479..bad6ced 100644
--- a/src/effects/Sk1DPathEffect.cpp
+++ b/src/effects/Sk1DPathEffect.cpp
@@ -171,6 +171,11 @@
SkScalar SkPath1DPathEffect::next(SkPath* dst, SkScalar distance,
SkPathMeasure& meas) const {
+#if defined(IS_FUZZING_WITH_LIBFUZZER)
+ if (dst->countPoints() > 100000) {
+ return fAdvance;
+ }
+#endif
switch (fStyle) {
case kTranslate_Style: {
SkPoint pos;