本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回のハッカーはcharsbarこと石垣憲一さんで、
Perl 5.26リリース
去る2017年5月30日にPerl 5.
Perl 5はかれこれ20年以上も同じメジャーバージョンを使い続けていることからも察せられるように、
Perl 5.
本稿では、@INC
からカレントディレクトリが削除された経緯とその対策を説明し、
@INCからカレントディレクトリが削除
Perlはバージョン3の時代である1990年から、@INC
の末尾に、jcode.
というライブラリがよく利用されましたが、jcode.
というファイルを設置するだけで期待したとおりに動作したのは、@INC
の末尾にカレントディレクトリが含まれていたからです。
# ほかの場所にインストールされていなければ
# CGIスクリプトと同じディレクトリにある
# jcode.plを読み込む
require "jcode.pl";
Perl 5.@INC
から.
が削除されました。上のコードはそのままではもう期待どおりの動作はしません
何が問題だったのか
UNIX系OSの世界、
読み込んだ時点でなにがしかのコードが実行されてしまうという点では、
Rubyの対応とPerlの初期の反応
そのため、$:
)
Perlの世界でも、@INC
からカレントディレクトリを削除する提案がされていたほか、
CVE-2016-1238とPerlの対応
この議論は2016年4月にまたも蒸し返されるのですが、
対策を取れば既存のモジュールやアプリケーションが壊れることはこれまでの議論からもわかっていたので、
公式にはCVE-2016-1238というIDで識別されるこの脆弱性に関する議論は1年近く続きました。その詳細は割愛しますが、@INC
からカレントディレクトリが削られました。コアモジュールのうち特によく使われるものについては、do
関数については、
どのように対応すればよいのか
この変更によって、Catalyst
のように多くの利用実績があるWebアプリケーションフレームワークなども含まれているため、
どのように対応すればよいかは立場によって変わりますが、
ツールチェインを更新する
一般的なCPANモジュールについては、
最近新たにPerl 5.Test::Harness
モジュールを最新のものにしてください。
CPANクライアントとしてcpanm
コマンドを使っている人は、
$ cpanm App::cpanminus Test::Harness
また、Minilla
などのモジュールオーサリングツールを使っている場合も、
環境変数を設定する
CPANクライアントを最新のものに更新するだけでインストール時の問題が解決するのは、PERL_
という環境変数を設定して、@INC
の末尾にカレントディレクトリを追加させているためです。
この環境変数はあくまでも一時しのぎで、
$ export PERL_USE_UNSAFE_INC=1
適切な検索パスを指定する
CPANモジュールのようにほかのユーザーにインストールして使ってもらうモジュールやアプリケーションを開発している人は、
もっとも、lib
ディレクトリの下にまとめられているモジュールやアプリケーション自体がこの問題の影響で挙動を変えることはめったにありません。問題となるのはたいてい、Makefile.
やBuild.
、
これらの中でinc::Module::Install
やt::Testの
ようなディレクトリ名を含むモジュールを利用している場合は、@INC
の中にカレントディレクトリが含まれていることが前提となっているため、
従来どおりの挙動にしたい場合は、Makefile.
やテストファイルの先頭で、@INC
の末尾にカレントディレクトリを追加してください。
# 末尾にデフォルトのカレントディレクトリがなければ追加
BEGIN { push @INC, "." if $INC[-1] ne "."; }
上記で条件節を追加しているのは、
CPANディストリビューションの場合、lib
モジュールを使ってカレントディレクトリを追加してもよいでしょう。
use lib ".";
ただし、lib
モジュールは@INC
の先頭にカレントディレクトリを追加するため、FindBin
モジュールや__
キーワードなどを利用して、@INC
には相対パスを含めないようにしたほうがよいでしょう。
use FindBin;
use lib $FindBin::Bin;
別のツールに切り替える
場合によっては、
たとえば、Module::Install
については、Minilla
などのオーサリングツールに移行するか、ExtUtils::MakeMaker
やExtUtils::MakeMaker::CPANfile
などのモジュールを使うことも検討してください。
doやrequireでライブラリを読み込んでいる場合
古くからあるCGIスクリプトなどでrequire
関数を使ってカレントディレクトリにあるライブラリを読み込ませている場合は、
require "./jcode.pl";
アプリケーションの設定をdo
関数で読み込ませている場合も同じです。
do "./config.pl";
もちろん./
の代わりに$FindBin::Bin
などでパスを指定してもかまいません。
doの新しい警告
do
はuse
やrequire
と違ってファイルが見つからなくてもエラー終了しないため、@INC
の変更でカレントディレクトリのファイルが見つからなくなっても気付けません。そのため、
do "config.pl" failed, '.' is no longer in @INC;
did you mean do "./config.pl"?
古いPerl向けの対応
ここまではPerl 5.
OSによっては古いバージョンのPerlにこの変更をバックポートしているものがありますが、
簡単に対応可能なPerlかどうかを調べるには、-V
オプションは、
$ perl -V:usesitecustomize
usesitecustomize='define';
define
の値が返ってきたら対応できます。
続いてもう一つPerlの設定を調べます。
$ perl -V:sitelib
sitelib='/usr/local/share/perl5';
表示されたディレクトリの下にsitecustomize.
というファイルがなければ作成し、
if (!$ENV{PERL_USE_UNSAFE_INC}) {
pop @INC if $INC[-1] eq ".";
}
これでperl -V
を実行すると、@INC
から.が消えたことが確認できるはずです
独自のコマンドをインストールする場合
独自のコマンドをインストールするCPANディストリビューションについては、@INC
からカレントディレクトリを抜くようにしたほうがよいでしょう。
典型的にはコマンドの先頭付近に先ほどと同じような行を追加します。
BEGIN { pop @INC if $INC[-1] eq "."; }
なお、@INC
の調整は起動に使われるスクリプトの先頭で一度行えば十分です。Perlに同梱されるコアモジュールの中には、@INC
をローカライズしてカレントディレクトリを省いているものもありますが、
<続きの
本誌最新号をチェック!
WEB+DB PRESS Vol.130
2022年8月24日発売
B5判/
定価1,628円
ISBN978-4-297-13000-8
- 特集1
イミュータブルデータモデルで始める
実践データモデリング
業務の複雑さをシンプルに表現! - 特集2
いまはじめるFlutter
iOS/Android両対応アプリを開発してみよう - 特集3
作って学ぶWeb3
ブロックチェーン、スマートコントラクト、 NFT