Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Psych.dump raises Encoding::CompatibilityError for UTF-16/UTF-32 strings

オープン
#819 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

@Halvanhelv がすでに取り組んでいます。

2026年9月10日 から。

  • #820 @Halvanhelv による — オープン

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
55/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
ruby, yaml
領域
backend

調査の方向性

lib/psych/visitors/yaml_tree.rb の303、313、316行付近にある Psych::Visitors::YAMLTree#visit_String を調べてください。まず test/psych/test_encoding.rb の UTF-16 エンコーディングのカバレッジ(test_transcode_utf16le と test_transcode_utf16be を含む)を確認し、その後、UTF-16/32 文字列がエンコーディングエラーなしでダンプされ、同等の UTF-8 文字列と同様にラウンドトリップすることを検証してください。

索引モデルが issue の本文から書いたものです。

説明

Summary

Psych.dump raises Encoding::CompatibilityError for any string in a non-ASCII-compatible encoding (UTF-16LE/BE, UTF-32LE/BE). An empty string is enough to trigger it.

This is asymmetric with the load side: Psych.load explicitly supports UTF-16 input and has tests for it (test_transcode_utf16le / test_transcode_utf16be in test/psych/test_encoding.rb), but dumping a UTF-16 string crashes.

require "psych"

Psych.load("--- こんにちは!".encode("UTF-16LE"))  # => "こんにちは!"  (works)
Psych.dump("".encode("UTF-16LE"))                  # => raises
Encoding::CompatibilityError: incompatible encoding regexp match (US-ASCII regexp with UTF-16LE string)
    lib/psych/visitors/yaml_tree.rb:303:in 'String#match?'
    lib/psych/visitors/yaml_tree.rb:303:in 'Psych::Visitors::YAMLTree#visit_String'

Affects every dump entry point: Psych.dump, YAML.dump, and to_yaml on a String, or on any Hash/Array/nested structure containing one — including when the string is used as a hash key.

Cause

visit_String matches the string against US-ASCII regexp literals:

  • yaml_tree.rb:303 — o.match?(/\n(?!\Z)/)
  • yaml_tree.rb:313 — o.match?(/^[^[:word:]][^"]*$/)
  • yaml_tree.rb:316 — /\A0[0-7]*[89]/.match?(o)

A string whose encoding is not ASCII-compatible cannot be matched against an ASCII regexp at all, so the first of these raises regardless of the string's content.

The guard above them only covers ASCII_8BIT:

def binary? string
  string.encoding == Encoding::ASCII_8BIT && !string.ascii_only?
end

so UTF-16/32 falls straight through.

Which encodings are affected

The crashing set maps exactly onto Encoding#ascii_compatible?:

encoding ascii_compatible? Psych.dump
UTF-8, ISO-8859-1, EUC-JP, Windows-1252, Shift_JIS, ASCII-8BIT true works
UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE false raises

Every other non-UTF-8 encoding transcodes and round-trips correctly, which suggests the UTF-16/32 family is simply an unhandled case rather than a deliberate restriction.

Expected

A UTF-16/32 string should dump like the equivalent UTF-8 string does — it should not be tagged !binary, and it should round-trip.

Environment

Reproduced on psych 5.4.0 (Ruby 4.0.4) and on master 79be592f1dbe3c6eb36d4e1015b8379207158a75 (5.5.0), same file and line on both.

I have a patch and will open a PR referencing this issue.

主要言語
Ruby
スター
597
フォーク
223
平均マージ
6時間 8分
マージ済み PR(30日)
2

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

ruby/psych のほかの issue

ruby/psych の issue をすべて見る

似ている issue

Ruby の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。