develooper Front page | perl.perl5.porters | Postings from October 2011

[perl #96116] File::Glob ':glob' causes infinite loop

Thread Previous
From:
Father Chrysostomos via RT
Date:
October 25, 2011 22:50
Subject:
[perl #96116] File::Glob ':glob' causes infinite loop
Message ID:
rt-3.6.HEAD-31297-1319608220-1896.96116-15-0@perl.org
On Thu Aug 04 03:16:05 2011, jpl@research.att.com wrote:
> Ed Avis <eda@waniasset.com> noted:
> 
> >     Unfortunately, that's a "feature", not a "bug".  Spaces delimit
> separate
> >     >patterns, and there must be a ton of scripts that rely on that
> behavior
> >     >("*.c *.h")
>     There must be lots of programs that rely on that.  But are they
> not outnumbered
>     by the programs which rely on glob working for general filenames,
> e.g.
> 
>          $wildcard = shift @ARGV;
>          @files = glob($wildcard);
> 
>     OK, so that code is broken and has always been broken.  But it's
> not uncommon,
>     as a quick search turns up:
> 
>       
<http://www.google.com/codesearch#search/&q=glob\%28\$%20lang:^perl$&type=cs>
> 
>     It's all rather unfortunate, since the '*.c *.h' behaviour can
> easily be had by
>     doing (glob('*.c'), glob('*.h')) instead, and was always more of
> an accidental
>     side-effect of calling out to tcsh for the globbing.
> 
> 
> One reason this bug has gone (relatively) unnoticed for so long is
> that
> it doesn't happen in list context.  So your example and many of the
> examples you cite will work just fine.  It's scalar context that
> triggers the problem.  There's some magic that I don't yet fully
> understand (and won't until I get  back from vacation) that hands glob
> a
> second argument that can be used to identify which invocation is in
> play, so state can be maintained.  It's there (using -MO=Deparse) when
> ':glob' is used
> 
>     use File::Glob (':glob');
>     while (defined($_ = glob("$dir/*", 0))) {
>          last if ++$entries > $max;
>     }
>     while (defined($_ = glob("$dir/*", 1))) {
>          last if ++$entries > $max;
>     }
> 
> but not when it is missing
> 
>     use File::Glob (':globally');
>     while (defined($_ = glob("$dir/*"))) {
>          last if ++$entries > $max;
>     }
>     while (defined($_ = glob("$dir/*"))) {
>          last if ++$entries > $max;
>     }
> 
> That seems totally backwards; it seems like the extra argument is
> essential for maintaining state to make scalar context act like an
> iterator, but it's ':glob' that is broken and everything else works.

File::Glob::glob explicitly ignores its second argument:

sub glob {
    splice @_, 1; # don't pass PL_glob_index as flags!
    goto &bsd_glob;
}

What you are seeing above is a B::Deparse bug, fixed in 5.14.0.

> My
> diffs point how to make things work with embedded space, but I'm not
> satisfied, because I don't really understand what's happening.  Anyone
> should feel free to fix things while I'm vacationing:-) .  -- jpl




Thread Previous


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