2010/03/06(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