[英]How can I validate a Perl regex in user input?
我从假定有效的 perl regexp 值的用户那里得到输入列表。 示例可能是:
\\b[Bb]anana\\b
\\s*Apples[BANANA]\\s+
有没有安全的方法来验证这些字符串?
首先,考虑您希望让用户对模式执行多少操作。 Perl 正则表达式可以运行任意代码。
但是,要验证您可以将字符串用作模式而不会导致致命错误,您可以使用qr//
运算符来编译字符串并返回正则表达式。 如果有问题, qr
会给你一个致命错误,你可以用eval
捕获:
my $pattern = eval { qr/$input/ };
如果您返回undef
,则该模式无效。 而且,尽管问题中有评论,但制作无效模式的方法有无数种。 我知道是因为我一直手动输入它们,而且我还没有办法搞砸:)
这不会将模式应用于字符串,但您可以使用$pattern
进行匹配:
if( $pattern ) {
$target =~ $pattern; # or $target =~ m/$pattern/
}
好吧,验证正则表达式需要了解您期望的输入类型。 正则表达式运算符与自动机接受的字符串集之间存在直接关系。
这里的问题是通常这组字符串并不为人所知或指定不当,例如:
regex 中的基本运算符集是基本语言字符集(提供要操作的符号)和使事情变得复杂的运算符:这是替代|
(选择一个或另一个),连接(这里没有符号,因为两个正则表达式只是放在一起表示来自一组的一组字符串,然后是一个字符串,这次来自第二组)和闭包,由*
(这最后的含义允许任何重复——包括没有——来自前一组的字符串)。
绝对所有的正则表达式都可以作为(主要是更复杂的)表达式来处理,它只使用这三个运算符,仅此而已。 例如,可以通过重复应用它的正则表达式来处理+
运算符,并将*
添加到第二个实例(用括号包围以将其全部分组) ?
可选后缀可以通过以下规则(regexp)? == (regexp|)
(regexp)? == (regexp|)
(使用与否的选择)
|
意味着另一种选择……您提供两组字符串,结果集是两组的并集。 这意味着如果一个字符串属于一个或任何一个集合,它就会被接受。这组规则将为您提供构成正则表达式的完整字符串集。 这可能符合(或不符合)您的想法……但是如果您的想法定义不明确,那么它将成为您的正则表达式。
因此,作为一个结论,您需要一个通用程序来测试您自己的想法以及您如何设计您的正则表达式。 有一个定理(称为抽水定理)用于演示正则表达式和有限状态自动机的等价性。 这是一项非常重要的成就,因为它允许您使用正则表达式进行高效的单次传递、字符串识别。 如果您深入研究,您会发现可以编写一个工具,从正则表达式可以系统地构建将被某些正则表达式接受的完整字符串集。 但这有一个问题,其中许多正则表达式创建了无限组的字符串,这意味着算法不会在有限的时间内完成。
作为最后的评论,我可以告诉您,这使正则表达式成为选择字符串的非常强大的工具。 例如,您可以使用正则表达式来检测复杂的事情,例如作为一串数字组成 23 的倍数的十进制形式,或者验证信用卡号码是否存在转录错误。
如果您需要对提供给您的内容完全怀疑,您可以使用Safe模块来限制可用于eval()
上下文的操作码。
您可以从permit_only()
添加或减去以满足您的需要。
sub safestringeval ($) {
require Safe;
my $safe = Safe->new;
$safe->permit_only(qw/:base_core anonhash anonlist gvsv gv gelem padsv padav padhv padany/);
return $safe->reval($_[0], 1);
}
$regex = safestringeval('qr{'.$input.'}');
我实际上不记得这个用例,所以我查了一下。 :) 这是为了允许输入的字符串包含实时转义序列。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.