GrTessellator: fix for zombie edge fuzzer crash.

While splitting one edge, merge_collinear_edges() may in rare cases
merge the other edge of the intersection out of existence.
split_edge() then brings these dead edges partially back to life,
leaving the mesh in an inconsistent state.

The fix is to null out the top and bottom pointers of dead edges to
mark them as dead, and only split living edges.

Bug: skia:7911
Change-Id: I1c0b59581acfcd0b8191f2d129b33f7d0d1a2516
Reviewed-on: https://skia-review.googlesource.com/129181
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Stephen White 2018-05-18 11:49:21 -04:00 committed by Skia Commit-Bot
parent 13197b8d4f
commit ec79c39a77
2 changed files with 18 additions and 1 deletions

View File

@ -1013,6 +1013,7 @@ void merge_edges_above(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex**
rewind(activeEdges, current, edge->fTop, c);
other->fWinding += edge->fWinding;
disconnect(edge);
edge->fTop = edge->fBottom = nullptr;
} else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
rewind(activeEdges, current, edge->fTop, c);
other->fWinding += edge->fWinding;
@ -1033,6 +1034,7 @@ void merge_edges_below(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex**
rewind(activeEdges, current, edge->fTop, c);
other->fWinding += edge->fWinding;
disconnect(edge);
edge->fTop = edge->fBottom = nullptr;
} else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
rewind(activeEdges, current, other->fTop, c);
edge->fWinding += other->fWinding;
@ -1070,7 +1072,7 @@ void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current,
void split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c,
SkArenaAlloc& alloc) {
if (v == edge->fTop || v == edge->fBottom) {
if (!edge->fTop || !edge->fBottom || v == edge->fTop || v == edge->fBottom) {
return;
}
LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",

View File

@ -472,6 +472,20 @@ static SkPath create_path_31() {
return path;
}
// Reduction from skbug.com/7911 that causes a crash due to splitting a
// zombie edge.
static SkPath create_path_32() {
SkPath path;
path.moveTo( 0, 1.0927740941146660348e+24);
path.lineTo(2.9333931225865729333e+32, 16476101);
path.lineTo(1.0927731573659435417e+24, 1.0927740941146660348e+24);
path.lineTo(1.0927740941146660348e+24, 3.7616281094287041715e-37);
path.lineTo(1.0927740941146660348e+24, 1.0927740941146660348e+24);
path.lineTo(1.3061803026169399536e-33, 1.0927740941146660348e+24);
path.lineTo(4.7195362919941370727e-16, -8.4247545146051822591e+32);
return path;
}
static std::unique_ptr<GrFragmentProcessor> create_linear_gradient_processor(GrContext* ctx) {
SkPoint pts[2] = { {0, 0}, {1, 1} };
@ -563,5 +577,6 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(TessellatingPathRendererTests, reporter, ctxInfo) {
test_path(ctx, rtc.get(), create_path_29());
test_path(ctx, rtc.get(), create_path_30());
test_path(ctx, rtc.get(), create_path_31(), SkMatrix(), GrAAType::kCoverage);
test_path(ctx, rtc.get(), create_path_32());
}
#endif