Почему все модули Perl 5 должны заканчиваться 1;
?
Это потому, что use Module LIST;
эквивалентно BEGIN { require Module; Модуль->импорт(СПИСОК); }
(см. perldoc -f use)
В частности, require Module;
можно реализовать с помощью следующего фрагмента кода (из perldoc -f require):
sub require {
my ($filename) = @_;
if (exists $INC{$filename}) {
return 1 if $INC{$filename};
die "Compilation failed in require";
}
my ($realfilename,$result);
ITER: {
foreach $prefix (@INC) {
$realfilename = "$prefix/$filename";
if (-f $realfilename) {
$INC{$filename} = $realfilename;
$result = do $realfilename; ## HERE
last ITER;
}
}
die "Can't find $filename in \@INC";
}
if ($@) {
$INC{$filename} = undef;
die $@;
} elsif (!$result) { ## AND HERE
delete $INC{$filename};
die "$filename did not return true value";
} else {
return $result;
}
}
Видите do $realfilename
? Посмотрите на perldoc -f do, и вы увидите, что это в значительной степени эквивалент eval system("cat $realfilename")
, что в основном означает глотание файла в и оцените его.
Глядя на perldoc -f eval, вы получите: «В обеих формах возвращаемое значение является значением последнего выражения, вычисленного внутри мини-программы». То есть последний оператор в файле.
Стоит отметить, что если последнее «оператор» является объявлением подпрограммы, это не является истинным значением:
$ perl -le'$r = eval "sub a {1}"; print $r ? "true" : "false"'
false
В то время как 1;
после него:
$ perl -le'$r = eval "sub a {1} 1"; print $r ? "true" : "false"'
true
Глядя снова на sub require
выше, и зная, что делает require
и do
, $result
, что do $ realfilename
возвращает действительно последний оператор eval
ed из файла, который действительно является последним оператором в файле.
Если такой последний оператор не является истинным значением, то ## AND HERE
elsif()
, который я выделил, будет вызываться, а require
умрет, поскольку модуль не возвращает истинное значение.
Модуль use
также умрет, так как он выполняет require
за кулисами.
Короче говоря, не имеет значения, чем вы заканчиваете файл, если это значение понимается perl как true
. Образцы в дикой природе (CPAN) включают 1;
, хотя некоторые в наши дни предпочитают заканчивать свои файлы на 1
(без пропущенной точки с запятой), а другие просто странно используют такие вещи, как ' 0, но true';
или 'supercalifragilisticexpiralidous';
, все из которых Perl анализирует как "истинные" значения.
Надеюсь, вышесказанное вас удовлетворило ;)
Удачного взлома!