From: ko1@... Date: 2017-01-31T09:37:53+00:00 Subject: [ruby-dev:49972] [Ruby trunk Bug#8484] Restoring conditions through the ruby method call during VM processing Issue #8484 has been updated by Koichi Sasada. Backport deleted (1.9.3: UNKNOWN, 2.0.0: UNKNOWN) まだ考え直してない。この間も tailcall で同じような問題があった。 ---------------------------------------- Bug #8484: Restoring conditions through the ruby method call during VM processing https://bugs.ruby-lang.org/issues/8484#change-62784 * Author: Yui NARUSE * Status: Assigned * Priority: Normal * Assignee: Koichi Sasada * Target version: 2.2.0 * ruby -v: ruby 2.1.0dev (2013-06-03 trunk 41049) [x86_64-freebsd9.1] * Backport: ---------------------------------------- r41041 で、ブロック呼び出し前の VM 内の処理中に Ruby のメソッドが何らかの理由で呼ばれると argv が壊れるという問題を直しました。 具体的には、 ~~~ruby 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);` ともうちょっとわかりやすく書いてあるので、 「頂いた問題点を元に、一度全部総点検が必要そうです」とのことですので、お願いします。 -- https://bugs.ruby-lang.org/