This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #126064] Apply scalar context to stat args
authorFather Chrysostomos <sprout@cpan.org>
Sun, 20 Sep 2015 22:06:39 +0000 (15:06 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 20 Sep 2015 22:21:28 +0000 (15:21 -0700)
If we don’t apply scalar context to stat’s argument, then it doesn’t
get its context marked:

$ ./perl -Ilib -MO=Concise -le 'stat stat stat'
7  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
6     <1> stat vK/1 ->7
5        <1> stat K/1 ->6
4           <1> stat K/1 ->5
-              <1> ex-rv2sv sK/1 ->4
3                 <#> gvsv[*_] s ->4
-e syntax OK

and it might think that it is in void context at run time:

$ ./perl -Ilib -le 'print 1, 2, 3,(stat stat stat), 4, 5, 6'
1456

It ate my stack items!

If it reads past the beginning of the stack, it can crash.

Just apply scalar context, and Bob’s your uncle, of course.

op.c
t/op/stat.t

diff --git a/op.c b/op.c
index 0163b7a..cd9023a 100644 (file)
--- a/op.c
+++ b/op.c
@@ -9710,6 +9710,7 @@ Perl_ck_ftst(pTHX_ OP *o)
            op_free(o);
            return newop;
        }
+       scalar((OP *) kid);
        if ((PL_hints & HINT_FILETEST_ACCESS) && OP_IS_FILETEST_ACCESS(o->op_type))
            o->op_private |= OPpFT_ACCESS;
        if (type != OP_STAT && type != OP_LSTAT
index a807b90..2d7e3c7 100644 (file)
@@ -25,7 +25,7 @@ if ($^O eq 'MSWin32') {
     ${^WIN32_SLOPPY_STAT} = 0;
 }
 
-plan tests => 115;
+plan tests => 116;
 
 my $Perl = which_perl();
 
@@ -632,6 +632,10 @@ SKIP: {
     ok(1, 'can "lstat -t" without crashing');
 }
 
+# [perl #126064] stat stat stack busting
+is join("-", 1,2,3,(stat stat stat),4,5,6), "1-2-3-4-5-6",
+  'stat inside stat gets scalar context';
+
 END {
     chmod 0666, $tmpfile;
     unlink_all $tmpfile;