Skip Menu |

This queue is for tickets about the Acme-BadExample CPAN distribution.

Report information
The Basics
Id: 9055
Status: resolved
Priority: 0/
Queue: Acme-BadExample

People
Owner: Nobody in particular
Requestors: rwxr-xr-x [...] gmx.de
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.5
Fixed in: (no value)



Subject: [bug] Acme::BadExample runs with this script :-)
Hello, I came upon Acme::BadExample while reading perl.perl6.language. Under SUPPORT it says: You're kidding right? I tell you what. If you can find some way to make this module run, I shall happily stump up a $100 reward, payable in your choice of American dollars, Australian dollars, or as a vertical metre of beer (cartons). Well, my program uses Acme::BadExample and runs more or less normally. So how did I do it? I consider using source filters here cheating, as any program can be "filtered" to "1;"; so I had to apply the dor patch to my otherwise unmodified perl-5.8.6 to make it parse the // die statement. I have all of strict, warnings, diagnostics, English, less, locale, POSIX and utf8, so no problems there. I don't have Win32::ProcessTable or Unix::Processtable, but those can be faked by creating the appropriate %INC entries. Note that Acme::BadExample doesn't touch %INC, only %INV. Another nice touch is that it uses strict 'vars' and declares @CACHE but then proceeds to fill %CACHE. More weirdness: it calls the ordinary function SUPER::new, not SUPER->new (which is a special call to the inherited new); and it opens /root/.<random> for reading, but then attempts to write to it. The infinite loop contains a function call, so thanks to Perl's dynamically scoped "last" we're out of there again. The various die() and system() calls can all be overridden; delete $CORE::{system} is a no-op, since the CORE:: prefix is more of a parser hack than a real package. The only real problems in this module are 1) the use of the // operator, which requires a core patch, and 2) the false return value, which makes require fail (unless you overload string literals :-) Here's my script: #!/usr/local/bin/perl use overload (); # see below # preload a few modules so we can override their import() methods use strict; use warnings (); use diagnostics (); # make it all happen at compile time BEGIN { # disable system() and die() for everyone *CORE::GLOBAL::system = sub { print ":system(@_)\n"; }; *CORE::GLOBAL::die = sub { print ":die(@_)\n"; }; # for whatever reason, Acme::BadExample calls SUPER::new, not # SUPER->new in its constructor. that means we can just define # it here. sub SUPER::new { last } # the "last" above is used to abort the two loops in Acme::BadExample. # one of them would be an infinite loop, but luckily it calls # Acme::BadExample->new, which calls SUPER::new (see above). # A::BE wants to load three modules: it.pm, Win32/ProcessTable.pm and # Unix/ProcessTable.pm. make all of them succeed by adding an @INC hook. push @INC, sub { open my $fh, '<', \'1'; $fh }; # note: predefining entries in %INC would work too, since although # A::BE tries to guard against that, it misspells INC as INV :-) # make no strict, use strict and use warnings no-ops. *strict::unimport = sub {}; *strict::import = sub {}; *warnings::import = sub {}; # insert constant overloading into A::BE. # needed to turn the '' at the end into a true value, grr. *diagnostics::import = sub { overload::constant 'q' => sub { $_[1] || 1 }; }; # create non-empty Acme::SuperHappyFunGeneralExample here to # stop use base '...' from complaining. package Acme::SuperHappyFunGeneralExample; sub foo {} # redirect all bare prints to $_ open my $fh, '>', \$_; select $fh; } use Acme::BadExample; BEGIN { # restore printing to STDOUT select STDOUT; # print "discarding collected output:\n--------------\n$_--------------\n"; } # success print "i told u i was hardcore\n"; __END__ I haven't tried it, but changing the last line of Acme::BadExample from ''; to undef; should make my script fail (I hope that counts as patch :-). HTH, Lukas
use overload (); # see below # preload a few modules so we can override their import() methods use strict; use warnings (); use diagnostics (); # make it all happen at compile time BEGIN { # disable system() and die() for everyone *CORE::GLOBAL::system = sub { print ":system(@_)\n"; }; *CORE::GLOBAL::die = sub { print ":die(@_)\n"; }; # for whatever reason, Acme::BadExample calls SUPER::new, not # SUPER->new in its constructor. that means we can just define # it here. sub SUPER::new { last } # the "last" above is used to abort the two loops in Acme::BadExample. # one of them would be an infinite loop, but luckily it calls # Acme::BadExample->new, which calls SUPER::new (see above). # A::BE wants to load three modules: it.pm, Win32/ProcessTable.pm and # Unix/ProcessTable.pm. make all of them succeed by adding an @INC hook. push @INC, sub { open my $fh, '<', \'1'; $fh }; # note: predefining entries in %INC would work too, since although # A::BE tries to guard against that, it misspells INC as INV :-) # make no strict, use strict and use warnings no-ops. *strict::unimport = sub {}; *strict::import = sub {}; *warnings::import = sub {}; # insert constant overloading into A::BE. # needed to turn the '' at the end into a true value, grr. *diagnostics::import = sub { overload::constant 'q' => sub { $_[1] || 1 }; }; # create non-empty Acme::SuperHappyFunGeneralExample here to # stop use base '...' from complaining. package Acme::SuperHappyFunGeneralExample; sub foo {} # redirect all bare prints to $_ open my $fh, '>', \$_; select $fh; } use Acme::BadExample; BEGIN { # restore printing to STDOUT select STDOUT; # print "discarding collected output:\n--------------\n$_--------------\n"; } # success print "i told u i was hardcore\n";