Bug 1367928

Summary: Open() fails if filename ends in a space
Product: [Fedora] Fedora Reporter: GeoffLeach <geoffleach.gl>
Component: perlAssignee: Jitka Plesnikova <jplesnik>
Status: CLOSED NOTABUG QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: low Docs Contact:
Priority: unspecified    
Version: 23CC: cweyl, iarnell, jplesnik, kasal, perl-devel, ppisar, psabata, rc040203, tcallawa
Target Milestone: ---   
Target Release: ---   
Hardware: i686   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2016-08-30 15:00:10 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:

Description GeoffLeach 2016-08-17 20:41:56 UTC
Description of problem: 
Open() fails if file name ends in a space


Version-Release number of selected component (if applicable): 
5.22.2


How reproducible:
100%

Steps to Reproduce:
1.$file = 't ';

2.$o = open($fh, $file)|| die 'whoops';

3.

Actual results:
"whoops"

Expected results:
no "whoops"

Additional info:

Comment 1 Petr Pisar 2016-08-30 15:00:10 UTC
Checking what the code does on operating level shows:

$ strace -e open ./test 
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libperl.so.5.22", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libnsl.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libm.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libcrypt.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libutil.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libfreebl3.so", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/dev/urandom", O_RDONLY)          = 3
open("./test", O_RDONLY)                = 3
open("/usr/share/perl5/strict.pm", O_RDONLY) = 4
open("/usr/share/perl5/warnings.pm", O_RDONLY) = 4
open("t", O_RDONLY)                     = -1 ENOENT (No such file or directory)
whoops: No such file or directory at ./test line 5.
+++ exited with 2 +++

So the problem is that the trailing white space is removed.

Reading open() documentation in perlfunc POD revelads this is a feature:

            The filename passed to the one- and two-argument forms of open()
            will have leading and trailing whitespace deleted and normal
            redirection characters honored. This property, known as "magic
            open", can often be used to good effect. A user could specify a
            filename of "rsh cat file |", or you could change certain
            filenames as needed:

                $filename =~ s/(.*\.gz)\s*$/gzip -dc < $1|/;
                open(FH, $filename) or die "Can't open $filename: $!";

            Use the three-argument form to open a file with arbitrary weird
            characters in it,

                open(FOO, "<", $file)
                    || die "can't open < $file: $!";

            otherwise it's necessary to protect any leading and trailing
            whitespace:

                $file =~ s#^(\s)#./$1#;
                open(FOO, "< $file\0")
                    || die "open failed: $!";


Therefore I recommend you to use 3-argument form with explicit open mode like this:

$o = open($fh, '<', $file)|| die 'whoops';