【问题标题】:What interprets Perl filename checks?什么解释 Perl 文件名检查?
【发布时间】:2012-10-19 11:59:15
【问题描述】:

代码 'if(-e "filename")' 测试在执行包含该代码的脚本的目录中是否存在名为 filename 的文件。

什么是名称检查?珀尔?操作系统? Bash on POSIX-os?

'if(-e "cat string")' 会在 Linux 上执行 cat 命令吗?


我想知道为了能够避免像“../file”这样不需要的文件访问会访问父目录中的文件。


分享我的校验码:

if($folder =~ m/$([\\]?\.[\\]?\.|[\\]?\\|[\\]?\/|[\\]?\?|[\\]?*|[\\]?:|[\\]?\||[\\]?\"|[\\]?\<|[\\]?\>)^|$([\\]?\.[\\]?\.|[\\]?\\|[\\]?\/|[\\]?\?|[\\]?*|[\\]?:|[\\]?\||[\\]?\"|[\\]?\<|[\\]?\>)\/|\/([\\]?\.[\\]?\.|[\\]?\\|[\\]?\/|[\\]?\?|[\\]?*|[\\]?:|[\\]?\||[\\]?\"|[\\]?\<|[\\]?\>)\/|\/([\\]?\.[\\]?\.|[\\]?\\|[\\]?\/|[\\]?\?|[\\]?*|[\\]?:|[\\]?\||[\\]?\"|[\\]?\<|[\\]?\>)^|\$'[^']*'/)
{
    #error
}


更新正则表达式:

if($folder =~ m/(\/|\\)|$([\\]?\.[\\]?\.^|$[\\]?(\*|\?)^|\$'[^']*'/)
{
    #error
}

解释:$folder 应该已经是一个纯文件名了。如果它包含 Windows 或 POSIX 路径分隔符或者是(任何转义的)父目录反向链接或者是(任何转义的)通配符(因为它匹配第一个匹配文件并且至少在 Mac OS X 上返回 true)或者包含 C ANSI 转义任何地方的序列,信号错误。其他任何东西,即使不合法或不合法,也应该简单地返回“文件不存在”,因此可以提供给“if(-e $folder)”。

【问题讨论】:

  • 我没有。谢谢。我现在有。 :-)
  • 只看主要交替的第一个成员 (...|...|...|...),我可以告诉你,你的线路位置向后。 $ 匹配行的end^ 开头。将美元符号放在开头不会匹配任何内容--除非您正在进行多行匹配。
  • 你是对的。对不起大家感兴趣。它必须是 ^...$。我会把它留给用户来纠正它。
  • 如果你想去掉路径,也许可以看看File::Basename

标签: perl filenames sanitization


【解决方案1】:

操作系统可以。 Perl 对-e(以及其他类似-s 的调用)的调用是通过调用C 库函数stat 来实现的。

没有涉及到 shell,因此"cat some_file" 不会被执行。相反,操作系统会寻找一个名为“cat some_file”的文件。

stat 当然可以用相对路径名来调用。如果您不希望这样做,则删除除文件名+扩展名之外的所有内容。这种事情有Perl modules

我不想调试/查看您提出的正则表达式,因为老实说,它完全不可读且不可维护。

【讨论】:

  • 谢谢,仅从文件名开始是一个好的开始,请参阅我对 cdarke 答案的评论。这将使重新更容易。你知道一种使 re 可读和可维护的方法吗?欢迎了解这种方式!
【解决方案2】:
  1. 名称检查谁? 最后,所有文件 I/O 都由操作系统完成,除非您是设备驱动程序。 Perl 向操作系统发出请求以进行检查,尽管它可能会通过 C 运行时库来执行此操作。为什么要问?

  2. 'if(-e "cat string")' 会在 Linux 上执行 cat 命令吗? 不会。语法错误。打开文件,然后自己阅读。好的,如果您必须使用 cat,请使用 systemxq,具体取决于您要对输出执行的操作。

  3. 您想知道以便能够避免像“../file”这样的不受欢迎的文件访问吗?为什么这是不受欢迎的?是..,还是前导目录名?

    use File::Basename;
    my $name = basename($filename);
    

将删除前导目录名称。

【讨论】:

  • 删除前导目录名称将比我原来的方法更好。文件名参数只能是文件名,因此不需要其他任何内容,请参阅我对 dan1111 的回答的评论
【解决方案3】:

Perl 不使用 shell 来检查文件是否存在。您可以将-e 视为内部Perl 函数,尽管它的外观很奇怪。它不能用作执行 shell 命令的偷偷摸摸的方式。

我认为您不需要这么复杂的正则表达式。如果您不希望用户能够进入父目录,只需确保文件名以单词字符开头(无论如何在 Linux 上):

if($folder =~ m/^\W/)
{
    print "path doesn't start with an alphanumeric character!";
}

当然,如果您担心,以这种方式强制执行路径是一种糟糕的安全方法。相反,您应该正确设置您的权限。

【讨论】:

  • 你是对的,文件/文件夹权限可以而且应该用于避免访问不能读取的文件夹。如果可以读取一个文件夹,检查文件访问参数是否纯粹是一个文件名(即剥离目录部分)和一个很好的文件名(仍然需要一些检查 *)就足够了,因为我将同意几分钟后上面的早期答案。 *:\.\.在 linux 上将是父目录的名称,该目录将存在并且通常可以访问)
猜你喜欢
  • 1970-01-01
  • 2018-11-30
  • 2011-04-25
  • 2014-01-16
  • 1970-01-01
  • 1970-01-01
  • 2019-10-14
  • 2015-07-15
  • 2011-03-01
相关资源
最近更新 更多