Crash when calling fill_preserve with fuzzed path in Cairo
Issue Summary
OSS-Fuzz triggered a crash in Cairo with the SVG below. I was able to reproduce the same crash with the following C code:
#include <cairo.h>
int main(int argc, char *argv[])
{
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 20, 20);
cairo_t *cr = cairo_create(surface);
cairo_set_line_width(cr, 1);
cairo_move_to(cr, 9000000, 33);
cairo_line_to(cr, -9000000, 3);
cairo_fill_preserve(cr);
cairo_destroy(cr);
cairo_surface_destroy(surface);
return 0;
}
To compile: gcc -ggdb -Wall $(pkg-config --cflags --libs cairo) crash.c
Example SVG
<svg height="20" width="20"><path d="M 9000000 33 L -9000000 3"/></svg>
Librsvg Version
Platform
Reproduced on Arch Linux. Found by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=69459
Additional logs
Command: ./target/debug/rsvg-convert crash.svg
Conditional jump or move depends on uninitialised value(s)
at 0x48D322B: UnknownInlinedFun (cairo-tor-scan-converter.c:1338)
by 0x48D322B: UnknownInlinedFun (cairo-tor-scan-converter.c:1767)
by 0x48D322B: _cairo_tor_scan_converter_generate.lto_priv.0 (cairo-tor-scan-converter.c:1857)
by 0x48C8480: composite_polygon (cairo-spans-compositor.c:801)
by 0x48CBFC4: _cairo_spans_compositor_fill.lto_priv.0 (cairo-spans-compositor.c:1174)
by 0x488504E: _cairo_compositor_fill (cairo-compositor.c:245)
by 0x489656A: _cairo_image_surface_fill (cairo-image-surface.c:1018)
by 0x48D57EA: _cairo_surface_fill (cairo-surface.c:2453)
by 0x48906FB: _cairo_gstate_fill (cairo-gstate.c:1352)
by 0x48E03D8: cairo_fill_preserve (cairo.c:2454)
by 0x6E9D3D: cairo::context::Context::fill_preserve (context.rs:465)
by 0x2BA974: rsvg::drawing_ctx::DrawingCtx::fill (drawing_ctx.rs:1271)
by 0x42E79B: rsvg::drawing_ctx::DrawingCtx::draw_shape::{{closure}} (drawing_ctx.rs:1370)
by 0x42B275: rsvg::drawing_ctx::DrawingCtx::with_discrete_layer::{{closure}} (drawing_ctx.rs:918)
Uninitialised value was created by a heap allocation
at 0x4842788: malloc (vg_replace_malloc.c:446)
by 0x48C7F09: UnknownInlinedFun (cairo-tor-scan-converter.c:1875)
by 0x48C7F09: composite_polygon (cairo-spans-compositor.c:788)
by 0x48CBFC4: _cairo_spans_compositor_fill.lto_priv.0 (cairo-spans-compositor.c:1174)
by 0x488504E: _cairo_compositor_fill (cairo-compositor.c:245)
by 0x489656A: _cairo_image_surface_fill (cairo-image-surface.c:1018)
by 0x48D57EA: _cairo_surface_fill (cairo-surface.c:2453)
by 0x48906FB: _cairo_gstate_fill (cairo-gstate.c:1352)
by 0x48E03D8: cairo_fill_preserve (cairo.c:2454)
by 0x6E9D3D: cairo::context::Context::fill_preserve (context.rs:465)
by 0x2BA974: rsvg::drawing_ctx::DrawingCtx::fill (drawing_ctx.rs:1271)
by 0x42E79B: rsvg::drawing_ctx::DrawingCtx::draw_shape::{{closure}} (drawing_ctx.rs:1370)
by 0x42B275: rsvg::drawing_ctx::DrawingCtx::with_discrete_layer::{{closure}} (drawing_ctx.rs:918)
Invalid read of size 4
at 0x48D3230: UnknownInlinedFun (cairo-tor-scan-converter.c:1338)
by 0x48D3230: UnknownInlinedFun (cairo-tor-scan-converter.c:1767)
by 0x48D3230: _cairo_tor_scan_converter_generate.lto_priv.0 (cairo-tor-scan-converter.c:1857)
by 0x48C8480: composite_polygon (cairo-spans-compositor.c:801)
by 0x48CBFC4: _cairo_spans_compositor_fill.lto_priv.0 (cairo-spans-compositor.c:1174)
by 0x488504E: _cairo_compositor_fill (cairo-compositor.c:245)
by 0x489656A: _cairo_image_surface_fill (cairo-image-surface.c:1018)
by 0x48D57EA: _cairo_surface_fill (cairo-surface.c:2453)
by 0x48906FB: _cairo_gstate_fill (cairo-gstate.c:1352)
by 0x48E03D8: cairo_fill_preserve (cairo.c:2454)
by 0x6E9D3D: cairo::context::Context::fill_preserve (context.rs:465)
by 0x2BA974: rsvg::drawing_ctx::DrawingCtx::fill (drawing_ctx.rs:1271)
by 0x42E79B: rsvg::drawing_ctx::DrawingCtx::draw_shape::{{closure}} (drawing_ctx.rs:1370)
by 0x42B275: rsvg::drawing_ctx::DrawingCtx::with_discrete_layer::{{closure}} (drawing_ctx.rs:918)
Address 0x1c is not stack'd, malloc'd or (recently) free'd
Process terminating with default action of signal 11 (SIGSEGV): dumping core
Access not within mapped region at address 0x1C
at 0x48D3230: UnknownInlinedFun (cairo-tor-scan-converter.c:1338)
by 0x48D3230: UnknownInlinedFun (cairo-tor-scan-converter.c:1767)
by 0x48D3230: _cairo_tor_scan_converter_generate.lto_priv.0 (cairo-tor-scan-converter.c:1857)
by 0x48C8480: composite_polygon (cairo-spans-compositor.c:801)
by 0x48CBFC4: _cairo_spans_compositor_fill.lto_priv.0 (cairo-spans-compositor.c:1174)
by 0x488504E: _cairo_compositor_fill (cairo-compositor.c:245)
by 0x489656A: _cairo_image_surface_fill (cairo-image-surface.c:1018)
by 0x48D57EA: _cairo_surface_fill (cairo-surface.c:2453)
by 0x48906FB: _cairo_gstate_fill (cairo-gstate.c:1352)
by 0x48E03D8: cairo_fill_preserve (cairo.c:2454)
by 0x6E9D3D: cairo::context::Context::fill_preserve (context.rs:465)
by 0x2BA974: rsvg::drawing_ctx::DrawingCtx::fill (drawing_ctx.rs:1271)
by 0x42E79B: rsvg::drawing_ctx::DrawingCtx::draw_shape::{{closure}} (drawing_ctx.rs:1370)
by 0x42B275: rsvg::drawing_ctx::DrawingCtx::with_discrete_layer::{{closure}} (drawing_ctx.rs:918)
If you believe this happened as a result of a stack
overflow in your program's main thread (unlikely but
possible), you can try to increase the size of the
main thread stack using the --main-stacksize= flag.
The main thread stack size used in this run was 8388608.