【问题标题】:Perl "do", with relative path beginning with "." or ".."Perl "do",相对路径以 "." 开头要么 ”..”
【发布时间】:2018-09-22 02:25:06
【问题描述】:

我正在尝试使用 Perl 的 do EXPR 函数作为穷人的配置解析器,使用第二个 .pl 文件,它只返回一个列表作为配置信息。 (我认为这可能是do 的理想用途,尤其是因为我可以在我的代码中写“do or die”。)这里有一个例子:

main.pl

# Go read the config file
my %config = do './config.pl';

# do something with it
$web_object->login($config{username}, $config{password});

config.pl

# Configuration file for main script
(
  username => "username",
  password => "none_of_your_business",
  favorite_color => "0x0000FF",
);

阅读Perldoc for do 提供了很多关于相对路径的有用建议 - 搜索 @INC 和修改 %INC,关于 5.26 不搜索“.”的特殊警告。等等。但它也有这些位:

# 加载确切的指定文件(./ 和../ 特殊情况)...


使用 do 与相对路径(./ 和 ../ 除外),如...

然后它实际上从不费心解释“./”或“../”的特殊情况路径处理 - 一个重要的遗漏!

所以我的问题都是关于“当你do './file.pl';真正会发生什么”?比如……

  • 尽管 CWD 从 @INC 中删除,但此语法在 5.26 中是否仍然有效?
  • 无论如何,“./”从谁的角度来看:Perl 二进制文件、执行的 Perl 脚本、来自用户 shell 的 CWD,还是其他?
  • 是否存在需要注意的安全风险?
  • 这比修改 @INC 并仅使用基本文件名更好还是更糟?

感谢任何见解。

【问题讨论】:

  • Re "然后它实际上从不费心解释“./”或“../”的特殊情况路径处理 - 一个重要的遗漏!”,呵呵, "do './stat.pl' 很像eval `cat stat.pl`;"
  • Re "无论如何从谁的角度来看是"./"",Perl 只是将路径传递给操作系统,. 引用 CWD。​​span>
  • Re "是否有需要注意的安全风险?",忘记安全风险,让它工作怎么样。不要对 CWD 做出假设。 Solutions。 (是的,这对 setuid 脚本来说是一个安全风险。)
  • 正在回答的问题,我想补充一下——您为什么要这样做?只需正确使用完整路径,例如来自 ikegami 的链接。

标签: perl perldoc perl-core


【解决方案1】:

好的,所以 - 首先,我不确定您的 config.pl 是否真的是正确的方法 - 对于初学者来说,它不是 perl,因为它无法编译。不过,无论哪种方式,尝试评估内容以“解析配置”通常都不是一个好计划——它很容易出现令人不快的故障和安全漏洞,因此应保留在需要时使用。

我会敦促您采取不同的方式:

把它写成一个模块

类似这样的:

package MyConfig;

# Configuration file for main script
our %config = (
   username       => "username",
   password       => "none_of_your_business",
   favorite_color => "0x0000FF",
);

然后你可以在你的主脚本中:

use MyConfig; #note - the file needs to be the same name, and in @INC

并以如下方式访问它:

print $MyConfig::config{username},"\n"; 

如果您不能将其放入现有的 @INC - 这可能是您不能放入的原因,FindBin 允许您使用相对于脚本位置的路径:

use FindBin; 
use lib "$FindBin::Bin"; 
use MyConfig;

将您的“配置”编写为已定义的可解析格式,而不是可执行代码。

YAML

YAML 非常适合配置文件,尤其是:

use YAML::XS;

open ( my $config_file, '<', 'config.yml' ) or die $!; 
my $config = Load ( do { local $/; <$config_file> });

print $config -> {username};

你的配置文件看起来像:

username: "username"
password: "password_here"
favourite_color: "green"
air_speed_of_unladen_swallow: "african_or_european?"

(YAML 还支持多维数据结构、数组等。不过你似乎不需要这些。)

JSON

JSON based 看起来差不多,只是输入是:

{
  "username": "username",
  "password": "password_here",
  "favourite_color": "green",
  "air_speed_of_unladen_swallow": "african_or_european?"
}

你阅读它:

use JSON;
open ( my $config_file, '<', 'config.json' ) or die $!; 
my $config = from_json ( do { local $/; <$config_file> });

使用相对路径进行配置:

您完全不必担心@INC。您可以简单地基于相对路径使用...但更好的选择是不要这样做,而是使用 FindBin - 它可以让您指定“相对于我的脚本路径”,这样更加健壮。

 use FindBin;
 open ( my $config_file, '<', "$FindBin::Bin/config.yml" ) or die $!; 

然后你就会知道你正在阅读与你的脚本在同一目录中的那个,无论它是从哪里调用的。

具体问题:

无论如何从谁的角度来看“./”:Perl 二进制文件、执行的 Perl 脚本、来自用户 shell 的 CWD,还是其他?

当前工作目录通过进程向下传递。所以默认情况下用户的shell,除非perl脚本执行chdir

是否有需要注意的安全风险?

任何时候您“评估”某些东西,就好像它是可执行代码(并且EXPR 可以)存在安全风险。它可能并不大,因为脚本将以用户身份运行,而用户是可以篡改CWD的人。核心风险是:

  • 用户位于“不同”目录中,其他人在该目录中放置了恶意软件以供他们运行。 (例如,想象“config.pl”中有rm -rf /*)。也许/tmp 中有一个“config.pl”,他们不小心“运行”了?
    • evaling 的东西有一个错字,并以时髦和意想不到的方式破坏了脚本。 (例如,它可能会重新定义 $[ 并从今以后以难以调试的方式混淆程序逻辑)
  • 脚本在特权上下文中执行任何操作。情况似乎并非如此,但请参阅前一点并想象一下您是root 还是其他特权用户。

这比修改 @INC 并仅使用基本文件名更好还是更糟?

更糟糕的国际海事组织。实际上,根本不要修改@INC,而是使用完整路径,或者使用FindBin 的相对路径。并且不要在不必要的时候eval 事情。

【讨论】:

  • 有趣的是 do 解析配置文件现在显然不受欢迎......因为我专门从官方 Perl 文档中得到了这个想法! perldoc.perl.org/functions/do.html(滚动到底部)
  • 这是你可以使用它的一个例子,并不是说你必须。 doeval 都有一席之地 - 它们确实让您几乎可以运行任意/用户指定的代码。通过这样做,您在代码中引入了危险 - 有时值得冒险,但对于像“加载配置文件”这样简单的事情......当更简单和更安全的情况下,运行时“混乱地爆炸”根本不值得方法可用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-08
  • 2016-05-22
  • 2013-09-06
  • 2012-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多