他人の空似

2013 年 12 月 6 日

mrubyにバグ報告をした@その2

Filed under: 未分類 — 中の人 @ 9:23 AM

mrubyを弄る過程でいろいろバグを発見して報告したので一応書くだけ書いておきます。

MRB_NAN_BOXING次第でコンパイル結果が変わる

MRB_NAN_BOXINGという設定のON/OFF次第でコンパイルしたバイトコードが変わる=>別の環境にもっていっても動かない、というバグ。

そもそもMRB_NAN_BOXINGとはは何かというと、doubleやfloatのNaN表現に余裕があることを利用し、そこに値を入れることでmrb_valueのサイズを減らそうというもの。

なぜそれでバグが起こるかというと、mrb_vtypeというmrubyの型情報をMRB_NAN_BOXINGで入れようとしたのだが、NaNの定義上の都合から0だけは入らず、すべて+1したものを入れるようにしていました。
それをそのままバイトコード側にも反映したため、MRB_NAN_BOXING次第で型のインデックスが1ずれ、動作しなくなっていたわけです。

バグ報告をしたところ、irep_pool_typeというバイトコード内に入れる専用の型情報が用意され、そちらから実行時に変換する形で修正されました。

実際に修正された時のdiff
https://github.com/mruby/mruby/commit/71354b91cb48ff3a5c1e3c09492d18a3c30efcb9

MRB_PARSER_BUF_SIZEが65536以上でバイトコードが壊れる

MRB_PARSER_BUF_SIZEが65536以上で65536文字以上のリテラルを使おうとするとバイトコードが壊れて実行できなくなるバグ。
あくまでバイトコードのロードに失敗するだけなので、ソースコードから直に実行する場合は問題ない。

まずMRB_PARSER_BUF_SIZEが何かから説明すると、パーサーで扱う最大のリテラル長を定義したもので、子の文字数以上のリテラルはパース時にエラーとされる。

で、なぜ65536文字以上だとだめなのかは簡単で、バイトコード上ではリテラルの長さに2byteしか割り当てていないため。

コンパイル時にエラーするべきでは?と報告したところ、そもそも65536以上にすることがないと判断されたのか、設定項目から削除され、1024固定となりました。

実際に修正された時のdiff
https://github.com/mruby/mruby/commit/ed0d9f0066eb541ae4ceddf47bdd85112feccddf

コンパイル時にレジスタ使い切るとクラッシュ

mrubyのVM上のレジスタは最大で512個なのだが、これを超えて使うようなソースコードを読み込ませるとクラッシュするというもの。
具体的にはローカル変数が512個あるコードなどが当たる。
(mrubyのVMではローカル変数一つにレジスタが一つ割り当てられている)

これは単にエラー処理の実装が間違っていて、解放済みメモリーを触ってしまっているだけ。
このエラー処理に分岐するのがレジスタ使い切りぐらいしか存在しないため、エンバグ後発見されなかっただけと思われる。

実際に修正された時のdiff
https://github.com/mruby/mruby/commit/56a93a3357ab9f50a4105980e0b4d39e7d400e3b

Powered by WordPress