[Anthy-dev 2276] Re: r5rs: Scm_eval_c_string バグ, スタック保護

Back to archive index

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*****



Anthy-dev メーリングリストの案内
Back to archive index