Skip Menu |

This queue is for tickets about the Devel-Declare CPAN distribution.

Report information
The Basics
Id: 32040
Status: resolved
Priority: 0/
Queue: Devel-Declare

People
Owner: Nobody in particular
Requestors: mschwern [...] cpan.org
Cc:
AdminCc:

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



Subject: Segfault if used in a one liner.
The attached test demonstrates that Devel::Declare segfaults when used in a one liner (or when the program is coming from STDIN). It demonstrates some sort of memory or string corruption.
Subject: oneliner.t
#!/usr/bin/perl -w use Test::More tests => 2; ok open my $mod, '>', "Foo.pm"; print $mod <<'END'; package Foo; use Devel::Declare; BEGIN { Devel::Declare->install_declarator( "Foo", "method", DECLARE_PACKAGE | DECLARE_PROTO, sub { return q[my $self = shift;]; }, sub { my ($name, $proto, $sub, @rest) = @_; if (defined $name && length $name) { unless ($name =~ /::/) { $name = "Foo::${name}"; } no strict "refs"; *{$name} = $sub; } return wantarray ? ($sub, @rest) : $sub; } ); } 1; END my $prog = <<'END'; package Foo; method foo () {}; END is system("$^X -I. -MFoo -wle '$prog'"), 0; END { unlink 'Foo.pm'; }
This is caused by the scalar holding the code of -e being too small for additional code to be injected. It'd need to be reallocated, which won't work as the parser holds pointers to the location of the underlying char buffer. Latest Devel-Declare now bails out instead of corrupting your memory. Not sure if this can be fixed from within Devel-Declare.
For some reason the filter Devel::Declare adds for SvGROWing the line string before the parser sees it isn't applied to the code in -e.
FWIW this bug is blocking the use of Devel::Declare, or modules which use DD, in perl5i.
The linestr-reallocating source filter can't take effect on -e code, nor on string-evaled code, because in both cases the entire code is presented to the tokeniser up front. A source filter operates on the input handle from which source is read, so applies only when reading from a file, stdin, or equivalent. A second problem for the source filter is that it has to be installed separately for each file it is to have effect on. So, given your Foo.pm module, a file starting "use Foo;" is fine, the filter being applied to the file, but sticking "-MFoo" on the command line doesn't work, because the file isn't open yet and the source filter goes somewhere useless. These aspects of source filters are unavoidable, and it's not possible to fix on perls where the source filter is the only feasible way to reallocate linestr. You'll notice that you don't have these problems with string-evaled code, despite source filters not applying there. On older perls, D:D uses some nasty tricks to intercept string evals and preemptively reallocate the linestr. These tricks can't be used for other situations such as -e. On Perl 5.13.6 and above, D:D uses a block hook to influence string eval slightly more cleanly. As a bonus, the block hook *does* apply to -e, code in files, and so on, and it only needs to be set up once. The result is that opening any code block, after D:D has been initialised, will cause linestr reallocation. Unfortunately the mere start of a code file doesn't count as opening a block (though the start of a string eval does); it has to be a real block in the code. But the result is a limited ability to use D:D in one-liners: $ perl5.14.1 -MFoo -le '{;} package Foo; method () {}; print "ok"' ok I hope that's enough to be useful to you.