From: senorblanco Date: Mon, 2 Mar 2015 17:34:13 +0000 (-0800) Subject: Fix for out-of-bounds intersection (found by fuzzer). X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~3364 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a2b6d28755916cbb4817cd9d1cd1b0e237de9a50;p=platform%2Fupstream%2FlibSkiaSharp.git Fix for out-of-bounds intersection (found by fuzzer). Sometimes, the intersection returned by check_intersection() is out-of-bounds for both edges (above both tops or below both bottoms) due to floating-point inaccuracy. This causes split_edge() to create a tiny negative-length edge on one side (which would then assert). Although we could safely remove this assert and allow the negative length edge to be removed, it's faster/safer to simply avoid its creation in the first place by adjusting one edge to the other edge's endpoint. Added a new unit test to exercise this case. Review URL: https://codereview.chromium.org/968993002 --- diff --git a/src/gpu/GrTessellatingPathRenderer.cpp b/src/gpu/GrTessellatingPathRenderer.cpp index be28a69..a9ae6fa 100644 --- a/src/gpu/GrTessellatingPathRenderer.cpp +++ b/src/gpu/GrTessellatingPathRenderer.cpp @@ -958,13 +958,19 @@ void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc) LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n", edge->fTop->fID, edge->fBottom->fID, v->fID, v->fPoint.fX, v->fPoint.fY); - Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc); - insert_edge_below(newEdge, v); - insert_edge_above(newEdge, edge->fBottom); - set_bottom(edge, v, activeEdges); - cleanup_active_edges(edge, activeEdges, alloc); - fix_active_state(newEdge, activeEdges); - merge_collinear_edges(newEdge, activeEdges); + if (sweep_lt(v->fPoint, edge->fTop->fPoint)) { + set_top(edge, v, activeEdges); + } else if (sweep_gt(v->fPoint, edge->fBottom->fPoint)) { + set_bottom(edge, v, activeEdges); + } else { + Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc); + insert_edge_below(newEdge, v); + insert_edge_above(newEdge, edge->fBottom); + set_bottom(edge, v, activeEdges); + cleanup_active_edges(edge, activeEdges, alloc); + fix_active_state(newEdge, activeEdges); + merge_collinear_edges(newEdge, activeEdges); + } } void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, SkChunkAlloc& alloc) { diff --git a/tests/TessellatingPathRendererTests.cpp b/tests/TessellatingPathRendererTests.cpp index 1625bf2..0635e7f 100644 --- a/tests/TessellatingPathRendererTests.cpp +++ b/tests/TessellatingPathRendererTests.cpp @@ -220,6 +220,16 @@ static SkPath create_path_14() { return path; } +static SkPath create_path_15() { + SkPath path; + path.moveTo( 0.0f, 0.0f); + path.lineTo(10000.0f, 0.0f); + path.lineTo( 0.0f, -1.0f); + path.lineTo(10000.0f, 0.000001f); + path.lineTo( 0.0f, -30.0f); + return path; +} + static void test_path(GrDrawTarget* dt, GrRenderTarget* rt, const SkPath& path) { GrTessellatingPathRenderer tess; GrPipelineBuilder pipelineBuilder; @@ -259,5 +269,6 @@ DEF_GPUTEST(TessellatingPathRendererTests, reporter, factory) { test_path(dt, rt, create_path_12()); test_path(dt, rt, create_path_13()); test_path(dt, rt, create_path_14()); + test_path(dt, rt, create_path_15()); } #endif