$ ln -s /usr/bin/perl bar
$ perl -le' print "bar", -l foo'
1
The -l ate my bar.
It’s this naughty piece of code in doio.c:Perl_my_lstat_flags that is
the culprit:
if (ckWARN(WARN_IO)) {
Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
GvENAME(cGVOP_gv));
return (PL_laststatval = -1);
}
When -l is followed by a bareward, it has no argument on the stack,
but the filetest op itself is a gvop. That snippet is from the bare-
word-handling code.
So, if warnings are off, it falls through to the argument-on-the-stack
code and pops off something does not belong to it (that belong to the
print, in the example above).
if (ckWARN(WARN_IO)) {
Perl_warner(aTHX_ packWARN(WARN_IO), "Use of -l on filehandle %s",
GvENAME(cGVOP_gv));
- return (PL_laststatval = -1);
}
+ return (PL_laststatval = -1);
}
else if (PL_laststype != OP_LSTAT
&& (PL_op->op_private & OPpFT_STACKED) && ckWARN(WARN_IO))
}
use Config;
-plan(tests => 28 + 27*14);
+plan(tests => 29 + 27*14);
ok( -d 'op' );
ok( -f 'TEST' );
is( eval "-r -$op \$ft", "-r", "stacked overloaded -$op" );
is( eval "-$op -r \$ft", "-$op", "overloaded stacked -$op" );
}
+
+# -l stack corruption: this bug occurred from 5.8 to 5.14
+{
+ push my @foo, "bar", -l baz;
+ is $foo[0], "bar", '-l bareword does not corrupt the stack';
+}