Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix "Error: invalid byte sequence in UTF-8" error when retrieving catalogues with invalid encoding from PuppetDB on Puppet 3 server #38

Merged
merged 12 commits into from
Oct 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/puppet/catalog-diff/comparer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ def do_str_diff(str1, str2)
diff
end

def validate_encoding(str)
unless str.valid_encoding?
Puppet::debug("Detected that string used in diff had invalid #{str.encoding} encoding. Replacing invalid characters in diff output.")
str.encode!('UTF-8', 'UTF-8', :invalid => :replace)
end
str
end

def str_diff(cont1, cont2)
return nil unless cont1 && cont2

Expand All @@ -138,6 +146,9 @@ def str_diff(cont1, cont2)
sum2 = Digest::MD5.hexdigest(str2)
end

str1 = validate_encoding(str1)
str2 = validate_encoding(str2)

return nil unless str1 && str2
return nil if sum1 == sum2

Expand Down
16 changes: 16 additions & 0 deletions spec/unit/puppet/catalog_diff/comparer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,22 @@
diffs = compare_resources(res1, res2, show_resource_diff: true)
expect(diffs[:string_diffs]['file.foo'][3]).to eq("-\t content => \"foo content\"")
end

it 'returns string_diffs with show_resource_diff with content encoded in ISO8859-1 (latin1)' do
# Without this the unit test fails when running on LC_ALL=C but works with LC_ALL=en_US.UTF-8
# With this it works on both.
Encoding.default_internal = 'UTF-8'
Encoding.default_external = 'UTF-8' # Needed because diff uses tempfile.

latin1_string = [246].pack('C*').force_encoding('UTF-8')
res1[0][:parameters][:content] = latin1_string
expect{compare_resources(res1, res2, show_resource_diff: true)}.not_to raise_error
diffs = compare_resources(res1, res2, show_resource_diff: true)

ruby_default_replacement_string_for_invalid_characters = '�'
expect(diffs[:string_diffs]['file.foo'][3]).to \
eq("-\t content => \"" + ruby_default_replacement_string_for_invalid_characters + "\"")
end

it 'returns a diff without path parameter' do
diffs = compare_resources(res1, res2, ignore_parameters: 'path')
Expand Down