Bug 102922

Summary: evince abrt on a double free in cairo_truetype_font_destroy
Product: cairo Reporter: Sebastien Bacher <seb128>
Component: pdf backendAssignee: Adrian Johnson <ajohnson>
Status: RESOLVED FIXED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: normal    
Priority: medium CC: jeanbaptiste.lallement
Version: unspecified   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:

Description Sebastien Bacher 2017-09-21 07:15:21 UTC
Using cairo 1.14.10 on Ubuntu, evince sibabrt when printing a document (which I got from the submitter but don't share here since it includes private info)

Backtrace

#0  0x00007f8d67db80bb in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007f8d67db9f5d in __GI_abort () at abort.c:90
#2  0x00007f8d67e0229d in __libc_message (action=action@entry=
    do_abort, fmt=fmt@entry=0x7f8d67f29408 "*** Error in `%s': %s: 0x%s ***\n")
    at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007f8d67e0965a in malloc_printerr (action=<optimised out>, str=0x7f8d67f29740 "double free or corruption (!prev)", ptr=<optimised out>, ar_ptr=<optimised out>) at malloc.c:5423
#4  0x00007f8d67e0b74e in _int_free (av=0x7f8d6815bc20 <main_arena>, p=<optimised out>, have_lock=0) at malloc.c:4172
#5  0x00007f8d67e1040e in __GI___libc_free (mem=<optimised out>)
    at malloc.c:3142
#6  0x00007f8d6928621c in cairo_truetype_font_destroy (font=font@entry=0x556abc58ce30) at ../../../../src/cairo-truetype-subset.c:292
#7  0x00007f8d692881df in cairo_truetype_subset_init_internal (truetype_subset=truetype_subset@entry=0x7ffe160e3490, font_subset=font_subset@entry=0x7ffe160e3600, is_pdf=is_pdf@entry=1) at ../../../../src/cairo-truetype-subset.c:1226
#8  0x00007f8d69288b4a in _cairo_truetype_subset_init_pdf (truetype_subset=truetype_subset@entry=0x7ffe160e3490, font_subset=font_subset@entry=0x7ffe160e3600)
    at ../../../../src/cairo-truetype-subset.c:1242
#9  0x00007f8d692c637b in _cairo_pdf_surface_emit_truetype_font_subset (font_subset=0x7ffe160e3600, surface=0x556abcd1f5c0)
    at ../../../../src/cairo-pdf-surface.c:5436
#10 0x00007f8d692c637b in _cairo_pdf_surface_emit_unscaled_font_subset (font_subset=0x7ffe160e3600, closure=0x556abcd1f5c0)
    at ../../../../src/cairo-pdf-surface.c:5910
#11 0x00007f8d69284ce1 in _cairo_sub_font_collect (closure=0x7ffe160e35b0, entry=0x556abcb6d150) at ../../../../src/cairo-scaled-font-subsets.c:746
#12 0x00007f8d69284ce1 in _cairo_scaled_font_subsets_foreach_internal (font_subsets=<optimised out>, font_subset_callback=font_subset_callback@entry=0x7f8d692c6290 <_cairo_pdf_surface_emit_unscaled_font_subset>, closure=closure@entry=0x556abcd1f5c0, type=type@entry=CAIRO_SUBSETS_FOREACH_UNSCALED)
    at ../../../../src/cairo-scaled-font-subsets.c:1067
#13 0x00007f8d69285c77 in _cairo_scaled_font_subsets_foreach_unscaled (font_subsets=<optimised out>, font_subset_callback=font_subset_callback@entry=0x7f8d692c6290 <_cairo_pdf_surface_emit_unscaled_font_subset>, closure=closure@entry=0x556abcd1f5c0) at ../../../../src/cairo-scaled-font-subsets.c:1095
#14 0x00007f8d692c20d8 in _cairo_pdf_surface_emit_font_subsets (surface=0x556abcd1f5c0) at ../../../../src/cairo-pdf-surface.c:5956
#15 0x00007f8d692c20d8 in _cairo_pdf_surface_finish (abstract_surface=0x556abcd1f5c0) at ../../../../src/cairo-pdf-surface.c:2031
#16 0x00007f8d69268ec6 in _cairo_surface_finish (surface=0x556abcd1f5c0)
    at ../../../../src/cairo-surface.c:1033
#17 0x00007f8d69269ad7 in INT_cairo_surface_finish (surface=0x556abcd1f5c0)
    at ../../../../src/cairo-surface.c:1080
#18 0x00007f8d6923dc8f in _cairo_paginated_surface_finish (abstract_surface=0x556abcd189b0) at ../../../../src/cairo-paginated-surface.c:213
#19 0x00007f8d69268ec6 in _cairo_surface_finish (surface=0x556abcd189b0)
    at ../../../../src/cairo-surface.c:1033
#20 0x00007f8d69269ad7 in INT_cairo_surface_finish (surface=0x556abcd189b0)
    at ../../../../src/cairo-surface.c:1080
#21 0x00007f8d6a458b17 in unix_end_run (op=0x556abc2d5430, wait=0, cancelled=0)
    at ././gtk/gtkprintoperation-unix.c:373
#22 0x00007f8d6a32a5f8 in print_pages_idle (user_data=0x556abcd048c0)
    at ././gtk/gtkprintoperation.c:2935
#23 0x00007f8d69dc7b90 in gdk_threads_dispatch (data=0x556abc48fa00)
    at ././gdk/gdk.c:743
Comment 1 Sebastien Bacher 2017-09-21 07:17:34 UTC
valgrind reports an invalid read error

==7173== Invalid write of size 8
==7173==    at 0x6C86FD7: cairo_truetype_font_write_glyf_table (cairo-truetype-subset.c:690)
==7173==    by 0x6C8858B: cairo_truetype_font_generate (cairo-truetype-subset.c:978)
==7173==    by 0x6C8858B: cairo_truetype_subset_init_internal (cairo-truetype-subset.c:1146)
==7173==    by 0x6CC637A: _cairo_pdf_surface_emit_truetype_font_subset (cairo-pdf-surface.c:5436)
==7173==    by 0x6CC637A: _cairo_pdf_surface_emit_unscaled_font_subset (cairo-pdf-surface.c:5910)
==7173==    by 0x6C84CE0: _cairo_sub_font_collect (cairo-scaled-font-subsets.c:746)
==7173==    by 0x6C84CE0: _cairo_scaled_font_subsets_foreach_internal (cairo-scaled-font-subsets.c:1067)
==7173==    by 0x6CC20D7: _cairo_pdf_surface_emit_font_subsets (cairo-pdf-surface.c:5956)
==7173==    by 0x6CC20D7: _cairo_pdf_surface_finish (cairo-pdf-surface.c:2031)
==7173==    by 0x6C68EC5: _cairo_surface_finish (cairo-surface.c:1033)
==7173==    by 0x6C69AD6: cairo_surface_finish (cairo-surface.c:1080)
==7173==    by 0x6C3DC8E: _cairo_paginated_surface_finish (cairo-paginated-surface.c:213)
==7173==    by 0x6C68EC5: _cairo_surface_finish (cairo-surface.c:1033)
==7173==    by 0x6C69AD6: cairo_surface_finish (cairo-surface.c:1080)
==7173==    by 0x5B0DB16: unix_end_run (gtkprintoperation-unix.c:373)
==7173==    by 0x59DF5F7: print_pages_idle (gtkprintoperation.c:2935)
==7173==    by 0x6097B8F: gdk_threads_dispatch (gdk.c:743)
==7173==    by 0x776ADE4: g_main_context_dispatch (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.0)
==7173==    by 0x776B1AF: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.0)
==7173==    by 0x776B23B: g_main_context_iteration (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.0)
==7173==    by 0x6FAEBEC: g_application_run (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.5400.0)
==7173==    by 0x127C97: main (main.c:316)
==7173==  Address 0x166d0558 is 8 bytes after a block of size 160 alloc'd
==7173==    at 0x4C31B25: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7173==    by 0x6C87FAF: _cairo_truetype_font_create (cairo-truetype-subset.c:205)
==7173==    by 0x6C87FAF: cairo_truetype_subset_init_internal (cairo-truetype-subset.c:1134)
==7173==    by 0x6CC637A: _cairo_pdf_surface_emit_truetype_font_subset (cairo-pdf-surface.c:5436)
==7173==    by 0x6CC637A: _cairo_pdf_surface_emit_unscaled_font_subset (cairo-pdf-surface.c:5910)
==7173==    by 0x6C84CE0: _cairo_sub_font_collect (cairo-scaled-font-subsets.c:746)
==7173==    by 0x6C84CE0: _cairo_scaled_font_subsets_foreach_internal (cairo-scaled-font-subsets.c:1067)
==7173==    by 0x6CC20D7: _cairo_pdf_surface_emit_font_subsets (cairo-pdf-surface.c:5956)
==7173==    by 0x6CC20D7: _cairo_pdf_surface_finish (cairo-pdf-surface.c:2031)
==7173==    by 0x6C68EC5: _cairo_surface_finish (cairo-surface.c:1033)
==7173==    by 0x6C69AD6: cairo_surface_finish (cairo-surface.c:1080)
==7173==    by 0x6C3DC8E: _cairo_paginated_surface_finish (cairo-paginated-surface.c:213)
==7173==    by 0x6C68EC5: _cairo_surface_finish (cairo-surface.c:1033)
==7173==    by 0x6C69AD6: cairo_surface_finish (cairo-surface.c:1080)
==7173==    by 0x5B0DB16: unix_end_run (gtkprintoperation-unix.c:373)
==7173==    by 0x59DF5F7: print_pages_idle (gtkprintoperation.c:2935)
==7173==    by 0x6097B8F: gdk_threads_dispatch (gdk.c:743)
==7173==    by 0x776ADE4: g_main_context_dispatch (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.0)
==7173==    by 0x776B1AF: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.0)
==7173==    by 0x776B23B: g_main_context_iteration (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5400.0)
==7173==    by 0x6FAEBEC: g_application_run (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.5400.0)
==7173==    by 0x127C97: main (main.c:316)

let me know if you need more debug info
Comment 2 Bryce Harrington 2017-09-21 16:49:47 UTC
It's crashing trying to free a font:

    free (font->glyphs);

So would probably be useful to know what fonts are being used in the document.  Perhaps the reporter could construct a PoC using the same fonts as in the crashing doc and see if they crash that one too.
Comment 3 Jean-Baptiste Lallement 2017-09-21 16:57:42 UTC
I don't have the source of the document and the fonts with which it's been built but according to the content of the pdf it references the following fonts:

ComicSansMS,Bold
Helvetica
Helvetica-Bold
Helvetica-Oblique
MSShellDlg,Bold
Comment 4 Uli Schlachter 2017-09-21 19:12:24 UTC
> ==7173== Invalid write of size 8
> ==7173==    at 0x6C86FD7: cairo_truetype_font_write_glyf_table (cairo-truetype-subset.c:690)
> ==7173==    by 0x6C8858B: cairo_truetype_font_generate (cairo-truetype-subset.c:978)
> ==7173==    by 0x6C8858B: cairo_truetype_subset_init_internal (cairo-truetype-subset.c:1146)
[...]
> ==7173==  Address 0x166d0558 is 8 bytes after a block of size 160 alloc'd
> ==7173==    at 0x4C31B25: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
> ==7173==    by 0x6C87FAF: _cairo_truetype_font_create (cairo-truetype-subset.c:205)
> ==7173==    by 0x6C87FAF: cairo_truetype_subset_init_internal (cairo-truetype-subset.c:1134)


Line 690 is

> font->glyphs[i].location = next - start_offset;

The only statement modifying variable i is:

> for (i = 0; i < font->base.num_glyphs; i++) {

Since the above line is outside of this for-loop, i is at most font->base.num_glyphs.

Looking a bit more at the callers, init_internal allocates the font with _cairo_truetype_font_create(), which does:

> font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t));

(I think) "num_glyphs_in_face" is (supposed to be) the number of glyphs in the original font and "base.num_glyphs" is the number of glyphs which ended up in the subsetted font. No idea why this manages to subset more glyphs than the font even has. There are more numbers involved here (cairo_truetype_subset_init_internal() uses font->scaled_font_subset->num_glyphs...).

Behdad, ideas?

@Sebastian: You could try adding assert(font->base.num_glyphs < font->num_glyphs_in_face); before the end of cairo_truetype_font_use_glyph(). This assert should trigger earlier than what valgrind can detect (ignore the error which is only detected during free(), that's longer after things went wrong). Hopefully the backtrace for this one would be more useful, but I am just guessing here.
Comment 5 Sebastien Bacher 2017-09-22 06:27:25 UTC
> Hopefully the backtrace for this one would be more useful, but I am just guessing here.

backtrace is

#1  0x00007ffff48bef5d in __GI_abort () at abort.c:90
#2  0x00007ffff48b4f17 in __assert_fail_base (fmt=<optimised out>, assertion=assertion@entry=0x7ffff5de0e18 "font->base.num_glyphs < font->num_glyphs_in_face", file=file@entry=0x7ffff5de0e00 "cairo-truetype-subset.c", line=line@entry=1029, function=function@entry=0x7ffff5de0e80 <__PRETTY_FUNCTION__.11613> "cairo_truetype_font_use_glyph") at assert.c:92
#3  0x00007ffff48b4fc2 in __GI___assert_fail (assertion=assertion@entry=0x7ffff5de0e18 "font->base.num_glyphs < font->num_glyphs_in_face", file=file@entry=0x7ffff5de0e00 "cairo-truetype-subset.c", line=line@entry=1029, function=function@entry=0x7ffff5de0e80 <__PRETTY_FUNCTION__.11613> "cairo_truetype_font_use_glyph")
    at assert.c:101
#4  0x00007ffff5d8da79 in cairo_truetype_font_use_glyph (font=<optimised out>, glyph=<optimised out>, out=<optimised out>) at cairo-truetype-subset.c:1029
#5  0x00007ffff5d8f63f in cairo_truetype_subset_init_internal (truetype_subset=truetype_subset@entry=0x7fffffffd840, font_subset=font_subset@entry=0x7fffffffd9b0, is_pdf=is_pdf@entry=1) at cairo-truetype-subset.c:1142
#6  0x00007ffff5d8ffea in _cairo_truetype_subset_init_pdf (truetype_subset=truetype_subset@entry=0x7fffffffd840, font_subset=font_subset@entry=0x7fffffffd9b0)
    at cairo-truetype-subset.c:1244
#7  0x00007ffff5dceb8b in _cairo_pdf_surface_emit_truetype_font_subset (font_subset=0x7fffffffd9b0, surface=0x55555621aad0) at cairo-pdf-surface.c:5436
#8  0x00007ffff5dceb8b in _cairo_pdf_surface_emit_unscaled_font_subset (font_subset=0x7fffffffd9b0, closure=0x55555621aad0) at cairo-pdf-surface.c:5910
#9  0x00007ffff5d8c20e in _cairo_sub_font_collect (closure=0x7fffffffd960, entry=0x55555605bc00) at cairo-scaled-font-subsets.c:746
#10 0x00007ffff5d8c20e in _cairo_scaled_font_subsets_foreach_internal (font_subsets=<optimised out>, font_subset_callback=font_subset_callback@entry=0x7ffff5dceaa0 <_cairo_pdf_surface_emit_unscaled_font_subset>, closure=closure@entry=0x55555621aad0, type=type@entry=CAIRO_SUBSETS_FOREACH_UNSCALED)
    at cairo-scaled-font-subsets.c:1067
#11 0x00007ffff5d8d0b7 in _cairo_scaled_font_subsets_foreach_unscaled (font_subsets=<optimised out>, font_subset_callback=font_subset_callback@entry=0x7ffff5dceaa0 <_cairo_pdf_surface_emit_unscaled_font_subset>, closure=closure@entry=0x55555621aad0) at cairo-scaled-font-subsets.c:1095
#12 0x00007ffff5dca673 in _cairo_pdf_surface_emit_font_subsets (surface=0x55555621aad0) at cairo-pdf-surface.c:5956
#13 0x00007ffff5dca673 in _cairo_pdf_surface_finish (abstract_surface=0x55555621aad0) at cairo-pdf-surface.c:2031
#14 0x00007ffff5d70486 in _cairo_surface_finish (surface=0x55555621aad0)
    at cairo-surface.c:1033
#15 0x00007ffff5d710b7 in INT_cairo_surface_finish (surface=0x55555621aad0)
    at cairo-surface.c:1080
#16 0x00007ffff5d43365 in _cairo_paginated_surface_finish (abstract_surface=0x555556197e90) at cairo-paginated-surface.c:213
#17 0x00007ffff5d70486 in _cairo_surface_finish (surface=0x555556197e90)
    at cairo-surface.c:1033
#18 0x00007ffff5d710b7 in INT_cairo_surface_finish (surface=0x555556197e90)
    at cairo-surface.c:1080
#19 0x00007ffff6f5fb17 in unix_end_run (op=0x55555583a430, wait=0, cancelled=0)
    at ././gtk/gtkprintoperation-unix.c:373
#20 0x00007ffff6e315f8 in print_pages_idle (user_data=0x555555f9f840)
    at ././gtk/gtkprintoperation.c:2935
#21 0x00007ffff68ceb90 in gdk_threads_dispatch (data=0x5555559cb820)
    at ././gdk/gdk.c:743
#22 0x00007ffff5225de5 in g_main_context_dispatch ()
    at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#23 0x00007ffff52261b0 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
Comment 6 Adrian Johnson 2017-09-22 07:11:35 UTC
The font is broken in some way. The backtrace doesn't help because the problem occurred earlier when it was parsing some data out of the font. There is not much I can do without the pdf.
Comment 7 Sebastien Bacher 2017-09-22 07:20:50 UTC
The issue was not there in .6, bisecting the commits it started with 
"scaled-font-subsets: if glyph 0 used for rendering, remap to different index"
Comment 9 Sebastien Bacher 2017-09-26 15:41:25 UTC
could that fix be backported to the 1.14 serie?
Comment 10 Adrian Johnson 2017-09-26 20:27:33 UTC
Patch should work with 1.14.
Comment 11 Sebastien Bacher 2017-09-26 20:30:42 UTC
right, I backported it to Ubuntu but I was wondering if it would make sense to be commited upstream to the stable serie as well
Comment 12 Adrian Johnson 2017-09-26 21:15:27 UTC
If there is another 1.14 release it will be included.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.