🍣

[Bug #19841] Time オブジェクトが循環参照しているときに Marshal.dump でエラーになるバグ報告

に公開

[Bug #19841] Marshal.dump stack overflow with recursive Time

  • 次のように Time オブジェクが循環参照しているときに Marshal.dump を呼び出すと SystemStackError が発生するというバグ報告
t = Time.at(0, 1, :nanosecond)
t.instance_exec { @v = t }

# error: 'Time#_dump': stack level too deep (SystemStackError)
Marshal.dump(t)
  • Marshal.dump は循環参照にも対応しているのでえらーにならないのが期待する挙動みたいですね
  • 以下のように Time でない場合はうまく動くみたい
t = Object.new
t.instance_exec { @v = t }

dump = Marshal.dump(t)
pp Marshal.load(dump)
# => #<Object:0x00007a908de47710 @v=#<Object:0x00007a908de47710 ...>>
  • これなんですがこのケースの対応自体は可能みたいなんですが書式が変わったり、他のケースで失敗するみたいな弊害があるみたいですね
  • で^他の互換性を保つのが難しいみたいなのでこのチケットでは SyntaxError を出すのではなくてより明示的なエラーを出すように開発版の Ruby 3.5-dev で対応されました
t = Time.at(0, 1, :nanosecond)
t.instance_exec { @v = t }

Marshal.dump(t)
# Ruby 3.4 => 'Time#_dump': stack level too deep (SystemStackError)
# Ruby 3.5 -> 'Marshal.dump': can't dump recursive object using _dump() (RuntimeError)
GitHubで編集を提案

Discussion