gpt4 book ai didi

Perl:quotemeta 仅用于正则表达式吗?文件名安全吗?

转载 作者:行者123 更新时间:2023-12-04 05:21:27 25 4
gpt4 key购买 nike

一边回答this关于使用空格(以及可能的其他字符)安全转义文件名的问题,one of the answers据说使用 Perl 的内置 quotemeta 功能。

quotemeta 的文档指出:

quotemeta (and \Q ... \E ) are useful when interpolating strings 
into regular expressions, because by default an interpolated variable
will be considered a mini-regular expression.

在quotemeta 的文档中,唯一提到它的用途是转义除 /[A-Za-z_0-9]/ 之外的所有字符。与 \用于正则表达式。它没有说明文件名的用途。然而,这似乎是一个非常令人愉快的副作用,如果没有记录的话。

在对思南 Ünür 的评论中 answer对于之前的问题,霍布斯说:

shell escaping is different from regexp escaping, and although I can't come up with a situation where quotemeta would give a truly unsafe result, it's not meant for the task. If you must escape, instead of bypassing the shell, I suggest trying String::ShellQuote which takes a more conservative approach using sh single quotes to defang everything except single quotes themselves, and backslashes for single quotes. – hobbs Aug 13 '09 at 14:25



是否安全 - 完全 - 使用 quotemeta 代替更保守的文件引用,如 String::Shellquote ? quotemeta utf8 或多字节字符安全吗?

我整理了一个不清楚的测试。看来,quotemeta 运行良好,除了带有 \n 的文件名或目录名。 , 或 \r在里面。虽然很少见,但这些字符在 Unix 中是合法的,我见过它们。回想一下某些字符,例如 LF、CR 和 NUL 不能用 \ 转义。 .我用 quotemeta 读取了包含 700k 文件的硬盘驱动器并且没有失败。

我怀疑(虽然我还没有证明)quotemeta 可能会因多字节字符而失败,其中一个或多个字节落入 ASCII 范围。例如, à可以编码为一个字符 (UTF8 C3 A0) 或两个字符(U+0061 给出 a u+0300 是组合重音符号)。我在 quotemeta 中唯一证明的失败是带有 \n 的文件。或 \r在我创建的路径中。我会对其他字符感兴趣放入 nasty_names去测试。

ShellQuote除了在创建文件时以 NUL 结尾的文件名外,所有文件名都可以完美运行。我从来没有失败过。

那么用什么?澄清一下:shell 引用不是我经常做的事情,因为我通常只使用 Perl open 打开一个进程的管道。该方法不会遇到所讨论的 shell 问题。我很感兴趣,因为我看到经常用于文件名转义的 quotemeta 。

(感谢 Ether 我添加了 IPC::System::Simple)

测试文件:
use strict; use warnings; use autodie;
use String::ShellQuote;
use File::Find;
use File::Path;
use IPC::System::Simple 'capturex';

my @nasty_names;
my $top_dir = '/Users/andrew/bin/pipetestdir/testdir';
my $sub_dir = "easy_to_remove_me";
my (@qfail, @sfail, @ipcfail);

sub wanted {
if ($File::Find::name) {
my $rtr;
my $exec1="ls ".quotemeta($File::Find::name);
my $exec2="ls ".shell_quote($File::Find::name);
my @exec3= ("ls", $File::Find::name);

$rtr=`$exec1`;
push @qfail, "$exec1"
if $rtr=~/^\s*$/ ;

$rtr=`$exec2`;
push @sfail, "$exec2"
if $rtr=~/^\s*$/ ;

$rtr = capturex(@exec3);
push @ipcfail, \@exec3
if $rtr=~/^\s*$/ ;
}
}

chdir($top_dir) or die "$!";
mkdir "$top_dir/$sub_dir";
chdir "$top_dir/$sub_dir";

push @nasty_names, "name with new line \n in the middle";
push @nasty_names, "name with CR \r in the middle";
push @nasty_names, "name with tab\tright there";
push @nasty_names, "utf \x{0061}\x{0300} combining diacritic";
push @nasty_names, "utf e̋ alt combining diacritic";
push @nasty_names, "utf e\x{cc8b} alt combining diacritic";
push @nasty_names, "utf άέᾄ greek";
push @nasty_names, 'back\slashes\\Not\\\at\\\\end';
push @nasty_names, qw|back\slashes\\IS\\\at\\\\end\\\\|;

sub create_nasty_files {
for my $name (@nasty_names) {
open my $fh, '>', $name ;
close $fh;
}
}

for my $dir (@nasty_names) {
chdir("$top_dir/$sub_dir");
mkpath($dir);
chdir $dir;
create_nasty_files();
}

find(\&wanted, $top_dir);

print "\nquotemeta failed on:\n", join "\n", @qfail;
print "\nShell Quote failed on:\n", join "\n", @sfail;
print "\ncapturex failed on:\n", join "\n", @ipcfail;
print "\n\n\n",
"Remove \"$top_dir/$sub_dir\" before running again...\n\n";

最佳答案

Quotemeta 在这些假设下是安全的:

  • 只有非字母数字字符才具有特殊含义。
  • 如果非字母数字字符具有特殊含义,则在其前面放置反斜杠将始终使其不特殊。
  • 如果非字母数字字符没有特殊含义,则在其前面放置反斜杠将不起作用。

  • 无论您使用什么引用上下文,shell 都违反了规则 2 和 3——在引号之外,反斜杠换行不会生成换行符;在双引号中,反斜杠标点符号将反斜杠放入输出中(在特定标点符号列表之外);在单引号中,一切都是字面意思,反斜杠甚至不能保护您免受结束单引号的影响。

    我还是推荐 String::ShellQuote如果你需要为 shell 引用一些东西。如果可以的话,我还建议避免让 shell 完全处理您的文件名,使用 LIST -form system/ exec/ openIPC::Open2 , IPC::Open3 , 或 IPC::System::Simple .

    至于除了 shell 之外的东西……许多不同的东西都违反了一个或多个规则。例如,过时的 POSIX“基本”正则表达式和各种编辑器正则表达式具有默认情况下非特殊的标点符号,但在前面带有反斜杠时变得特殊。基本上我要说的是,了解您正在将数据提供给非常好的东西,并正确逃脱。仅使用 quotemeta如果它完全合适,或者如果您将它用于不太重要的事情。

    关于Perl:quotemeta 仅用于正则表达式吗?文件名安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3796682/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com