セキュリティ&プログラミングキャンプ「Rubyのバグを探せ」問題

これはセキュリティ&プログラミングキャンプのCTF競技(タイムトライアルのチーム戦)で出題された問題です。Ruby処理系へのバグの仕込みと問題文の原稿を僕が書き、竹迫さんが競技環境で実行するための調査や加筆を行ってくれました。参加者のShota Fukumori (sora_h)が「21日に『セプキャン行ってきたトーク』するから早く公開しろ」というので、取り急ぎ公開します。

問題文

これはプログラミング言語クラスでのタイムトライアル処理系デバッグ演習のために作られた、バグの混入してあるRuby処理系のソースコードです。C言語で書かれています。誰も着手しなかった「veryhard」の問題なので、解説を加筆してCTFの問題とします。

言語クラスではRuby処理系のビルドの仕方やテストのためのツールを2日目に演習し、3日目の朝に「1時間で8問のバグを易しい順に倒す演習」(タイムトライアル処理系デバッグ)をやりました。演習を受けていない人でも着手できるように、Rubyのビルド方法を改めて書いておきます。

$ mkdir build
$ cd build
$ ../configure --disable-gems --disable-install-docs
$ make

これで本来はmakeに成功するはずですが、rubyコマンドがビルドされた後、Rubyにバグが入っているためmake中に自動で走るmake testが失敗します。

$ make
/.../veryhard/lib/fileutils.rb:1399:in `quote': can't convert
NilClass to String (TypeError)
       from /.../veryhard/lib/fileutils.rb:1399:in `<class:Entry_>'
       from /.../veryhard/lib/fileutils.rb:1092:in `<module:FileUtils>'
       from /.../veryhard/lib/fileutils.rb:85:in `<top (required)>'
       from ../tool/mkconfig.rb:11:in `require'
       from ../tool/mkconfig.rb:11:in `<main>'
make: *** [.rbconfig.time] Error 1

make runやmake gdbを使うと(src)/test.rbが実行されます。自分で好きな内容をtest.rbに書いてmake runしてみてください。で、このバグ入り処理系はなにか「常識的に考えておかしいだろこれ」という挙動をするはずなので、原因となるバグを見つけ出し、処理系が正しく動くようにCで書かれたコードを修正してください。

添付したtest.rbはおかしな挙動の一つの例として、下記のように「素数を計算しようとしてThread.rbがエラーを吐く」という意味不明なものにしてあります。しかしtest.rbは「バグを再現するための最小限のコード」にした方がいいでしょう。

$ make run
./miniruby -I../lib -I.ext/common -I./- -r../ext/purelib.rb  ../test.rb
/.../veryhard/lib/thread.rb:11:in `<top (required)>': Thread not
available for this ruby interpreter (RuntimeError)
       from /.../veryhard/lib/singleton.rb:63:in `require'
       from /.../veryhard/lib/singleton.rb:63:in `<top (required)>'
       from /.../veryhard/lib/prime.rb:14:in `require'
       from /.../veryhard/lib/prime.rb:14:in `<top (required)>'
       from ../test.rb:1:in `require'
       from ../test.rb:1:in `<main>'
make: *** [run] Error 1

このRuby処理系のバグを直すために修正されるべきファイル名と行番号を回答してください。たとえばspcamp.cの2403行目であれば「spcamp.c:2403」が回答となります。2行以上の修正が必要な場合は、修正を開始する行目を回答としてください。

なお、VM環境で走らせていることなどが原因でgc周りでのテストにコケることがありますが、これはこの課題の意図したものではありません。またmakeしたrubyをmake installしないで使うとgems(パッケージ管理)周辺でコケることがありますが、これも意図したものではありません。

※BackTrack 4 Live CD (Ubuntu8.10) でビルドできるようにしています。

余談

大雑把に言って、10分以内に解けたらmoriyoshi級で、10時間以内で解けたらsora_h級。(sora_hは他の問題も解きつつ6時間掛けて解けなかったが、その後帰ってきて僕の「( https://gist.github.com/1145883 )」というヒントを聞いてノータイムで「◯◯か!」と答えたのでオーダーとしては10時間ってことでいいかなーと。)

他の大人の所要時間:

knu:「Rubyのバグを探せ」はソース取得から10分掛からなかったが、ホームだし当然か。実際のバグはこんな単純じゃないしな… http://twitter.com/#!/knu/status/103037840899846144

mrkn: 解けたけど15分もかかっちゃった。http://twitter.com/#!/mrkn/status/103062497954775040

znz: 40分ぐらいで出来た。「バグを再現するための最小限のコード」は簡単に作れても、直すのは見慣れないところが対象だったから時間がかかった。 http://twitter.com/#!/znz/status/103084755758755840

余談2

言語クラス内での演習の際の、加筆のない問題文

問8 (全部クリアした人向け)

おめでとう!

ここまでの問題をクリアして時間が余ってしまった人のために、veryhard.zipが用意されています。ヒントは一切ありません。

余談3

test.rbの内容

require 'prime'
p Prime.prime? 2403

そしてその結果:

/.../veryhard/lib/thread.rb:11:in `<top (required)>': Thread not
available for this ruby interpreter (RuntimeError)