Bug #8484
Restoring conditions through the ruby method call during VM processing
Description
r41041 で、ブロック呼び出し前の VM 内の処理中に Ruby のメソッドが何らかの理由で呼ばれると argv が壊れるという問題を直しました。
具体的には、
y = Object.new
def y.s(a)
yield(a)
end
m = Object.new
def m.method_missing(*a)
super
end
assert_equal [m, nil], y.s(m){|a,b|[a,b]}
のようなコードの場合、
y.s
にm
とblock
が渡されるy.s
でyield(a)
が呼ばれるargv
が設定されるvm_invoke_block
内のVALUE * const rsp = GET_SP() - ci->argc; SET_SP(rsp);
でargv
の先頭にsp
が設定されるvm_yield_setup_args
vm_yield_setup_block_args
y.s
のブロックパラメータは2つなのに、引数は一つなので、a.to_ary
が呼ばれる (rb_check_array_type(arg0)
)method_missing
が呼ばれるsuper
が呼ばれる (このへんでvm _push_frame
が呼ばれる)vm_push_frame
のinitialize local variablesのところでargv
にnil
が代入されて破壊される
で、これ自体は argv
を対比しておいて戻せばよいです。
また、SET_SP(rsp)
のあたりは、ささださん曰く「 argv
に書き込みがない、という前提でそこは作ってるんだよね」だそうな。
しかし、「そんな前提わかるかっ」ですし、
methodの方は SAVE_RESTORE_CI(tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a"), ci);
ともうちょっとわかりやすく書いてあるので、
「頂いた問題点を元に、一度全部総点検が必要そうです」とのことですので、お願いします。
Updated by hsbt (Hiroshi SHIBATA) about 7 years ago
- Target version changed from 2.1.0 to 2.2.0
Updated by nobu (Nobuyoshi Nakada) almost 7 years ago
- Description updated (diff)
Updated by ko1 (Koichi Sasada) about 4 years ago
- Backport deleted (
1.9.3: UNKNOWN, 2.0.0: UNKNOWN)
まだ考え直してない。この間も tailcall で同じような問題があった。