[kansaipm] FindBin

Yasushi Nakajima nakajima at netstock.co.jp
Fri Jul 4 22:24:01 CDT 2003


 片松さん、お久しぶりです。XPDFJは実に遅々たる進行状況です。

片松> #!/usr/bin/perl -wT
片松> use strict;
片松> use FindBin;
片松> use lib,$FindBin::Bin;
片松> …
片松> 
片松> Insecure dependency in chdir while running with -T switch at C:/Perl58/lib/Cwd.pm line 419.

 この話ですが、Unixだと起きないですね。Windowsだとダメ。調べてみると、
Cwd.pmが提供するabs_path()(相対パスから絶対パスを得るルーチン)が、
Windowsでは与えられた相対パスにchdirしてからカレントディレクトリを取得す
るという方法を使っている。FindBin.pmを見ると、abs_path()に与えられるパス
はもともと$0から持ってきている。汚染チェックモードでは、$0は外部由来の変
数として汚染扱いなので、結局はchdir()に汚染されたデータを与えていると言
うことでこのようにチェックに引っかかるわけですね。

片松> 今はこの様な感じで適当にごまかしておりますが…
片松> #!/usr/bin/perl -wT
片松> use strict;
片松> package hoge;
片松> BEGIN{
片松> 	our $thisScriptPath = __FILE__;
片松> 	$thisScriptPath =~ s!\/[^/]+?$!!;
片松> }
片松> use lib $hoge::thisScriptPath;

 これだと、$thisScriptPathが相対パスかもしれないので、もしどれかのモジュー
ルでカレントディレクトリを変更していたら、そこから先ではuseやrequireに失
敗する危険がありますね。やはり絶対パスに直してからuse libに渡した方が安
全。File::Spec->rel2abs()を使うといいと思います。File::Spec::Win32は、
Cwdのようにchdir()したりしませんので、汚染チェックには引っかかりません。

use File::Spec;
BEGIN {
	my(undef, $p) = File::Spec->splitpath(File::Spec->rel2abs($0));
	use lib $p;
}

 ただし、5.005の頃のFile::Spec::Win32にはバグがあって上記のコードは無限
ループになります。Win32.pmに次のパッチを当てる必要があります。

*** win32.pm.org	Sat Jul  5 12:12:22 2003
--- win32.pm	Sat Jul  5 12:12:42 2003
***************
*** 360,370 ****
      if ( ! $self->file_name_is_absolute( $path ) ) {
  
          # Figure out the effective $base and clean it up.
!         if ( ! $self->file_name_is_absolute( $base ) ) {
!             $base = $self->rel2abs( $base ) ;
!         }
!         elsif ( !defined( $base ) || $base eq '' ) {
              $base = cwd() ;
          }
          else {
              $base = $self->canonpath( $base ) ;
--- 360,370 ----
      if ( ! $self->file_name_is_absolute( $path ) ) {
  
          # Figure out the effective $base and clean it up.
!         if ( !defined( $base ) || $base eq '' ) {
              $base = cwd() ;
+         }
+         elsif ( ! $self->file_name_is_absolute( $base ) ) {
+             $base = $self->rel2abs( $base ) ;
          }
          else {
              $base = $self->canonpath( $base ) ;


 それから、片松さんの案を見ていて気づいたのですが、$0は汚染されていると
みなされますが、$p = __FILE__; とした場合の$pは汚染されているとはみなさ
れません。__FILE__はスクリプト中に書かれた文字列と同じ扱いなので、外部由
来とは判断されないんですね。でも、$0と__FILE__は結局はどちらもOSからperl
に渡された同じコマンドライン引数に由来するので、ちょっと変ですね。

-- 
Yasushi Nakajima <nakajima at netstock.co.jp>




More information about the Kansai-pm mailing list