The Man Who Fell From The Wrong Side Of The Sky:2010年3月6日分

[最新版] [一覧] [前月] [今月] [翌月]

2010/3/6(Sat)

[NetBSD] libedit I18N への道 (その5.3)

@ この patch は出来そこないだ。食べられないよ by 山岡士郎

さてさて、いろいろ ガラガラ崩れはじめとりますが、もういっちょ救いようのない
問題を発見してしまいましたが、俺はもう限界かもしれない。

editline(3)には以下の機能があります。

     el_set()
           Set editline parameters.  op determines which parameter to set, and
           each operation has its own parameter list.

           The following values for op are supported, along with the required
           argument list:

           EL_GETCFN, int (*f)(EditLine *, char *c)
                 Define the character reading function as f, which is to
                 return the number of characters read and store them in c.
                 This function is called internally by el_gets() and
                 el_getc().  The builtin function can be set or restored with
                 the special function name ``EL_BUILTIN_GETCFN''.

要するに tty(4) から文字(列)を読み込むための関数を override できる機能なのです。
EL_BUILTIN_GETCFN というのは正に 第3回でいじった read_char() そのものです。

さっそく el.c のコードをみてみませう。

281 	case EL_GETCFN:
282 	{
283 		el_rfunc_t rc = va_arg(ap, el_rfunc_t);
284 		rv = el_read_setfn(el, rc);
285 		el->el_flags &= ~NARROW_READ;
286 		break;
287 	}

el_set(3)の引数は可変引数リストですので、283行目で va_arg(3) を使って取得します。
ここでは override するint (*f)(Editline *, char *)型の関数ポインタは
read.h で typedef される el_rfunc_t となっとるのですが、で・す・が。

@@ -35,7 +35,7 @@
 #ifndef        _h_el_read
 #define        _h_el_read

-typedef int (*el_rfunc_t)(EditLine *, char *);
+typedef int (*el_rfunc_t)(EditLine *, Char *);

 typedef struct el_read_t {
        el_rfunc_t      read_char;      /* Function to read a character */

ぎゃー勝手にインタフェースを char -> Char(=wchar_t) に変更してやがんの。
これはひどい、ひどすぎる。

お分かりだと思いますが、これバイナリの後方互換をパーペキに失ってます。
後方互換を失うって何?という人は 以前の記事読んでください。

ですので古いバイナリが int (*)(EditLine *, char *) の関数ポインタを新しい libedit に渡してしまい
int (*)(EditLine *, wchar_t*)として呼ばれたら、まずまともに動かないことでしょう。

ま唯一の救いは、新しい libeditは char よりも大きな wchar_t のサイズを持つ
記憶領域へのポインタを古いバイナリ側が用意した override 関数に渡すので
まずbuffer overflow は発生しないだろうということくらいっすか。
# つったって、(この機能を使ってないとはいえ)sh(1)とかちょー重要なアプリがリンクするライブラリでこれはねーよ…

ということで、次回からは1月の変更をすべて Reset / Mutemathして(笑)
libedit を一から i18n 化する連載ということでwwwちょwww


[ホームへ] [ページトップへ]