Ian Jackson <ijack...@chiark.greenend.org.uk> writes: > Apparently this has been klnown about for EIGHTEEN YEARS > https://rt.perl.org/Public/Bug/Display.html?id=2783 > and no-one has fixed it or even documented it.
It's been documented for pretty close to eighteen years too. See perlop(1): The null filehandle "<>" is special: it can be used to emulate the behavior of sed and awk, and any other Unix filter program that takes a list of filenames, doing the same to each line of input from all of them. Input from "<>" comes either from standard input, or from each file listed on the command line. Here's how it works: the first time "<>" is evaluated, the @ARGV array is checked, and if it is empty, $ARGV[0] is set to "-", which when opened gives you standard input. The @ARGV array is then processed as a list of filenames. The loop while (<>) { ... # code for each line } is equivalent to the following Perl-like pseudo code: unshift(@ARGV, '-') unless @ARGV; while ($ARGV = shift) { open(ARGV, $ARGV); while (<ARGV>) { ... # code for each line } } except that it isn't so cumbersome to say, and will actually work. It really does shift the @ARGV array and put the current filename into the $ARGV variable. It also uses filehandle ARGV internally. "<>" is just a synonym for "<ARGV>", which is magical. (The pseudo code above doesn't work because it treats "<ARGV>" as non-magical.) Since the null filehandle uses the two argument form of "open" in perlfunc it interprets special characters, so if you have a script like this: while (<>) { print; } and call it with "perl dangerous.pl 'rm -rfv *|'", it actually opens a pipe, executes the "rm" command and reads "rm"'s output from that pipe. If you want all items in @ARGV to be interpreted as file names, you can use the module "ARGV::readonly" from CPAN, or use the double bracket: while (<<>>) { print; } > I think this is a serious bug in Perl which should be fixed in a > security update. There is absolutely no way. So much stuff in Perl depends on this. You will break all kinds of scripts. It's been a feature of the language for basically forever. There have been extensive discussions of this on perl5-porters, and there's some general consensus that it was a bad idea originally, but changing this destroys backwards compatibility. You just can't; it's like removing strcpy from libc. The best you could do would be to add a pragmata to turn it off, and *maybe*, *someday*, enable that pragmata by default with a sufficiently new version in "use". -- Russ Allbery (r...@debian.org) <http://www.eyrie.org/~eagle/>