Subject: | please circumvent a core Perl bug in Getopt::Long |
Date: | Thu, 9 Mar 2017 07:21:13 +0000 (UTC) |
To: | "bug-Getopt-Long [...] rt.cpan.org" <bug-Getopt-Long [...] rt.cpan.org> |
From: | Sébastien Blondeel <sblondeel [...] yahoo.com> |
Getopt-Long-2.42
Perl v5.20.2
Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) x86_64 GNU/Linux
What follows is probably related to
https://rt.perl.org/Public/Bug/Display.html?id=77706
with a discussion and a short bug trigger in
https://rt.perl.org/Public/Bug/Display.html?id=114372
the short bug trigger being
$ perl -e '@x=(1,2); @h{@x=sort}=@x'
panic: attempt to copy freed scalar e45e78 at -e line 1.
If this fails:
my @L = (1);
sub a { my ($l) = @_; shift @$l while @$l; }
sub b { a(\@L); my $a = shift; }
b(@L);
Then surely this must fail:
sub a { my ($l) = @_; shift @$l while @$l; }
sub main {
a(\@ARGV);
my $a = shift;
}
main(@ARGV);
This is why this fails:
sub GetOptionsFromArray {
my ($argv, @optionlist) = @_;
while (@$argv > 0) {
shift(@$argv);
}
}
sub main {
GetOptionsFromArray(\@ARGV);
my $arg = shift;
}
main(@ARGV);
Which makes @ARGV rather unusable after a call to Getoptions:
https://stackoverflow.com/questions/26508899/error-panic-attempt-to-copy-freed-scalar-when-using-getoptlong
use Getopt::Long qw(GetOptions);
sub main {
GetOptions();
my $arg=shift;
}
main(@ARGV);
In other words, pretty please, use the following bugware in Getopt::Long while
this long-standing, hard to fix, far and deep reaching, core Perl bug exists.
What follows should be enough and not hurt performance too much; maybe add comments
to explain why we must use a reference to a copy of @ARGV, not a reference to
@ARGV itself:
--- Long.pm.orig 2017-03-09 08:07:20.000000000 +0100
+++ Long.pm 2017-03-09 08:07:49.000000000 +0100
@@ -177,7 +177,7 @@
sub getoptions {
my ($self) = shift;
- return $self->getoptionsfromarray(\@ARGV, @_);
+ return $self->getoptionsfromarray([@ARGV], @_);
}
sub getoptionsfromarray {
@@ -255,7 +255,7 @@
sub GetOptions(@) {
# Shift in default array.
- unshift(@_, \@ARGV);
+ unshift(@_, [@ARGV]);
# Try to keep caller() and Carp consistent.
goto &GetOptionsFromArray;
}