2008-07-13 (Sun) [長年日記]

_ [mutt][obsd]ついに MB_LEN_MAX が 1 な件で影響を受けてしまった

いろいろアップデートしてて、

なんか mutt-1.5.18 になったら hcache の subject が途中で切れておかしいな、

と思って見てみたら、charset.c で

int mutt_convert_string (char **ps, const char *from, const char *to, int flags)
{
 ...
    char *buf, *ob;
    size_t ibl, obl;
 ...
    obl = MB_LEN_MAX * ibl;
    ob = buf = safe_malloc (obl + 1);

つーのがあって、 MB_LEN_MAX が 1 だから euc-jp から utf-8 への mutt_convert_string がバッファ不足になってた。

これは openbsd-ports に報告か。 文字コードとか知らないから、説明がむずかしい。

とりあえず、こんなんじゃ日本人として使えたもんじゃないよな。送信はやめておこう。

追記

めもがきで反応をいただいた。

muttは--without-wc-funcsでbuildしてるでしたっけ?

けっきょく ports は恐いので mutt-dev に逃げたんですが、そこで書いたように、以前解説をいただいた vfprintfというか、mbrtowcの問題 がある (修正方法はわかったけど、パッチあてるのがめんどい) ので、snapshot まんまの libc + packages で使ってて気付いたのです。

つまり without-wc-funcs ナシです。

だから mutt に限って言えば

  • PR5351 を直して --without-wc-funcs にする

のが一番いいわけで、そこは変化なしです。

今回は「デフォルト libc + packages で、それなりに使えてたのが 1.5.18 で壊れちゃった」という話でした。あーややこし。

ま、それはそれとして charset.c の mutt_iconv を見てみると……よくわかりません。

EILSEQ をリプレイスしている以外は何もしないで再開してるのかな。 ちょっと今は時間切れになりそうなので、またあとで。

追記の追記

iconv に動的 realloc が必要だとすると、mutt_convert_string でやらなきゃいけないっぽい。 ほかは bufo[BUFO] とか、sizeof(bufo) とかやってるぽい。

mutt-dev は厳密にチェックするのを嫌うひとがいるから、↓こんな程度かな。

diff -r cc67b008038c charset.c
--- a/charset.c	Fri Jul 11 11:34:42 2008 +0200
+++ b/charset.c	Mon Jul 14 14:27:27 2008 +0900
@@ -391,6 +391,8 @@
     ret1 = iconv (cd, &ib, &ibl, &ob, &obl);
     if (ret1 != (size_t)-1)
       ret += ret1;
+    else /* if (errno == E2BIG) */
+      ret = -1;
     if (ibl && obl && errno == EILSEQ)
     {
       if (inrepls)
@@ -479,7 +481,19 @@
     obl = MB_LEN_MAX * ibl;
     ob = buf = safe_malloc (obl + 1);

-    mutt_iconv (cd, &ib, &ibl, &ob, &obl, inrepls, outrepl);
+    while (mutt_iconv (cd, &ib, &ibl, &ob, &obl, inrepls, outrepl) == (size_t)-1)
+    {
+      if (errno != E2BIG)
+	break;
+      /* MB_LEN_MAX*ibl may be insufficient */
+      /* XXX: "6" is a magic number */
+      dprint(4, (debugfile, "mutt_convert_string E2BIG: ibl=%u, obl=%u\n", ibl, obl));
+      len = ob - buf;
+      safe_realloc (&buf, len + (6 * ibl) + 1);
+      ob = buf + len;
+      obl = 6 * ibl;
+    }
+    iconv (cd, 0, 0, &ob, &obl);
     iconv_close (cd);

     *ob = '\0';

最後の iconv(,0,0,,) の意味がわかってなくて、 下にちょろっと出てる *ob=0 と一緒なのかどうかとか、 なんかアレだけど、明日にでも mutt-dev に投げておこう。 pdmef 氏がなんとかしてくれるだろ。

[]

«前の日記(2008-07-11 (Fri)) 最新 次の日記(2008-07-14 (Mon))»