ruby-trunk-changes r34971 - r34988

日曜日に開発者会議があり、チケットの棚卸されたこともあってか今日はたくさん修正がありました。 json ライブラリの更新や Random、FileUtils、tmpdir、method_missing、IO#set_encoding の不具合修正などです。

naruse:r34971 2012-03-11 22:36:06 +0900

拡張ライブラリ json の最新版をマージしています。VERSION は "1.6.6" になっています。 記載されているチケット番号は JSON.parse に :object_class というオプションを利用すると SEGV するという不具合についてのものですが、その修正の他組み込みクラスの JSON エンコード/デコード対応や JSON.generate で JSON エンコードした文字列を作成する時のバッファを管理する内部で利用するクラスのリファクタリングやバッファサイズの調整を可能にするオプションの追加などがあります。 [ruby-core:41917] [Bug #5846]

naruse:r34972 2012-03-11 23:59:42 +0900

String#unpack で "M" 指示子(quoted-printable encoding 文字列のデコード)の時にパディング文字 "=" の後に改行以外の不正な文字があった時にそこで処理を止めていたのを、不正な文字だけスキップして続きを取り込むようにしています。 [ruby-dev:44875] [Bug #5635]

naruse:r34973 2012-03-12 02:42:18 +0900

r34971 の json マージの際にコミットから漏れていたファイル群を追加しています。

svn:r34974 2012-03-12 02:42:23 +0900

version.h の日付更新。

nobu:r34975 2012-03-12 06:48:45 +0900

lib/fileutils.rb の行末の空白除去。

nobu:r34976 2012-03-12 06:52:05 +0900

ext/json の新規追加になったファイルの svn property の設定です。

nobu:r34977 2012-03-12 07:03:36 +0900

Random.rand を fork した子プロセスから利用すると SEGV する不具合を修正しています。 [ruby-core:41209] [Bug #5661]

nobu:r34978 2012-03-12 07:04:13 +0900

random.c でデフォルトの乱数エンジンの VALUE 型の static 変数を持っていたのをやめて、中身の rb_random_t 構造体のほうだけ変数としては持って VALUE 型のほうは Random::DEFAULT 定数に格納するのに加えて GC のマーク対象として登録しています。

nobu:r34979 2012-03-12 07:19:06 +0900

tmpdir ライブラリで追加される Dir.tmpdir, Dir.mktmpdir で一時ディレクトリを作成する時に、親ディレクトリが world-writable なパーミッションでさらに sticky bit も立っていないような時はセキュリティ上の危険があるため、そこを一時ディレクトリ置き場として利用しないようにしています。また後始末で削除する時も同様にチェックして危険だったら削除せず例外を発生させるようにして、FileUtils.remove_entry_secure を使っていたのを FileUtils.remove_entry で削除するようにしています。日曜日の開発者会議で話題に上っていたもののようですがわたしは途中からきいていたのでちょっと定かではありませんが、JRuby で FileUtils.remove_entry_secure の処理のなかでうまくできないものがあって使わないようにしたいというようなことだったようです。

akr:r34980 2012-03-12 07:37:04 +0900

Dir.mktmpdir の動作が変化したのでそれについて rdoc と NEWS ファイルに追記しています。

naruse:r34981 2012-03-12 09:32:16 +0900

Complex のテストで lib/complex.rb がロードされていたら省くテストがあるのですが、拡張ライブラリ json に付属しているライブラリスクリプトjson/add/complex というパスなのでこれはチェック対象から外すようにしています。

nobu:r34982 2012-03-12 10:13:40 +0900

at_exit で登録したプロセス終了時の処理の中で exit を呼んだり例外が発生したり(exit も実際には SystemExit 例外の発生です)した時にそれは一旦捕捉して全ての登録された終了処理を登録の逆順に実行しておいてから最後に発生した例外が発生したかのように終了するのですが、その終了処理のなかで rescue で例外が捕捉して握り潰されるとそこで保存していた例外の情報が消えてしまっていたので、処理を呼び出した後で必要に応じて復旧するようにしています。 [ruby-core:43173] [Bug #5218]

nobu:r34983 2012-03-12 12:44:40 +0900

Object#method_missing を再定義して常に例外を発生させるようにすると、存在しないメソッドを呼んだ時に例外オブジェクトの method_missing がまた呼ばれて……と無限再帰が起きてしまうようなので Exception の method_missing, respond_to?, respond_to_missing? のメソッドを Object のメソッドと実体は同じだけどメソッドエントリは別物として再登録して Object#method_missing の再定義の影響を受けないようにしているようです。メソッドエントリのフラグとして NOEX_NOREDEF というのを追加して、Exception のこれらのメソッドエントリには付加されていますが、実際に再定義を禁止するコードが #if 0 のコメントアウトつきで書かれていますので本当に禁止はされていないですが、禁止したいみたいですね。まだ Exception#method_missing を再定義して例外を発生させると同じことが起きるのだと思います。 [ruby-core:40287] [Bug #5473]

nobu:r34984 2012-03-12 14:56:57 +0900

yield をパースした時の引数の扱いについてのフラグが NODE にセットされていましたが、これは古いもので既に命令列へのコンパイル時に使用されていないそうなので処理を削除しています。 [ruby-core:41929] [Bug #5847]

nobu:r34985 2012-03-12 19:03:36 +0900

r34983 で Exception にメソッドをコピーする時に respond_to? と respond_missing_to? を private メソッドとしてコピーしてしまっていたので public にしています。

nobu:r34986 2012-03-12 19:23:17 +0900

str_to_encindex() から String 型のオブジェクトで指定されたエンコーディングのインデックス番号を返す処理を str_find_encindex() として切り出して、rb_find_encoding() という API を追加。これを利用して IO#set_encoding に引数を2つ指定した時に不正なエンコーディング名が指定された時にはエラーになっていたのを、警告を出力してデフォルトのエンコーディングにするように修正しています。 [ruby-core:40726] [Bug #5567]

akr:r34987 2012-03-12 20:09:11 +0900

FileUtils の中で symlink が利用可能かどうかの判定に File.symlink(nil, nil) を呼んでみて NotImplementError が発生するかどうかで判定しているところで、それ以外の例外を例外クラスの指定なしの rescue で捕捉して false としていたのを TypeError を指定して捕捉するようにしています。ちなみにこれは path 名の文字列を期待している引数に nil を渡しているので TypeError が返ってくるのです。
ちなみに Ruby はこういう時 TypeError か ArgumentError か曖昧ですよね。ArgumentError が万能すぎるという指摘もありましたがこのあたり 3.0 で整理されるといいですね。

akr:r34988 2012-03-12 20:19:42 +0900

ライブラリ tmpdir.rb で追加される Dir.tmpdir で一時ディレクトリ置き場所として検討するディレクトリにカレントディレクトリ(".")も追加しています。そして適切なディレクトリがみつからなかったら専用のメッセージをつけて ArgumentError を発生させるようにしています。従来は File.expand_path に nil が渡されて結果的に TypeError が発生するようになっていたのでエラー原因がわかりにくくなっていました。