ruby-trunk の Marshal がバグってる件

1.9 で Time の同一のインスタンスを2つ以上含むようなオブジェクトを Marshal.dump/load すると2つ目が文字列になってしまいます。

$ cat test.rb
t = Time.now
p Marshal.load(Marshal.dump([t, t]))
$ ./ruby-trunk test.rb
[2008-03-28 09:44:03 +0900, "7P"]

ただしこれが発生するのはTimeの精度が1000nsec以下の値まであるようなシステムだけなので、MacOSXだと起きなかった。すごく人為的だけどこんなクラスを書くと発生しますね。

class A
  def initialize(a)
    @a = a
  end

  def _dump(lev=0)
    str = Marshal.dump(nil)
    str.instance_variable_set("@a", @a)
    str
  end

  def self._load(str)
    a = str.instance_variable_get("@a")
    self.new(a)
  end
end

という訳でパッチを ruby-dev に送ったんですけど、埋もれちゃってますね……。

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/34159

今思うとこのパッチだとdumpした文字列が変化するから、load 側で対応した方がいいんですけど、オブジェクトをロードしないとHashに登録できないんだけど、ロードする前にStringに付加されてるインスタンス変数のロードはやらないといけないので、ちょっとめんどうなのでした。