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

File::Spec - catfile wrongly makes relative path absolute #8760

Closed
p5pRT opened this issue Feb 1, 2007 · 6 comments
Closed

File::Spec - catfile wrongly makes relative path absolute #8760

p5pRT opened this issue Feb 1, 2007 · 6 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 1, 2007

Migrated from rt.perl.org#41422 (status was 'rejected')

Searchable as RT41422$

@p5pRT
Copy link
Author

p5pRT commented Feb 1, 2007

From [email protected]

Created by [email protected]

Consider​:
perl -MFile​::Spec -le 'print File​::Spec->catfile("","./blib")'
/blib
perl -MFile​::Spec -le 'print File​::Spec->catfile(undef,"blib")'
/blib

If the first element in the list passed to File​::Spec->catfile
is an empty string or undef, a following relative path is made
absolute.

The behaviour is similar on other architectures as well, in that
it is also broken.

On Windows, "\blib" is returned. Solaris returns "/ blib" (with
that blank).

IMHO, leading and trailing empty (or undef) elements should be
stripped, or the function should die with an appropriate error.

File​::Spec->catdir has the same bug.

Solution (e.g. for File​::Spec​::Unix.pm)​:

---snip---

Inline Patch
--- Unix.pm     2006-10-11 19:11:03.000000000 +0200
+++ Unix.pm.new 2007-02-01 21:51:22.000000000 +0100
@@ -78,6 +78,7 @@
 
 sub catdir {
     my $self = shift;
+    shift @_ while @_ && $_[0] =~ /^$/;
 
     $self->canonpath(join('/', @_, '')); # '' because need a trailing '/'
 }
@@ -91,6 +92,7 @@
 
 sub catfile {
     my $self = shift;
+    shift @_ while @_ && $_[0] =~ /^$/;
     my $file = $self->canonpath(pop @_);
     return $file unless @_;
     my $dir = $self->catdir(@_);
---snip---

--shmem
Perl Info

Flags:
    category=utilities
    severity=medium

This perlbug was built using Perl v5.8.8 - Sun Mar 26 12:41:48 UTC 2006
It is being executed now by  Perl v5.8.8 - Sun Mar 26 12:36:18 UTC 2006.

Site configuration information for perl v5.8.8:

Configured by abuild at Sun Mar 26 12:36:18 UTC 2006.

Summary of my perl5 (revision 5 version 8 subversion 8) configuration:
  Platform:
    osname=linux, osvers=2.6.16, archname=i586-linux-thread-multi
    uname='linux lutoslawski 2.6.16 #1 smp thu mar 23 15:20:09 utc 2006 i686 athlon i386 gnulinux '
    config_args='-ds -e -Dprefix=/usr -Dvendorprefix=/usr -Dinstallusrbinperl -Dusethreads -Di_db -Di_dbm -Di_ndbm -Di_gdbm -Duseshrplib=true -Doptimize=-O2 -march=i586 -mtune=i686 -fmessage-length=0 -Wall -D_FORTIFY_SOURCE=2 -g -Wall -pipe'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -march=i586 -mtune=i686 -fmessage-length=0 -Wall -D_FORTIFY_SOURCE=2 -g -Wall -pipe',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement'
    ccversion='', gccversion='4.1.0 (SUSE Linux)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =''
    libpth=/lib /usr/lib /usr/local/lib
    libs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.4.so, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.4'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.8/i586-linux-thread-multi/CORE'
    cccdlflags='-fPIC', lddlflags='-shared'

Locally applied patches:
    


@INC for perl v5.8.8:
    /home/shmem/comp/perl/lib
    /usr/lib/perl5/5.8.8/i586-linux-thread-multi
    /usr/lib/perl5/5.8.8
    /usr/lib/perl5/site_perl/5.8.8/i586-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.8
    /usr/lib/perl5/site_perl
    /usr/lib/perl5/vendor_perl/5.8.8/i586-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.8
    /usr/lib/perl5/vendor_perl
    .


Environment for perl v5.8.8:
    HOME=/home/shmem
    LANG=de_DE
    LANGUAGE (unset)
    LC_MESSAGES=C
    LD_LIBRARY_PATH=/usr/lib/fglrx/lib
    LOGDIR (unset)
    PATH=/sbin:/usr/sbin:/home/shmem/bin:/home/shmem/bin:/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/games:/opt/gnome/bin:/opt/kde3/bin:/usr/openwin/bin:/usr/lib/jvm/jre/bin:/usr/lib/mit/bin:/usr/lib/mit/sbin:/usr/NX/bin:/usr/openwin/bin:/usr/lib/ICAClient
    PERL5LIB=/home/shmem/comp/perl/lib
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Feb 2, 2007

From @schwern

Georg Moritz (via RT) wrote​:

Consider​:
perl -MFile​::Spec -le 'print File​::Spec->catfile("","./blib")'
/blib
perl -MFile​::Spec -le 'print File​::Spec->catfile(undef,"blib")'
/blib

If the first element in the list passed to File​::Spec->catfile
is an empty string or undef, a following relative path is made
absolute.

I do not believe this is a bug but an underdocumented feature of cat*. The intention is to mirror the behavior of splitdir() which uses an empty string to indicate the root directory. This allows splitdir and catdir/file to round trip. Additionally, "" really is the true name of the root directory.

Consider it this way and it will make more sense. catdir() takes a list of directory names. "/" is a path separator and not part of the directory name. With that in mind, how do you represent the root directory? What is its name? We call it / but really its name is the empty string. The directory-which-shall-not-be-named. The directory formerly known as "/". This is not just a File​::Spec thing but an accurate way of looking at the structure of the Unix filesystem.

Consider it another way. Given that the point of File​::Spec is to be filesystem agnostic, how would you put together an absolute path? You can't refer to it as "/", that's Unix specific.

That it accepts undef this is simply because undef becomes an empty string when used as a string. Turn on warnings.

@p5pRT
Copy link
Author

p5pRT commented Feb 2, 2007

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Feb 5, 2007

From [email protected]

Created by [email protected]

Consider​:
perl -MFile​::Spec -le 'print File​::Spec->catfile("","./blib")'
/blib
perl -MFile​::Spec -le 'print File​::Spec->catfile(undef,"blib")'
/blib

If the first element in the list passed to File​::Spec->catfile
is an empty string or undef, a following relative path is made
absolute.

The behaviour is similar on other architectures as well, in that
it is also broken.

On Windows, "\blib" is returned. Solaris returns "/ blib" (with
that blank).

IMHO, leading and trailing empty (or undef) elements should be
stripped, or the function should die with an appropriate error.

File​::Spec->catdir has the same bug.

Solution (e.g. for File​::Spec​::Unix.pm)​:

---snip---

Inline Patch
--- Unix.pm     2006-10-11 19:11:03.000000000 +0200
+++ Unix.pm.new 2007-02-01 21:51:22.000000000 +0100
@@ -78,6 +78,7 @@
 
 sub catdir {
     my $self = shift;
+    shift @_ while @_ && $_[0] =~ /^$/;
 
     $self->canonpath(join('/', @_, '')); # '' because need a trailing '/'
 }
@@ -91,6 +92,7 @@
 
 sub catfile {
     my $self = shift;
+    shift @_ while @_ && $_[0] =~ /^$/;
     my $file = $self->canonpath(pop @_);
     return $file unless @_;
     my $dir = $self->catdir(@_);
---snip---

--shmem
Perl Info

Flags:
    category=utilities
    severity=medium

This perlbug was built using Perl v5.8.8 - Sun Mar 26 12:41:48 UTC 2006
It is being executed now by  Perl v5.8.8 - Sun Mar 26 12:36:18 UTC 2006.

Site configuration information for perl v5.8.8:

Configured by abuild at Sun Mar 26 12:36:18 UTC 2006.

Summary of my perl5 (revision 5 version 8 subversion 8) configuration:
  Platform:
    osname=linux, osvers=2.6.16, archname=i586-linux-thread-multi
    uname='linux lutoslawski 2.6.16 #1 smp thu mar 23 15:20:09 utc 2006 i686 athlon i386 gnulinux '
    config_args='-ds -e -Dprefix=/usr -Dvendorprefix=/usr -Dinstallusrbinperl -Dusethreads -Di_db -Di_dbm -Di_ndbm -Di_gdbm -Duseshrplib=true -Doptimize=-O2 -march=i586 -mtune=i686 -fmessage-length=0 -Wall -D_FORTIFY_SOURCE=2 -g -Wall -pipe'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2 -march=i586 -mtune=i686 -fmessage-length=0 -Wall -D_FORTIFY_SOURCE=2 -g -Wall -pipe',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement'
    ccversion='', gccversion='4.1.0 (SUSE Linux)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =''
    libpth=/lib /usr/lib /usr/local/lib
    libs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.4.so, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.4'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.8/i586-linux-thread-multi/CORE'
    cccdlflags='-fPIC', lddlflags='-shared'

Locally applied patches:
    


@INC for perl v5.8.8:
    /home/shmem/comp/perl/lib
    /usr/lib/perl5/5.8.8/i586-linux-thread-multi
    /usr/lib/perl5/5.8.8
    /usr/lib/perl5/site_perl/5.8.8/i586-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.8
    /usr/lib/perl5/site_perl
    /usr/lib/perl5/vendor_perl/5.8.8/i586-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.8
    /usr/lib/perl5/vendor_perl
    .


Environment for perl v5.8.8:
    HOME=/home/shmem
    LANG=de_DE
    LANGUAGE (unset)
    LC_MESSAGES=C
    LD_LIBRARY_PATH=/usr/lib/fglrx/lib
    LOGDIR (unset)
    PATH=/sbin:/usr/sbin:/home/shmem/bin:/home/shmem/bin:/usr/local/bin:/usr/bin:/usr/X11R6/bin:/bin:/usr/games:/opt/gnome/bin:/opt/kde3/bin:/usr/openwin/bin:/usr/lib/jvm/jre/bin:/usr/lib/mit/bin:/usr/lib/mit/sbin:/usr/NX/bin:/usr/openwin/bin:/usr/lib/ICAClient
    PERL5LIB=/home/shmem/comp/perl/lib
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Feb 6, 2007

@rgs - Status changed from 'open' to 'rejected'

@p5pRT p5pRT closed this as completed Feb 6, 2007
@p5pRT
Copy link
Author

p5pRT commented Feb 7, 2007

From @adamkennedy

Can I strongly recommend that before you make any changes here you add
some round-trip testing for absolute path names?

Because as I understand it, "" intentionally represents the root path.

  DB<4> x File​::Spec->splitdir('/foo/bar')
0 ''
1 'foo'
2 'bar'

  DB<5> x File​::Spec->catdir(File​::Spec->splitdir('/foo/bar'))
0 '/foo/bar'

I seem to recall I rely on this "null string is root" in a number of
modules.

As for the undef case, I'm ambivalent, but I'd rather see an error than
have it silently relativise my paths.

Adam K

Georg Moritz wrote​:

# New Ticket Created by Georg Moritz
# Please include the string​: [perl #41439]
# in the subject line of all future correspondence about this issue.
# <URL​: http​://rt.perl.org/rt3/Ticket/Display.html?id=41439 >

This is a bug report for perl from gm@​cruft.de,
generated with the help of perlbug 1.35 running under perl v5.8.8.

-----------------------------------------------------------------
[Please enter your report here]

Consider​:
perl -MFile​::Spec -le 'print File​::Spec->catfile("","./blib")'
/blib
perl -MFile​::Spec -le 'print File​::Spec->catfile(undef,"blib")'
/blib

If the first element in the list passed to File​::Spec->catfile
is an empty string or undef, a following relative path is made
absolute.

The behaviour is similar on other architectures as well, in that
it is also broken.

On Windows, "\blib" is returned. Solaris returns "/ blib" (with
that blank).

IMHO, leading and trailing empty (or undef) elements should be
stripped, or the function should die with an appropriate error.

File​::Spec->catdir has the same bug.

Solution (e.g. for File​::Spec​::Unix.pm)​:

---snip---
--- Unix.pm 2006-10-11 19​:11​:03.000000000 +0200
+++ Unix.pm.new 2007-02-01 21​:51​:22.000000000 +0100
@​@​ -78,6 +78,7 @​@​

sub catdir {
my $self = shift;
+ shift @​_ while @​_ && $_[0] =~ /^$/;

 $self\->canonpath\(join\('/'\, @&#8203;\_\, ''\)\); \# '' because need a trailing '/'

}
@​@​ -91,6 +92,7 @​@​

sub catfile {
my $self = shift;
+ shift @​_ while @​_ && $_[0] =~ /^$/;
my $file = $self->canonpath(pop @​_);
return $file unless @​_;
my $dir = $self->catdir(@​_);
---snip---

--shmem

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags​:
category=utilities
severity=medium
---
This perlbug was built using Perl v5.8.8 - Sun Mar 26 12​:41​:48 UTC 2006
It is being executed now by Perl v5.8.8 - Sun Mar 26 12​:36​:18 UTC 2006.

Site configuration information for perl v5.8.8​:

Configured by abuild at Sun Mar 26 12​:36​:18 UTC 2006.

Summary of my perl5 (revision 5 version 8 subversion 8) configuration​:
Platform​:
osname=linux, osvers=2.6.16, archname=i586-linux-thread-multi
uname='linux lutoslawski 2.6.16 #1 smp thu mar 23 15​:20​:09 utc 2006 i686 athlon i386 gnulinux '
config_args='-ds -e -Dprefix=/usr -Dvendorprefix=/usr -Dinstallusrbinperl -Dusethreads -Di_db -Di_dbm -Di_ndbm -Di_gdbm -Duseshrplib=true -Doptimize=-O2 -march=i586 -mtune=i686 -fmessage-length=0 -Wall -D_FORTIFY_SOURCE=2 -g -Wall -pipe'
hint=recommended, useposix=true, d_sigaction=define
usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler​:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O2 -march=i586 -mtune=i686 -fmessage-length=0 -Wall -D_FORTIFY_SOURCE=2 -g -Wall -pipe',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -pipe -Wdeclaration-after-statement'
ccversion='', gccversion='4.1.0 (SUSE Linux)', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries​:
ld='cc', ldflags =''
libpth=/lib /usr/lib /usr/local/lib
libs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
libc=/lib/libc-2.4.so, so=so, useshrplib=true, libperl=libperl.so
gnulibc_version='2.4'
Dynamic Linking​:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.8/i586-linux-thread-multi/CORE'
cccdlflags='-fPIC', lddlflags='-shared'

Locally applied patches​:

---
@​INC for perl v5.8.8​:
/home/shmem/comp/perl/lib
/usr/lib/perl5/5.8.8/i586-linux-thread-multi
/usr/lib/perl5/5.8.8
/usr/lib/perl5/site_perl/5.8.8/i586-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.8
/usr/lib/perl5/site_perl
/usr/lib/perl5/vendor_perl/5.8.8/i586-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.8
/usr/lib/perl5/vendor_perl
.

---
Environment for perl v5.8.8​:
HOME=/home/shmem
LANG=de_DE
LANGUAGE (unset)
LC_MESSAGES=C
LD_LIBRARY_PATH=/usr/lib/fglrx/lib
LOGDIR (unset)
PATH=/sbin​:/usr/sbin​:/home/shmem/bin​:/home/shmem/bin​:/usr/local/bin​:/usr/bin​:/usr/X11R6/bin​:/bin​:/usr/games​:/opt/gnome/bin​:/opt/kde3/bin​:/usr/openwin/bin​:/usr/lib/jvm/jre/bin​:/usr/lib/mit/bin​:/usr/lib/mit/sbin​:/usr/NX/bin​:/usr/openwin/bin​:/usr/lib/ICAClient
PERL5LIB=/home/shmem/comp/perl/lib
PERL_BADLANG (unset)
SHELL=/bin/bash

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant