Embargo was requested on the GNOME bug yesterday, so I limited access to it. I debugged it tonight, it's a bug in pango. I plan to push a fix out to the public repository tomorrow. The following is what I wrote in response to the embargo report to me:
Thanks for the mail. Let me note that this issue has already made it to the upstream Pango bugzilla. Pedro forwarded the crash stacktrace from Ubuntu bug tracker before, but today he added a comment pointing out to the test web page. I have limited the bug to GNOME Hackers group for now:
Anyway, I debugged the issue. It happens whenever a PangoLayout is used to render text containing the Unicode character U+2028 LINE SEPERATOR, the layout is set to be ellipsized, and has a width narrow enough to ensure line wrapping. It can be reproduced using the command:
$ pango-view --markup --text 'test 
' --width 1 --ellipsize end
The invalid memory access happens in function pango_layout_line_postprocess() whenever both wrapping and ellipsization happen. However, ellipsization normally disables wrappnig. The only exception was when a LINE SEPARATOR character was seen. This particular behavior was introduced in pango version
1.21.4, in git commit 66240b30bc5a2b29b0d5f3bb5396f85ef557b077.
/* NB: the runs are in reverse order at this point, since we prepended them to the list
*/
/* Reverse the runs
*/
line->runs = g_slist_reverse (line->runs);
DEBUG ("postprocessing", line, state);
/* Ellipsize the line if necessary
*/
if (G_UNLIKELY (state->line_width >= 0 && should_ellipsize_current_line (line->layout, state)))
{
ellipsized = _pango_layout_line_ellipsize (line, state->attrs, state->line_width);
}
/* Truncate the logical-final whitespace in the line if we broke the line at it
*/
if (wrapped)
zero_line_final_space (line, state, last_run);
=============================
The problem happens when in the _pango_layout_line_ellipsize() call line is modified and now last_run is a dangling pointer. In zero_line_final_space() it is dereferenced and crashes. Apparently at the time of the crash run->glyphs is NULL. There's no immediate reason for this except that the memory is freed using gslice and perhaps immediately allocated in the same call (line_ellipsize()) and trashed.
Anyway, while my analysis is not conclusive, I doubt that this can be exploited easily. I have attached the patch for the invalid access. I have that and other patches to improve the behavior in my local tree. I have not pushed them as per your request. Please let me know when you want to make this public.
Embargo was requested on the GNOME bug yesterday, so I limited access to it. I debugged it tonight, it's a bug in pango. I plan to push a fix out to the public repository tomorrow. The following is what I wrote in response to the embargo report to me:
Thanks for the mail. Let me note that this issue has already made it to the upstream Pango bugzilla. Pedro forwarded the crash stacktrace from Ubuntu bug tracker before, but today he added a comment pointing out to the test web page. I have limited the bug to GNOME Hackers group for now:
http:// bugzilla. gnome.org/ show_bug. cgi?id= 556132
Anyway, I debugged the issue. It happens whenever a PangoLayout is used to render text containing the Unicode character U+2028 LINE SEPERATOR, the layout is set to be ellipsized, and has a width narrow enough to ensure line wrapping. It can be reproduced using the command:
$ pango-view --markup --text 'test 
' --width 1 --ellipsize end
The invalid memory access happens in function pango_layout_ line_postproces s() whenever both wrapping and ellipsization happen. However, ellipsization normally disables wrappnig. The only exception was when a LINE SEPARATOR character was seen. This particular behavior was introduced in pango version 9b0d5f3bb5396f8 5ef557b077.
1.21.4, in git commit 66240b30bc5a2b2
Here is the code involved:
======= ======= ======= ======= = line_postproces s (PangoLayoutLine *line,
ParaBreakSta te *state,
gboolean wrapped)
static void
pango_layout_
{
PangoLayoutRun *last_run = line->runs->data;
gboolean ellipsized = FALSE;
/* NB: the runs are in reverse order at this point, since we prepended them to the list
*/
/* Reverse the runs
*/
line->runs = g_slist_reverse (line->runs);
DEBUG ("postprocessing", line, state);
/* Ellipsize the line if necessary
should_ ellipsize_ current_ line (line->layout, state))) layout_ line_ellipsize (line, state->attrs, state->line_width);
*/
if (G_UNLIKELY (state->line_width >= 0 &&
{
ellipsized = _pango_
}
/* Truncate the logical-final whitespace in the line if we broke the line at it line_final_ space (line, state, last_run); ======= ======= ======= =
*/
if (wrapped)
zero_
=======
The problem happens when in the _pango_ layout_ line_ellipsize( ) call line is modified and now last_run is a dangling pointer. In zero_line_ final_space( ) it is dereferenced and crashes. Apparently at the time of the crash run->glyphs is NULL. There's no immediate reason for this except that the memory is freed using gslice and perhaps immediately allocated in the same call (line_ellipsize()) and trashed.
Anyway, while my analysis is not conclusive, I doubt that this can be exploited easily. I have attached the patch for the invalid access. I have that and other patches to improve the behavior in my local tree. I have not pushed them as per your request. Please let me know when you want to make this public.
Regards,
behdad