Iceweaselが落ちるのを直した (libcairoのバグ) ― 2007年12月07日
Debian sid 環境でいつも使ってる Iceweasel が落ちるようになってしまった。しょうがないのでとりあえず Epiphany に退避してたのだけど、原因を調べてみた。
bug-buddy によって保存された backtrace を見てみるも、シンボル情報が何もない。 iceweasel-dbg などの、debug パッケージを入れてみて、
LD_LIBRARY_PATH=/usr/lib/debug:/usr/lib/debug/usr/lib iceweasel
などとして起動してみるが、落ちているのは dbg パッケージのない、libcairo の中らしい。 そこで、
apt-get source libcairo2
してソースパッケージを取りよせ、debian/controlに
Package: libcairo2-dbg Section: libdevel Priority: extra Architecture: any Depends: ${misc:Depends}, libcairo2 (= ${binary:Version}) Description: The Cairo 2D vector graphics library (debug package) (ry This package contains the shared libraries for debug.
を追加、debian/rules の
dh_strip -a
を
dh_strip -a --dbg-package=libcairo2-dbg
に変更。dch -i で debian/changelog を適当に上げて debuild -rfakeroot -us -uc してパッケージ。libcairo2-dbg を install する。
さて、再度iceweaselを起動して、bug-buddy の backtrace 出力を眺めてみると、
Thread 1 (Thread 0x2b9020db0350 (LWP 30953)): #0 0x00002b901a67034f in __libc_waitpid (pid=30982, stat_loc=0x7fff91253200, options=0) at ../sysdeps/unix/sysv/linux/waitpid.c:41 oldtype = 0 result = <value optimized out> #1 0x00002b901d569b76 in g_spawn_sync () from /usr/lib/libglib-2.0.so.0 No symbol table info available. #2 0x00002b901d569e88 in g_spawn_command_line_sync () from /usr/lib/libglib-2.0.so.0 No symbol table info available. #3 0x00002b902196e583 in ?? () from /usr/lib/gtk-2.0/modules/libgnomebreakpad.so No symbol table info available. #4 <signal handler called> No locals. #5 0x00002b901c24107c in _get_bitmap_surface (bitmap=0x409bf28, own_buffer=0, font_options=0x2a61090, surface=0x7fff91253bf8) at /tmp/libcairo-1.4.10/src/cairo-ft-font.c:745 width = 0 height = 0 stride = 0 data = <value optimized out> subpixel = <value optimized out> __PRETTY_FUNCTION__ = "_get_bitmap_surface"
となっている。#5 で落ちて、#4 で bug-buddy が起動されてるのかな。
と、アタリをつけて、libcairo2 の当該個所のソースを見る。
724 static cairo_status_t 725 _get_bitmap_surface (FT_Bitmap *bitmap, 726 cairo_bool_t own_buffer, 727 cairo_font_options_t *font_options, 728 cairo_image_surface_t **surface) 729 { 730 int width, height, stride; 731 unsigned char *data; 732 int format = CAIRO_FORMAT_A8; 733 cairo_bool_t subpixel = FALSE; 734 735 width = bitmap->width; 736 height = bitmap->rows; 737 738 switch (bitmap->pixel_mode) { 739 case FT_PIXEL_MODE_MONO: 740 stride = (((width + 31) & ~31) >> 3); 741 if (own_buffer) { 742 data = bitmap->buffer; 743 assert (stride == bitmap->pitch); 744 } else { 745 data = _cairo_malloc_ab (height, stride); 746 if (!data) { 747 _cairo_error (CAIRO_STATUS_NO_MEMORY); 748 return CAIRO_STATUS_NO_MEMORY; 749 }
745行目で落ちてるらしい。 _cairo_malloc_cb の定義を探してみる。
% find . -name "*.h" -print|xargs egrep _cairo_malloc_ab (ry ./src/cairo-malloc-private.h:#define _cairo_malloc_ab(a, size) \ (ry
とのことで、cairo-malloc-private.h を見る。
#define _cairo_malloc_ab(a, size) \ ((unsigned) (a) >= INT32_MAX / (unsigned) (size) ? NULL : \ mallocunsigned) (a) * (unsigned) (size )
これと上記コードを突きあわせてみると、 _cairo_malloc_cb の 第二引数が ゼロの場合に division by zero エラーが発生しそうだ。で、backtrace を見てみると、 確かに、stride がゼロだ。stride は 740 行により、width がゼロならゼロになる。
さて、これを回避するには、と、libcairo の開発状況を調べにいく。
cairo 1.4.12 release available
を見ると、あやしいものが。
* Avoid crash for zero-sized bitmap glyph (Chris Wilson)
これっぽいな。repositry を覗いてみる。このバグレポを反映して、コミットされている。
というわけで、1.4.12 に upgrade したら直った。
2007.12.10追記
libcairo2 の 1.4.10-1.2 で修正されてるようだ
最近のコメント