Fix Gem::YAMLSerializer roundtrip of quoted metadata keys and values#9617
Merged
Conversation
Metadata may contain any UTF-8 keys and values, but the emitter wrote strings wrapped in quotes as plain scalars and never quoted mapping keys, so quotes were stripped on load and keys containing ": " or "#" misparsed. When a quoted key appeared first in a nested mapping, the whole mapping was swallowed as a scalar and the remaining pairs leaked into top-level specification attributes, raising NameError. The parser also kept Psych's quote wrappers in mapping keys when reading gems packaged by Psych-based RubyGems. Quote emitted strings that would be misread back, parse quoted mapping keys on load, and treat "#" as a comment only when preceded by whitespace, matching Psych in both directions. Fix #9560 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves Gem::YAMLSerializer so gemspec metadata containing quotes and other special characters can be emitted and parsed in a way that roundtrips correctly (including Psych-style quoted mapping keys).
Changes:
- Expanded parser support to recognize quoted mapping keys and refined handling of
#as a comment delimiter. - Updated emitter quoting rules so keys/values that would otherwise be misread are emitted as quoted scalars.
- Added/expanded tests covering quoted keys/values and special-character metadata cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
test/rubygems/test_gem_safe_yaml.rb |
Adds roundtrip and compatibility tests for quoted/special metadata keys and values. |
lib/rubygems/yaml_serializer.rb |
Updates YAML parsing/emitting to better handle quoted keys and special characters in scalars. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+439
to
+441
| when "#" | ||
| # A "#" starts a comment only when preceded by whitespace. | ||
| return val[0...i].rstrip if i.zero? || val[i - 1] == " " || val[i - 1] == "\t" |
quote_string only escaped backslash, double quote and a few whitespace characters, so other C0 control characters were emitted as raw bytes, which is invalid YAML inside quoted scalars. Quote strings containing control characters and escape them with the YAML escapes Psych uses, unescaping them symmetrically on load. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
strip_comment returned the value unchanged when it consisted entirely of a comment, so "key: # comment" loaded as the literal string "# comment" instead of nil as Psych does. Return an empty value so the comment is dropped, and remove the now unreachable i.zero? condition. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was the end-user or developer problem that led to this PR?
Gem::YAMLSerializercould not roundtrip gemspec metadata containing quotes or other special characters because the emitter wrote them as plain scalars and the parser did not understand quoted mapping keys.Fix #9560
What is your fix for the problem, implemented in this PR?
This change quotes emitted strings that would be misread back, parses quoted mapping keys, and treats "#" as a comment only when preceded by whitespace, so the output now roundtrips and matches Psych in both directions.
Make sure the following tasks are checked