Psych.dump raises Encoding::CompatibilityError for UTF-16/UTF-32 strings
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 55/100
調査の方向性
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
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
ruby/psych のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
-
Documentation
難易度 1/5 1時間未満 初心者へのやさしさ 72/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 68/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 52/100
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
似ている issue
-
Dependencies view: `getParent` loops forever on untitled documents, extension host runs out of memory対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 82/100
zerocracy/judges-action#2743 ·
メンテナーはふだん 8 日以内に返信
-
Python 3.15 support対応中かも @amnesiaof が今日担当しました。 オープンL: python L: python:uv
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
dependabot/dependabot-core#16524 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
content good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
rubyevents/rubyevents#2182 ·
メンテナーはふだん 1 日以内に返信
-
enhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
メンテナーはふだん 1 日以内に返信