Jira (PUP-9559) Puppet's Uniquefile doesn't open files in binary mode

4 views
Skip to first unread message

Josh Cooper (JIRA)

unread,
Mar 14, 2019, 4:46:02 AM3/14/19
to puppe...@googlegroups.com
Josh Cooper created an issue
 
Puppet / Improvement PUP-9559
Puppet's Uniquefile doesn't open files in binary mode
Issue Type: Improvement Improvement
Assignee: Unassigned
Created: 2019/03/14 1:45 AM
Priority: Normal Normal
Reporter: Josh Cooper

When using Puppet::Util.replace_file, contents are written to the underlying Uniquefile in text mode instead of binary. On POSIX, this is a noop. On Windows, it will cause the sequence "\r\n" to be written as "\n".

replace_file is also used by Puppet::Util::Execution (the child process' stdout is written to a Uniquefile. If the child process emits binary data, then it could be become corrupt if the output happens to contain the \r\n sequence.

The Uniquefile implementation is missing the following:

diff --git a/lib/puppet/file_system/uniquefile.rb b/lib/puppet/file_system/uniquefile.rb
index fdba62e7a4..058f6deea9 100644
--- a/lib/puppet/file_system/uniquefile.rb
+++ b/lib/puppet/file_system/uniquefile.rb
@@ -26,7 +26,7 @@ class Puppet::FileSystem::Uniquefile < DelegateClass(File)
 
   def initialize(basename, *rest)
     create_tmpname(basename, *rest) do |tmpname, n, opts|
-      mode = File::RDWR|File::CREAT|File::EXCL
+      mode = File::RDWR|File::CREAT|File::EXCL|File::BINARY
       perm = 0600
       if opts
         mode |= opts.delete(:mode) || 0

Add Comment Add Comment
 
This message was sent by Atlassian JIRA (v7.7.1#77002-sha1:e75ca93)
Atlassian logo

Josh Cooper (JIRA)

unread,
Mar 14, 2019, 4:51:02 AM3/14/19
to puppe...@googlegroups.com
Josh Cooper updated an issue
Change By: Josh Cooper
When using {{Puppet::Util.replace_file}}, contents are written to the underlying {{Uniquefile}} in {{text}} mode instead of {{binary}}. On POSIX, this is a noop. On Windows, it will cause the sequence "\ r\ n" to be written as "\ r\ n".

{{replace_file}} is also used by {{Puppet::Util::Execution}} (the child process' stdout is written to a {{Uniquefile}}. If the child process emits binary data
, then it could be become corrupt if the output that happens to contain the {{ " \ r\ n }} sequence ", then the output will be corrupted .


The {{Uniquefile}} implementation is missing the following:

{code:diff}

diff --git a/lib/puppet/file_system/uniquefile.rb b/lib/puppet/file_system/uniquefile.rb
index fdba62e7a4..058f6deea9 100644
--- a/lib/puppet/file_system/uniquefile.rb
+++ b/lib/puppet/file_system/uniquefile.rb
@@ -26,7 +26,7 @@ class Puppet::FileSystem::Uniquefile < DelegateClass(File)

   def initialize(basename, *rest)
     create_tmpname(basename, *rest) do |tmpname, n, opts|
-      mode = File::RDWR|File::CREAT|File::EXCL
+      mode = File::RDWR|File::CREAT|File::EXCL|File::BINARY
       perm = 0600
       if opts
         mode |= opts.delete(:mode) || 0
{code}

Josh Cooper (JIRA)

unread,
Mar 14, 2019, 11:40:02 AM3/14/19
to puppe...@googlegroups.com

Jorie Tappa (JIRA)

unread,
Mar 18, 2019, 12:50:05 PM3/18/19
to puppe...@googlegroups.com

Josh Cooper (Jira)

unread,
Jun 11, 2020, 1:00:04 AM6/11/20
to puppe...@googlegroups.com
Josh Cooper commented on Improvement PUP-9559
 
Re: Puppet's Uniquefile doesn't open files in binary mode

Verified this is still an issue, note the double "\r"

irb(main):020:0> file = Puppet::FileSystem::Uniquefile.new("C:\\Users\\Josh\\uniq.txt")
=> #<File:C:/Users/Josh/uniq.txt20200610-2368-kl7007>
irb(main):021:0> file.write("hello\r\nworld")
=> 12
irb(main):022:0> file.flush
=> #<File:C:/Users/Josh/uniq.txt20200610-2368-kl7007>
irb(main):023:0> File.binread(file.path)
=> "hello\r\r\nworld"

This message was sent by Atlassian Jira (v8.5.2#805002-sha1:a66f935)
Atlassian logo

Josh Cooper (Jira)

unread,
Jun 11, 2020, 2:17:03 AM6/11/20
to puppe...@googlegroups.com
Josh Cooper commented on Improvement PUP-9559

File::BINARY is defined to be 0, so adding the constant above does nothing. The real problem is that Uniquefile defaults to mode w+, so calling replace_file containing windows line endings will cause \n to be replaced with \r\n.

Reply all
Reply to author
Forward
0 new messages