diff --git a/lib/puppet/util/windows/string.rb b/lib/puppet/util/windows/string.rb index 04535d29e..13d9839d1 100644 --- a/lib/puppet/util/windows/string.rb +++ b/lib/puppet/util/windows/string.rb @@ -1,11 +1,14 @@ require 'puppet/util/windows' module Puppet::Util::Windows::String def wide_string(str) - # bug in win32-api, see https://tickets.puppetlabs.com/browse/PUP-1389 - wstr = str.encode('UTF-16LE') - wstr << 0 - wstr.strip + # ruby (< 2.1) does not respect multibyte terminators, so it is possible + # for a string to contain a single trailing null byte, followed by garbage + # causing buffer overruns. + # + # See http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?revision=41920&view=revision + newstr = str + "\0".encode(str.encoding) + newstr.encode!('UTF-16LE') end module_function :wide_string end diff --git a/spec/unit/util/windows/string_spec.rb b/spec/unit/util/windows/string_spec.rb index adb53d2be..60f7e6449 100644 --- a/spec/unit/util/windows/string_spec.rb +++ b/spec/unit/util/windows/string_spec.rb @@ -1,70 +1,54 @@ # encoding: UTF-8 #!/usr/bin/env ruby require 'spec_helper' require 'puppet/util/windows' describe "Puppet::Util::Windows::String", :if => Puppet.features.microsoft_windows? do + UTF16_NULL = [0, 0] def wide_string(str) Puppet::Util::Windows::String.wide_string(str) end + def converts_to_wide_string(string_value) + expected = string_value.encode(Encoding::UTF_16LE) + expected_bytes = expected.bytes.to_a + UTF16_NULL + + wide_string(string_value).bytes.to_a.should == expected_bytes + end + context "wide_string" do it "should return encoding of UTF-16LE" do wide_string("bob").encoding.should == Encoding::UTF_16LE end it "should return valid encoding" do wide_string("bob").valid_encoding?.should be_true end it "should convert an ASCII string" do - string_value = "bob".encode(Encoding::US_ASCII) - result = wide_string(string_value) - expected = string_value.encode(Encoding::UTF_16LE) - - result.bytes.to_a.should == expected.bytes.to_a + converts_to_wide_string("bob".encode(Encoding::US_ASCII)) end it "should convert a UTF-8 string" do - string_value = "bob".encode(Encoding::UTF_8) - result = wide_string(string_value) - expected = string_value.encode(Encoding::UTF_16LE) - - result.bytes.to_a.should == expected.bytes.to_a + converts_to_wide_string("bob".encode(Encoding::UTF_8)) end it "should convert a UTF-16LE string" do - string_value = "bob\u00E8".encode(Encoding::UTF_16LE) - result = wide_string(string_value) - expected = string_value.encode(Encoding::UTF_16LE) - - result.bytes.to_a.should == expected.bytes.to_a + converts_to_wide_string("bob\u00E8".encode(Encoding::UTF_16LE)) end it "should convert a UTF-16BE string" do - string_value = "bob\u00E8".encode(Encoding::UTF_16BE) - result = wide_string(string_value) - expected = string_value.encode(Encoding::UTF_16LE) - - result.bytes.to_a.should == expected.bytes.to_a + converts_to_wide_string("bob\u00E8".encode(Encoding::UTF_16BE)) end it "should convert an UTF-32LE string" do - string_value = "bob\u00E8".encode(Encoding::UTF_32LE) - result = wide_string(string_value) - expected = string_value.encode(Encoding::UTF_16LE) - - result.bytes.to_a.should == expected.bytes.to_a + converts_to_wide_string("bob\u00E8".encode(Encoding::UTF_32LE)) end it "should convert an UTF-32BE string" do - string_value = "bob\u00E8".encode(Encoding::UTF_32BE) - result = wide_string(string_value) - expected = string_value.encode(Encoding::UTF_16LE) - - result.bytes.to_a.should == expected.bytes.to_a + converts_to_wide_string("bob\u00E8".encode(Encoding::UTF_32BE)) end end end