develooper Front page | perl.perl5.porters | Postings from August 2009

[perl #68260] File::Find troubles with symlinks that use multiple slashes for a single directory separator

From:
Ed
Date:
August 7, 2009 03:49
Subject:
[perl #68260] File::Find troubles with symlinks that use multiple slashes for a single directory separator
Message ID:
rt-3.6.HEAD-2466-1249594481-937.68260-75-0@perl.org
# New Ticket Created by  Ed 
# Please include the string:  [perl #68260]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=68260 >


File::Find's contract_name produces an incorrect path when a symlink has
multiple slashes to represent a single directory separator alongside a
parent directory reference.  The code that converts '/DIRECTORY/../' to just
'/' is managing a single slash, but that doesn't mean it manages the
directory separator completely, since the separation may be represented by
multiple slashes.

I'm using perl 5.8.5 on linux.  I found this File::Find issue in 1.07, and
did an install of 1.13 to find it there as well.

Test case:

$ mkdir -p A/1 B/2
$ echo hello > B/2/file.txt
$ ln -s ..////../B/2/file.txt A/1/link_a
$ cat A/1/link_a
hello
$ cat try_sym_resolve
#!/usr/local/bin/perl

use strict;
use warnings;

use lib '.';
use File::Find ();

print "File::Find version:  $File::Find::VERSION\n";

File::Find::find(
     {  'wanted' => \&wanted
      , 'follow' => 1
      , 'follow_skip' => 2
      , 'dangling_symlinks' => 1
     }
   , $ARGV[0]
);

exit;

sub wanted {
   my ($dev) = lstat($_);

   print "$File::Find::name\n" if -r _ and -d _;
}
$ ./try_sym_resolve A/1/link_a
File::Find version:  1.13
A/1/link_a is a dangling symbolic link
 at ./try_sym_resolve line 11
$ ./try_sym_resolve B/2/file.txt
File::Find version:  1.13
$


I believe the issue is at File::Find's line 446, in contract_name:

       1 while $abs_name =~ s!/[^/]*/\.\./!/!;

Ignoring the leading path, that means we pass through:

A/1/..////../B/2/file.txt
A////../B/2/file.txt
A///B/2/file.txt

That last path is not where the link points.

In terms of a fix, I would think that multiple slashes could be compressed
to singles prior to line 446, and/or that the existing 446 RE could be
altered to use + (plus) instead of * (asterisk).

Come to think of it, this code also may be exposed to issues with paths that
include current directory representations, such as:

A/./../B

I didn't test that out, but it looks like it would resolve (incorrectly) to:

A/B

Thanks.



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About