Skip to content

Commit 651569b

Browse files
committed
briefly check if the downloaded cpanm or perlbrew seems to be a valid perl program,
and die with some reasonable message if not. Since we download them from github and github has been in maintainence frequently enough to make this a sensible issue, this commit perform a super dummy check on the downloaded content to see if they begin with "#!/" and decided whether they are valid or not. Of course this is far from accurate, but let's see if it is helpful.
1 parent 5dd901b commit 651569b

5 files changed

+98
-3
lines changed

lib/App/perlbrew.pm

+15-1
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,20 @@ sub do_install_program_from_url {
13701370

13711371
my $body = http_get($url) or die "\nERROR: Failed to retrieve $program_name executable.\n\n";
13721372

1373+
unless ($body =~ m{\A#!/}s) {
1374+
my $x = joinpath($ENV{TMPDIR} || "/tmp", "${program_name}.downloaded.$$");
1375+
my $message = "\nERROR: The downloaded $program_name program seem to be invalid. Please check if the following URL can be reached correctly\n\n\t$url\n\n...and try again latter.";
1376+
1377+
unless (-f $x) {
1378+
open my $OUT, ">", $x;
1379+
print $OUT $body;
1380+
close($OUT);
1381+
$message .= "\n\nThe previously downloaded file is saved at $x for manual inspection.\n\n";
1382+
}
1383+
1384+
die $message;
1385+
}
1386+
13731387
if ($body_filter && ref($body_filter) eq "CODE") {
13741388
$body = $body_filter->($body);
13751389
}
@@ -1823,7 +1837,7 @@ sub run_command_install_patchperl {
18231837

18241838
sub run_command_install_cpanm {
18251839
my ($self) = @_;
1826-
$self->do_install_program_from_url('https://github.com/miyagawa/cpanminus/raw/master/cpanm' => 'cpanm');
1840+
$self->do_install_program_from_url('https://raw.github.com/miyagawa/cpanminus/master/cpanm' => 'cpanm');
18271841
}
18281842

18291843
sub run_command_self_upgrade {

t/command-install-cpanm.t

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ $App::perlbrew::PERLBREW_HOME = my $perlbrew_home = tempdir( CLEANUP => 1 );
1515
sub App::perlbrew::http_get {
1616
my ($url) = @_;
1717
like $url, qr/cpanm$/, "GET cpanm url: $url";
18-
return "The content of cpanm";
18+
return "#!/usr/bin/env perl\n# The content of cpanm";
1919
}
2020
}
2121

t/command-install-patchperl.t

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ $App::perlbrew::PERLBREW_HOME = my $perlbrew_home = tempdir( CLEANUP => 1 );
1515
sub App::perlbrew::http_get {
1616
my ($url) = @_;
1717
like $url, qr/patchperl$/, "GET patchperl url: $url";
18-
return "The content of patchperl";
18+
return "#!/usr/bin/env perl\n# The content of patchperl";
1919
}
2020
}
2121

t/failure-command-install-cpanm.t

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env perl
2+
use strict;
3+
use warnings;
4+
use Test::Spec;
5+
use Path::Class;
6+
use IO::All;
7+
use File::Temp qw( tempdir );
8+
9+
use App::perlbrew;
10+
$App::perlbrew::PERLBREW_ROOT = my $perlbrew_root = tempdir( CLEANUP => 1 );
11+
$App::perlbrew::PERLBREW_HOME = my $perlbrew_home = tempdir( CLEANUP => 1 );
12+
13+
{
14+
no warnings 'redefine';
15+
sub App::perlbrew::http_get {
16+
my ($url) = @_;
17+
like $url, qr/cpanm$/, "GET cpanm url: $url";
18+
return "404 not found.";
19+
}
20+
}
21+
22+
describe "App::perlbrew->install_cpanm" => sub {
23+
it "should no produced 'cpanm' in the bin dir, if the downloaded content seems to be invalid." => sub {
24+
my $error;
25+
my $error_produced = 0;
26+
eval {
27+
my $app = App::perlbrew->new("install-cpanm", "-q");
28+
$app->run();
29+
} or do {
30+
$error = $@;
31+
$error_produced = 1;
32+
};
33+
34+
my $cpanm = file($perlbrew_root, "bin", "cpanm")->absolute;
35+
ok $error_produced, "generated an error: $error";
36+
ok !(-f $cpanm), "cpanm is not produced. $cpanm";
37+
};
38+
};
39+
40+
runtests unless caller;

t/failure-command-install-patchperl.t

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env perl
2+
use strict;
3+
use warnings;
4+
use Test::Spec;
5+
use Path::Class;
6+
use IO::All;
7+
use File::Temp qw( tempdir );
8+
9+
use App::perlbrew;
10+
$App::perlbrew::PERLBREW_ROOT = my $perlbrew_root = tempdir( CLEANUP => 1 );
11+
$App::perlbrew::PERLBREW_HOME = my $perlbrew_home = tempdir( CLEANUP => 1 );
12+
13+
{
14+
no warnings 'redefine';
15+
sub App::perlbrew::http_get {
16+
my ($url) = @_;
17+
like $url, qr/patchperl$/, "GET patchperl url: $url";
18+
return "Some invalid piece of text";
19+
}
20+
}
21+
22+
describe "App::perlbrew->install_patchperl" => sub {
23+
it "should not produce 'patchperl' in the bin dir, if the downloaded content does not seem to be valid." => sub {
24+
my $patchperl = file($perlbrew_root, "bin", "patchperl")->absolute;
25+
26+
my $error;
27+
my $produced_error = 0;
28+
eval {
29+
my $app = App::perlbrew->new("install-patchperl", "-q");
30+
$app->run();
31+
} or do {
32+
$error = $@;
33+
$produced_error = 1;
34+
};
35+
36+
ok $produced_error, "generated an error: $error";
37+
ok !(-f $patchperl), "patchperl is *not* installed: $patchperl";
38+
};
39+
};
40+
41+
runtests unless caller;

0 commit comments

Comments
 (0)