Skip Menu |

This queue is for tickets about the YAML-Tiny CPAN distribution.

Report information
The Basics
Id: 54790
Status: resolved
Priority: 0/
Queue: YAML-Tiny

People
Owner: Nobody in particular
Requestors: ANDK [...] cpan.org
Cc: smueller [...] cpan.org
AdminCc:

Bug Information
Severity: Important
Broken in: 1.41
Fixed in: 1.57



CC: SMUELLER [...] cpan.org
Subject: Trips over quoted hash key
% echo "--- configure_requires: 'Foo::Bar': 3.14 " > ttt.yml % perl -e ' use strict; for my $m ("YAML", "YAML::Syck", "YAML::XS", "YAML::Tiny", "Parse::CPAN::Meta"){ my $y = eval "use $m; $m\::LoadFile q{ttt.yml} or die"; print $@ if $@; printf "%18s (%s): %s\n", $m, $m->VERSION, join(",",keys %{$y->{configure_requires}}); } ' YAML (0.71): Foo::Bar YAML::Syck (1.07): Foo::Bar YAML::XS (0.32): Foo::Bar YAML::Tiny does not support a feature in line ' 'Foo::Bar': 3.14' at (eval 32) line 1 YAML::Tiny (1.41): Parse::CPAN::Meta does not support a feature in line ' 'Foo::Bar': 3.14' at (eval 36) line 1 Parse::CPAN::Meta (1.40): This can be extended to failing roundtrip on a string containing quotes: % perl -e ' use Data::Dumper; use YAML::Tiny; use strict; my $y = YAML::Tiny::Dump +{ qq[\x{27}a quoty \x{22} key] => 1 }; print $y; my $rt = YAML::Tiny::Load $y; print Data::Dumper::Dumper($rt); ' --- 'a quoty " key: 1 YAML::Tiny does not support a feature in line ''a quoty " key: 1' at -e line 5 Grading important because bug was discovered while parsing a META.yml. Greets,
RT-Send-CC: SMUELLER [...] cpan.org
I took a stab at fixing this for my own needs. I added a few basic tests. More are probably in order... http://github.com/toddr/YAML- Tiny/commit/67f819d3617a15a2fdf98b1666e3ab0e89c06fd4.diff Also attached.
Subject: quote_key.txt
--- a/lib/YAML/Tiny.pm +++ b/lib/YAML/Tiny.pm @@ -326,13 +326,20 @@ } # Get the key - unless ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { + my $key; + if($lines->[0] =~ s/^\s*"([^"]*[^\\])":(\s+|$)//) { + $key = $1; # double Quoted <= + $key =~ s/\\n/\n/msg; + } elsif($lines->[0] =~ s/^\s*\'([^']*[^\\])\':(\s+|$)//) { + $key = $1; # single Quoted <= + } elsif ( $lines->[0] =~ s/^\s*([^\'\" ][^\n]*?)\s*:(\s+|$)// ) { + $key = $1; # Regular support + } else { # Unsupported. if ( $lines->[0] =~ /^\s*[?\'\"]/ ) { croak("YAML::Tiny does not support a feature in line '$lines->[0]'"); } croak("YAML::Tiny failed to classify line '$lines->[0]'"); } - my $key = $1; # Do we have a value? if ( length $lines->[0] ) { @@ -486,6 +493,12 @@ my @lines = (); foreach my $name ( sort keys %$hash ) { my $el = $hash->{$name}; + if(defined $name && !is_valid_plain($name)) { + Test::More::diag("special: $name"); + $name =~ s/"/\\"/msg; + $name =~ s/\n/\\n/msg; + $name = "\"$name\""; + } my $line = (' ' x $indent) . "$name:"; my $type = ref $el; if ( ! $type ) { @@ -516,6 +529,19 @@ } @lines; +} + +# Check whether or not a scalar should be emitted as an plain scalar. +sub is_valid_plain { + return 0 unless length $_[0]; + # refer to YAML::Loader::parse_inline_simple() + return 0 if $_[0] =~ /^[\s\{\[\~\`\'\"\!\@\#\>\|\%\&\?\*\^]/; + return 0 if $_[0] =~ /[\{\[\]\},]/; + return 0 if $_[0] =~ /[:\-\?]\s/; + return 0 if $_[0] =~ /\s#/; + return 0 if $_[0] =~ /\:(\s|$)/; + return 0 if $_[0] =~ /[\s\|\>]$/; + return 1; } # Set error --- a/t/03_regression.t +++ b/t/03_regression.t @@ -10,7 +10,7 @@ use File::Spec::Functions ':ALL'; use t::lib::Test; -use Test::More tests(37, 0, 11); +use Test::More tests(39, 0, 11); # yaml_oks, load_oks, singles use YAML::Tiny qw{ Load Dump LoadFile DumpFile @@ -53,7 +53,24 @@ 'hash_indented', ); +##################################################################### +# Support for quoted hash keys +# Hash indented +yaml_ok( + "---\n" + . " \">=\": foo\n", + [ { '>=' => "foo" } ], + 'hash_double_quote', +); + +# Hash key new line +yaml_ok( + "---\n" + . qq{ "foo\\n": bar\n}, + [ { "foo\n" => "bar" } ], + 'hash_newline_double_quote', +);
This fix breaks tests if YAML::Perl is installed. RT # 55385 suggests changing testing via YAML::Perl to YAML
This has been fixed (differently) in the repository and will be tested further before release. The fix also generates quoted keys when necessary. Marking this as patched until there is more testing and it ships.
fixed in 1.57 releas