YamaKen
yamak****@bp*****
2005年 8月 24日 (水) 12:18:58 JST
ヤマケンです。 At Tue, 23 Aug 2005 17:57:28 -0700, jun.l****@gmail***** wrote: > これの追跡中に確認してみたのですが、スタック保護が正しく使えていません。例えば > Scm_eval_c_string() に次のようなコードがありますが、 > > ScmObj stack_start; > ScmObj str_port = SCM_NIL; > ScmObj ret = SCM_NIL; > > SigScm_gc_protect_stack(&stack_start); > > これを gcc (GCC) 4.0.1 20050617 (prerelease) (Debian 4.0.0-10) (IA32) で > コンパイルして、protect の直前で状態を調べると > (gdb) p &stack_start > $6 = (ScmObj *) 0xbfffe7d8 > (gdb) p &str_port > $7 = (ScmObj *) 0xbfffe7dc > (gdb) p $sp > $12 = (void *) 0xbfffe7d0 > で、%esp < &stack_start < &str_port となっていて、str_port が保護されて > いません。 これはまずいですね。 v> スタック保護は uim_init() で有効にして、ずっとつけっぱなしにしたほうがい > いと思います。限界まで conservative GC の false positive を減らしたい人 > の為に protect, unprotect は export したままでいいと思いますが、uim はそ > れにあたりませんので。 この方法はuimでは無理です。以下の例を見てください。 void init(void) { char foo[4096]; uim_init(); } int main(void) { init(); uim_bar(); } uim_init()のみでスタック保護開始点を設定すると、uim_bar()は保護 されてないスタック領域上で呼ばれる事になってしまいます。 この例のようにuim_init()の呼び出し位置をアプリケーション作者が制 御できるなら回避できますが、GUIツールキットの利用に伴って暗黙に 呼ばれるような場合ではスタック位置を保証できません。 At Tue, 23 Aug 2005 19:09:06 -0700, jun.l****@gmail***** wrote: > 他の方法でこれを解決するなら、uim の uim-scm.c で全ての uim-scheme API > について protect→unprotect だけをする wrapper を用意することになります。 > 多分自動 inline 回避の為に別ファイルに分けて。 uim APIの保護はuim_scm_eval_c_string()とuim_scm_eval()だけに仕掛 ければ大丈夫です。 libsscmや、uim APIを経由せずuim-scm APIを直接扱うコードではその ように自前でwrapper を用意して保護してもらう必要がありますね。 void a_wrapper(void) { ScmObj stack_start; Scm_gc_protect(&stack_start); /* cannot be expanded as inline block to avoid stack order inversion */ must_be_protected(); Scm_gc_unprotect(&stack_start); } void must_be_protected(void) { ScmObj x; x = Scm_foo(); } C99ならvariadic macroで解決できるんで、libsscmのユーザ向けには C99環境用のオプショナルなwrapperマクロを提供するあたりでどうでしょ う。uim APIを経由しないuim-scm APIの利用ではC89対応の手書き推奨 という事で。 ------------------------------- ヤマケン yamak****@bp*****