Perl Hackers Hub

第46回 Perl 5.26で変わること(1)

この記事を読むのに必要な時間:およそ 4 分

どのように対応すればよいのか

この変更によって,CPANで公開されているものに限っても数千件のディストリビューションが影響を受けることがわかっています。その中にはCatalystのように多くの利用実績があるWebアプリケーションフレームワークなども含まれているため,実際に影響を受ける人やアプリケーションの数はさらに増えることでしょう。

どのように対応すればよいかは立場によって変わりますが,典型的な対策は次のとおりです。

ツールチェインを更新する

一般的なCPANモジュールについては,CPANクライアントを最新のものに更新しておけば,この変更に由来するインストール時の問題はほぼ解決します。

最近新たにPerl 5.26をインストールした人ならすでに最新のツールを使っていると思いますが,環境によっては5.26より前のPerlにも今回の変更の一部が適用されていることがあります。モジュールのインストール時にファイルが見つからないなどのエラーを見かけたら,CPANクライアントとTest::Harnessモジュールを最新のものにしてください。

CPANクライアントとしてcpanmコマンドを使っている人は,コマンドラインから以下を実行することで最新版に更新できます。

$ cpanm App::cpanminus Test::Harness

また,Minillaなどのモジュールオーサリングツールを使っている場合も,最新にしておきましょう。

環境変数を設定する

CPANクライアントを最新のものに更新するだけでインストール時の問題が解決するのは,内部で一時的にPERL_USE_UNSAFE_INCという環境変数を設定して,Perlに従来どおり@INCの末尾にカレントディレクトリを追加させているためです。

この環境変数はあくまでも一時しのぎで,数年後にはサポートされなくなる可能性も高いのですが,ローカルの開発環境で自分以外のユーザーがいないとか,CIContinuous Integration継続的インテグレーション)環境のように都度環境を使い捨てるから大丈夫という場合は,ログイン時などに適宜この環境変数をセットしておくことで,問題を先送りできます。

$ export PERL_USE_UNSAFE_INC=1
適切な検索パスを指定する

CPANモジュールのようにほかのユーザーにインストールして使ってもらうモジュールやアプリケーションを開発している人は,検索パスにカレントディレクトリがなくてもモジュールやアプリケーションが正常動作するようにしておいたほうがよいでしょう。

もっとも,libディレクトリの下にまとめられているモジュールやアプリケーション自体がこの問題の影響で挙動を変えることはめったにありません。問題となるのはたいてい,Makefile.PLBuild.PL各種のテストファイルといった補助的なスクリプト類です。

これらの中でinc::Module::Installt::Testのようなディレクトリ名を含むモジュールを利用している場合は,暗黙のうちに@INCの中にカレントディレクトリが含まれていることが前提となっているため,適切な検索パスを追加する必要があります。

従来どおりの挙動にしたい場合は,Makefile.PLやテストファイルの先頭で,@INCの末尾にカレントディレクトリを追加してください。

# 末尾にデフォルトのカレントディレクトリがなければ追加
BEGIN { push @INC, "." if $INC[-1] ne "."; }

上記で条件節を追加しているのは,古いPerlや,前述した環境変数が設定された場合に何度もカレントディレクトリを追加させないためです。

CPANディストリビューションの場合,普通はカレントディレクトリが安全である(アーカイブを展開したあと,悪意を持った第三者のファイルがカレントディレクトリ以下に紛れ込むことはない)ことが前提になっているので,簡潔にlibモジュールを使ってカレントディレクトリを追加してもよいでしょう。

use lib ".";

ただし,libモジュールは@INCの先頭にカレントディレクトリを追加するため,実行中にファイル検索などの理由でカレントディレクトリを移動すると,かえって意図しないモジュールを読み込みやすくなってしまう(インストールされているモジュールよりも移動後のカレントディレクトリに存在しているモジュールを優先してしまう)危険性があります。安全性を優先するなら,FindBinモジュールや__FILE__キーワードなどを利用して,@INCには相対パスを含めないようにしたほうがよいでしょう。

use FindBin;
use lib $FindBin::Bin;
別のツールに切り替える

場合によっては,カレントディレクトリを検索パスに戻すのではなく,そもそもカレントディレクトリを追加しなくてもよいツールに切り替えるべきかもしれません。

たとえば,この問題の影響を受ける代表的なモジュールであるModule::Installについては,さまざまな理由からもう新規の開発では使うべきではないと最新版のドキュメントに警告が書いてあります。可能であればMinillaなどのオーサリングツールに移行するか,特殊な設定が不要ならもとのExtUtils::MakeMakerExtUtils::MakeMaker::CPANfileなどのモジュールを使うことも検討してください。

doやrequireでライブラリを読み込んでいる場合

古くからあるCGIスクリプトなどでrequire関数を使ってカレントディレクトリにあるライブラリを読み込ませている場合は,次のように書くと,ライブラリがカレントディレクトリにあることを明示できます。

require "./jcode.pl";

アプリケーションの設定をdo関数で読み込ませている場合も同じです。

do "./config.pl";

もちろん./の代わりに$FindBin::Binなどでパスを指定してもかまいません。

doの新しい警告

douserequireと違ってファイルが見つからなくてもエラー終了しないため,今回の@INCの変更でカレントディレクトリのファイルが見つからなくなっても気付けません。そのため,Perl 5.26ではカレントディレクトリに該当のファイルが存在している場合に限り,次のような警告を出します。

do "config.pl" failed, '.' is no longer in @INC;
did you mean do "./config.pl"?
古いPerl向けの対応

ここまではPerl 5.26で従来の挙動を取り戻したい場合にどうすればよいかを説明してきましたが,場合によっては,Perl本体のバージョンは上げられないけれど,この検索パスの保護は導入したいということもあるかもしれません。

OSによっては古いバージョンのPerlにこの変更をバックポートしているものがありますが,Perlの設定によってはPerlにパッチを当てたりしなくても簡単にこのしくみを導入できることがあります。

簡単に対応可能なPerlかどうかを調べるには,次のコマンドを実行します。大文字の-Vオプションは,そのまま使えばPerlの詳細設定を表示しますが,コロンに続いて項目名を渡すとその項目のコンパイルオプションを表示します。

$ perl -V:usesitecustomize
usesitecustomize='define';

defineの値が返ってきたら対応できます。

続いてもう一つPerlの設定を調べます。

$ perl -V:sitelib
sitelib='/usr/local/share/perl5';

表示されたディレクトリの下にsitecustomize.plというファイルがなければ作成し,次のようなコードを追加します注4⁠。このディレクトリとファイルには忘れずに適切なパーミッションを設定しておいてください。

if (!$ENV{PERL_USE_UNSAFE_INC}) {
    pop @INC if $INC[-1] eq ".";
}

これでperl -Vを実行すると,@INCから.が消えたことが確認できるはずです注5⁠。

独自のコマンドをインストールする場合

独自のコマンドをインストールするCPANディストリビューションについては,古い環境での安全性を高めるため,コマンドの先頭で@INCからカレントディレクトリを抜くようにしたほうがよいでしょう。

典型的にはコマンドの先頭付近に先ほどと同じような行を追加します。

BEGIN { pop @INC if $INC[-1] eq "."; }

なお,このような@INCの調整は起動に使われるスクリプトの先頭で一度行えば十分です。Perlに同梱されるコアモジュールの中には,影響の大きさを鑑みて動的にモジュールをロードする場面でモジュール内部で@INCをローカライズしてカレントディレクトリを省いているものもありますが,これは関心の分離の原則をあえて破った例外的な処置としてよいでしょう。

注4)
環境によっては,ここで表示されたのとは異なるディレクトリを利用するようにパッチが当たっていることがあります。たとえば,DebianjessieのシステムPerlでは,/etc/perl以下にファイルを用意しなければなりません。
注5)
もちろんこのしくみは,@INCにカレントディレクトリを追加するのに使うこともできます。

<続きの(2)こちら。>

WEB+DB PRESS

本誌最新号をチェック!
WEB+DB PRESS Vol.115

2020年2月22日発売
B5判/168ページ
定価(本体1,480円+税)
ISBN978-4-297-11187-8

  • 特集1 
    競技プログラミングの過去問で学ぶアルゴリズム
  • 特集2
    iOS 13徹底活用
  • 特集3
    小一時間でゲームを作る

著者プロフィール

石垣憲一(いしがきけんいち)

翻訳家兼プログラマ。歴史ネタ担当。最近は主にCPANツールチェーン界隈の片隅で活動中。

URL:http://d.hatena.ne.jp/charsbar/