Certain rectilienar path+clip combinations crash the image backend at stroke
Submitted by Zoltan Turanyi
Assigned to Chris Wilson @ickle
Description
If we have a complex, non-pixel aligned, rectilinear clip region and a rectilinear path, the image backend crashes at a stroke. (See offending code example below.) I saw this with 1.12.14, have not checked with 1.12.16, but none of the commits seem to address this.
The problem happens in composite_aligned_boxes() (file src\cairo-spans-compositor.c), where the local variable 'need_clip_mask' gets initialized to true via _clip_is_region() returning false. The latter returns false, because some of the clip boxes are not pixel aligned. (These are such boxes that do not intersect with the stroke (or the path of the stroke would not become pixel-aligned and composite_aligned_boxes() would not be called), but are kept because the fall within the stroke. See the third rectangle added to the clip in the below example. If you remove that third rectangle or make it pixel-aligned, the code runs fine.)
The code in composite_aligned_boxes() later assumes that if 'need_clip_mask' is true then the clip has a path (clip->path!=NULL) and calls get_clip_surface(), which asserts that clip->path is nonzero. Here we crash.
My proposal for a fix (without knowing all the complexity) would be to test for clip->path before setting need_clip_mask or calling get_clip_surface().
See below the code that causes the crash for me. I am not sure how to rate the severity of a bug causing a crash on rare situations, so I set it to normal. I use cairo on Windows, compiled with Visual Studio.
Cairo is a great library folks, thanks a lot for the effort!
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 100, 100); cairo_t *cr = cairo_create(surface); cairo_rectangle(cr, 10, 10, 80, 80); cairo_new_sub_path(cr); cairo_move_to(cr, 20, 20); cairo_line_to(cr, 20, 50); cairo_line_to(cr, 50, 50); cairo_line_to(cr, 50, 20); cairo_line_to(cr, 20, 20); cairo_new_sub_path(cr); cairo_move_to(cr, 31.5, 31.5); cairo_line_to(cr, 32.5, 31.5); cairo_line_to(cr, 32.5, 32.5); cairo_line_to(cr, 31.5, 32.5); cairo_line_to(cr, 31.5, 31.5); cairo_clip(cr); cairo_rectangle(cr, 5.5, 30.5, 90, 5); cairo_set_line_width(cr, 1.); cairo_stroke(cr); cairo_destroy(cr); cairo_surface_destroy (surface);
Version: 1.12.14