From 2ad66a1cb4877e9b94f651b9f4fdf8b341470503 Mon Sep 17 00:00:00 2001 From: Michal Fox Date: Fri, 2 Oct 2026 16:05:27 +0200 Subject: [PATCH] fix #6305: cli formatter: avoid encoding YAML output twice YAML::XS::Dump already returns UTF-8 encoded octets, but its output still got encoded once more. This is a leftover from when the YAML output was generated by CPAN::Meta::YAML, which returns a character string. As a result, all non-ASCII characters got mangled with the 'yaml' output format, for example a cluster description with a German umlaut when running: pvesh get /cluster/options --output-format yaml Print the output of YAML::XS::Dump as is, like it is already done for the 'json' output format, and add a test for the encoding of both. Fixes: 99d0252 ("properly encode YAML via YAML::XS") Signed-off-by: Michal Fox --- src/PVE/CLIFormatter.pm | 3 ++- test/format_test.pl | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/PVE/CLIFormatter.pm b/src/PVE/CLIFormatter.pm index ca4ee08..d93bed6 100644 --- a/src/PVE/CLIFormatter.pm +++ b/src/PVE/CLIFormatter.pm @@ -380,7 +380,8 @@ sub print_api_result { } if ($format eq 'yaml') { - print encode('UTF-8', YAML::XS::Dump($data)); + # Note: YAML::XS already returns UTF-8 encoded output + print YAML::XS::Dump($data); } elsif ($format eq 'json') { # Note: we always use utf8 encoding for json format print to_json($data, { utf8 => 1, allow_nonref => 1, canonical => 1 }) . "\n"; diff --git a/test/format_test.pl b/test/format_test.pl index 7b461ef..8ccfd5a 100644 --- a/test/format_test.pl +++ b/test/format_test.pl @@ -7,6 +7,7 @@ use lib '../src'; use PVE::JSONSchema; use PVE::CLIFormatter; +use Encode qw(decode); use Test::More; use Test::MockModule; @@ -53,4 +54,18 @@ foreach my $data (@$render_data) { is($actual, $expected, "string format '$renderer_name'"); } +# test that non-ASCII characters survive the structured output formats +my $unicode_data = { description => "Erkl\x{e4}rung" }; +for my $format (qw(json yaml)) { + open(my $fh, '>', \my $output) or die "failed to open in-memory file - $!\n"; + my $stdout = select($fh); + PVE::CLIFormatter::print_api_result( + $unicode_data, undef, undef, { 'output-format' => $format }, {}, + ); + select($stdout); + close($fh); + + like(decode('UTF-8', $output), qr/Erkl\x{e4}rung/, "output format '$format' is UTF-8 encoded"); +} + done_testing();