Memory leak from cairo_set_scaled_font() if font options set custom palette
I found this while looking at #794 (closed).
The following C program
(Loop in main
to increase the size of the leak so that other allocations do not show up / this becomes easier to spot in the output):
#include <cairo.h>
static void foo () {
cairo_surface_t *s = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
cairo_t *cr = cairo_create (s);
cairo_font_options_t *opt = cairo_font_options_create ();
cairo_scaled_font_t *font;
cairo_matrix_t matrix;
int index;
cairo_matrix_init_identity (&matrix);
cairo_font_options_set_custom_palette_color (opt, 0, 1, 1, 1, 1);
font = cairo_scaled_font_create (cairo_get_font_face (cr), &matrix, &matrix, opt);
cairo_set_scaled_font (cr, font);
cairo_scaled_font_destroy (font);
cairo_font_options_destroy (opt);
cairo_destroy (cr);
cairo_surface_destroy (s);
}
int main () {
int i;
for (i = 0; i < 1000 * 1000; i++) {
foo ();
}
cairo_debug_reset_static_data();
return 0;
}
..causes the following valgrind memcheck report (with --leak-check=full
):
==22607== 39,999,760 bytes in 999,994 blocks are definitely lost in loss record 203 of 203
==22607== at 0x48407B4: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==22607== by 0x4886C62: _cairo_font_options_init_copy (cairo-font-options.c:103)
==22607== by 0x488C029: _cairo_gstate_set_font_options (cairo-gstate.c:1757)
==22607== by 0x48841D7: _cairo_default_context_set_scaled_font (cairo-default-context.c:1310)
==22607== by 0x490809A: cairo_set_scaled_font (cairo.c:3318)
==22607== by 0x1092B8: foo (in /tmp/a.out)
==22607== by 0x109306: main (in /tmp/a.out)
Fix seems to be
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 8a253468d..e9019e8e6 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -193,6 +193,7 @@ void
_cairo_gstate_fini (cairo_gstate_t *gstate)
{
_cairo_stroke_style_fini (&gstate->stroke_style);
+ _cairo_font_options_fini (&gstate->font_options);
cairo_font_face_destroy (gstate->font_face);
gstate->font_face = NULL;
Does it make sense to add the reproducer to the test suite? Somehow? If not, this issue exists to at least save the reproducer somewhere.