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 で修正されてるようだ

<< 2007/12 >>
01
02 03 04 05 06 07 08
09 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

RSS