Don’t let method-BLOCK read beyond the stack
authorFather Chrysostomos <sprout@cpan.org>
Tue, 15 May 2012 19:52:13 +0000 (12:52 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Mon, 21 May 2012 23:51:46 +0000 (16:51 -0700)
commitf226e9be7c69188b9b91606ccfca77843eaf9a31
tree49c294e8ee8e50694b77cac200a323972d606b46
parent5114d26397c43471da5a7b6095cacf2201878986
Don’t let method-BLOCK read beyond the stack

$ ./perl -Ilib -e 'use B::Deparse; warn for new{}'
Can't call method "new" on an undefined value at -e line 1.
$ ./perl -Ilib -e 'use B::Deparse; warn for "foo", new{}'
Can't call method "new" without a package or object reference at -e line 1.

Now, why did adding "foo" there change the error message?  Because
new{} looks one past the end of the stack.  Adding "foo" just caused
it to look at the next dropping left behind by B::Deparse, which just
happened to be some non-ref that was not recognised as a package name.

In fact, I can even do this to control what value it picks up:

$ ./perl -Ilib -e '@_ = ("foo"); new{}'
Can't locate object method "new" via package "foo" (perhaps you forgot to load "foo"?) at -e line 1.

And then it calls a method with literally no arguments in @_:

$ ./perl -Ilib -we 'use B::Deparse; @_ = "B::Deparse"; warn new{}'
Use of uninitialized value $class in bless at lib/B/Deparse.pm line 569.
Explicit blessing to '' (assuming package main) at lib/B/Deparse.pm line 569.
Can't locate object method "init" via package "main" at lib/B/Deparse.pm line 588.

And the ultimate:

$ ./perl -Ilib -we 'for(1..1000000) {eval " warn +(1)x$_, new{}"}'
Bus error
$ ./perl -Ilib -we 'for(866..1018) { eval { warn +(1)x$_, new{} }}'
Bus error

OK, that’s enough fun.

With this commit, I’m making it an error to call a method this way
with no arguments.  I’m using the ‘without a package or object refer-
ence’ error message, as opposed to ‘on an undefined value’, because
there isn’t any undefined value; there’s nothing at all.
pp_hot.c
t/op/method.t