GNOME Bugzilla – Bug 724565
Buffer overflow in pango_glyph_item_get_logical_widths
Last modified: 2014-04-09 23:40:24 UTC
It can be reproduced using valgrind: valgrind pango-view -w 470 --text 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAⶼ??>' The non-latin character is the 'ETHIOPIC SYLLABLE CCHEE' unicode character (http://www.fileformat.info/info/unicode/char/2dbc/index.htm) The invalid write and read with stack traces as reported by valgrind: ==31315== Invalid write of size 4 ==31315== at 0x3C67C1C110: pango_glyph_item_get_logical_widths (pango-glyph-item.c:823) ==31315== by 0x3C67C0D67F: process_item (pango-layout.c:3409) ==31315== by 0x3C67C201D9: pango_layout_check_lines (pango-layout.c:3651) ==31315== by 0x3C67C21BC7: pango_layout_get_extents_internal (pango-layout.c:2534) ==31315== by 0x3C67C21FF5: pango_layout_get_pixel_extents (pango-layout.c:2755) ==31315== by 0x404F64: output_body (viewer-render.c:214) ==31315== by 0x405A55: do_output (viewer-render.c:312) ==31315== by 0x407E76: pangocairo_view_render (viewer-pangocairo.c:338) ==31315== by 0x40473E: main (viewer-main.c:65) ==31315== Address 0x4fecf10 is 0 bytes after a block of size 16 alloc'd ==31315== at 0x4A06409: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==31315== by 0x3C64C4D82E: g_malloc (gmem.c:159) ==31315== by 0x3C67C0D669: process_item (pango-layout.c:3408) ==31315== by 0x3C67C201D9: pango_layout_check_lines (pango-layout.c:3651) ==31315== by 0x3C67C21BC7: pango_layout_get_extents_internal (pango-layout.c:2534) ==31315== by 0x3C67C21FF5: pango_layout_get_pixel_extents (pango-layout.c:2755) ==31315== by 0x404F64: output_body (viewer-render.c:214) ==31315== by 0x405A55: do_output (viewer-render.c:312) ==31315== by 0x407E76: pangocairo_view_render (viewer-pangocairo.c:338) ==31315== by 0x40473E: main (viewer-main.c:65) ==31315== ==31315== Invalid read of size 4 ==31315== at 0x3C67C1C121: pango_glyph_item_get_logical_widths (pango-glyph-item.c:827) ==31315== by 0x3C67C0D67F: process_item (pango-layout.c:3409) ==31315== by 0x3C67C201D9: pango_layout_check_lines (pango-layout.c:3651) ==31315== by 0x3C67C21BC7: pango_layout_get_extents_internal (pango-layout.c:2534) ==31315== by 0x3C67C21FF5: pango_layout_get_pixel_extents (pango-layout.c:2755) ==31315== by 0x404F64: output_body (viewer-render.c:214) ==31315== by 0x405A55: do_output (viewer-render.c:312) ==31315== by 0x407E76: pangocairo_view_render (viewer-pangocairo.c:338) ==31315== by 0x40473E: main (viewer-main.c:65) ==31315== Address 0x4fecf10 is 0 bytes after a block of size 16 alloc'd ==31315== at 0x4A06409: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==31315== by 0x3C64C4D82E: g_malloc (gmem.c:159) ==31315== by 0x3C67C0D669: process_item (pango-layout.c:3408) ==31315== by 0x3C67C201D9: pango_layout_check_lines (pango-layout.c:3651) ==31315== by 0x3C67C21BC7: pango_layout_get_extents_internal (pango-layout.c:2534) ==31315== by 0x3C67C21FF5: pango_layout_get_pixel_extents (pango-layout.c:2755) ==31315== by 0x404F64: output_body (viewer-render.c:214) ==31315== by 0x405A55: do_output (viewer-render.c:312) ==31315== by 0x407E76: pangocairo_view_render (viewer-pangocairo.c:338) ==31315== by 0x40473E: main (viewer-main.c:65) ==31315== I've started digging into what's going on, but couldn't identify the root of the problem. It may also be in harfbuzz. So here is what I know. The function iterates over clusters, and uses the pango_glyph_item_iter_next_cluster function for this. The pango_glyph_item_iter_next_cluster function uses the glyph_item->glyphs->log_clusters array for determining the cluster boundaries. The problem is that the log_clusters value for the non-latin character is -51. This causes the iter->end_index to be set to 0, and then this causes the second parameter to the pango_utf8_strlen function to be negative. In this case, the pango_utf8_strlen counts the character until it reaches the null separator. In this case, it will be 4, so the character length of the first cluster is set to 4. The length of the second cluster is 1, and the width value for the second cluster is written to offset 5 in the logical_widths array. This is an overflow, since the array was initialized for 4 integers (16 bytes as valgrind reports) based on item->num_chars by process_item (pango-layout.c:3408). The -51 value comes from basic_engine_shape in basic-fc.c This function gets a hb_glyph_info_t structure from the harfbuzz hb_buffer_get_glyph_infos function to calculate the log_clusters array. So maybe it's a hurfbuzz bug, but I don't know how this harfbuzz API should work, so I suppose that it's working correctly.
*** This bug has been marked as a duplicate of bug 723582 ***