【一人 bugs.ruby Advent Calendar 2021】[Bug #17866] Incompatible changes with Psych 4.0.0【23日目】
一人 bugs.ruby Advent Calendar 2021 23日目の記事になります。
今日は Psych
が 4.0.0
にメジャーアップデートすることで非互換になる話です。
[Bug #17866] Incompatible changes with Psych 4.0.0
Psych.load
を Psych.safe_load
に置き換える PR がマージされて Psych 4.0.0 がリリースされました。
このチケットは Psych 4.0.0
が非互換になるのでそれの対応をするチケットになります。
問題点は大まかに2つあり、1つはデフォルトだとエイリアスが許可されていない問題です。
なので次のように &default
を使用している YAML ファイルを読み込むと Psych 4.0.0
ではエラーになってしまいます。
require "psych" require "date" data = <<~EOS default: &default aaa: aaa development: <<: *default EOS # Psych 4.0.0 以前 => OK 読み込める # Psych 4.0.0 以降 => NG 読み込めない pp Psych.load(data)
これの影響でいくつかの gem が対応を行っています。
- Rails : https://github.com/rails/rails/pull/42257
- Rubocop : https://github.com/rubocop/rubocop/pull/9806
このエイリアスがデフォルトで不許可になったのは再帰的なエイリアスになった場合に安全ではないケースがあるのが理由になります。
例えば以下のようなデータを読み込んだ際にの場合にクラッシュしてしまうのを防ぐためです。
require "psych" def process thing thing.each do |item| case item when Array process item when Hash # ... when String # ... end end end user_input = <<~EOS --- &1 - *1 EOS # error: stack level too deep (SystemStackError) process Psych.load(user_input)
また Psych.load
は『キーに Symbol
を定義できることを許容している』が YAML.load_file
に反映されていない問題があるようです。
# :text: という書き方が許可されてほしいが許可されていない require "psych" require "tempfile" require "yaml" Tempfile.open "example" do |file| file.write %(:text: "Hello.") file.rewind # load は OK puts "YAML Contents: #{YAML.load file}" # load_file は NG puts "YAML Contents: #{YAML.load_file file}" end
この Psych 4.0.0
は Ruby 3.1 からバンドルされる予定なので Ruby 3.1 にアップデートする際は注意する必要があります。