/ abcd ^ $ / i匹配Perl中的任何内容吗?

时间:2009-07-19 13:54:09

标签: regex perl

Perl是我从来没有充分理由进入的事情之一。不幸的是,我有一个非常具体的(看起来像我的错误)一点Perl代码,我需要定义它的操作可证明

此代码已经编写并已投入生产,我希望将其删除。

我认为成功匹配是不可能的,但这是对主题(特别是我的)的猜测不够好的事情之一。它正在守护一个代码块{},不幸的是它具有多个条件,所以无论这个表达式的状态如何都可以输入,但是如果确实发生了这个问题就会出现安全问题(如果状态未定义则会出现错误)恕我直言,但没有证据表明影响/严重程度较低(阅读永远不会得到修复)。

是否可以 /abcd^$/i 永远,是否成功匹配?包括空字节插入或任何可能的字节/二进制数据?我甚至会进行一些疯狂的环境攻击(例如,在1个字节内消耗主机上的所有内存,导致Perl表达式评估程序在运行时未经检查的2字节分配失败)。感谢创造力。

5 个答案:

答案 0 :(得分:6)

来自perlre联机帮助页:

  

但是,您可能希望将字符串视为一个字符串   多行缓冲区,以便“^”在任何换行符后匹配   在字符串中(除非换行符是\ n中的最后一个字符)   字符串),“$”将在任何换行符之前匹配。以牺牲为代价   更多的开销,你可以通过使用/ m修饰符来实现   模式匹配运算符。 (较旧的程序是通过设置$ * 来实现的,但是   这种做法已在perl 5.9中删除。)

因此,请确保$ *或其他预定义变量不会干扰。

即使是一个$ *修改过的表达式,比如/ abcd ^ $ / im(注意添加的“m”标志)也不匹配任何东西,因为“^”字符只在换行符后匹配。


另外,请确保正则表达式没有过载。如果导入的包执行类似的操作:

use overload;                                                                   
sub import {                                                                    
    overload::constant(qr => sub { $_ = shift; s/^abcd//; $_ });                 
} 

然后空字符串将匹配您的正则表达式。


另外,不知道这是正则表达式在你的代码中出现的方式,它可能不相关,但为了安全起见,你不应该隐式匹配$ _而是明确指定变量: “$ str =〜/ abcd ^ $ / i;”。

$ _是动态范围的,所以如果你有任何函数调用可以在你定义它的地方和正则表达式之间修改$ _,或者如果你以后添加它们,你会感到惊讶:)< / p>

答案 1 :(得分:4)

正则表达式的意图是什么?也许它没有正确地完成工作,我们可以为您解决这个问题。它试图匹配哪种数据?有可能原始编码器试图匹配文字^?哪种情况可以防范?

在这种情况下,我发现最好弄清楚代码中应该发生什么,而不是实际发生的情况。意图可能是正确的,但实施错误。错误确实发生了。 :)

您可以考虑在它守卫的代码中添加一个日志语句,以查看它是否曾被触发过。由于涉及所有特殊变量和重载,您可能无法仅查看正则表达式并找出它将执行的操作。如果你看到它被触发,你知道你仍然需要它。如果它从未被触发过,那么,你仍然不知道。

答案 2 :(得分:4)

顺便说一句,我想我会在这里指出use re 'debug'。您可以使用它来查看Perl如何编译和匹配您的正则表达式:

$ perl -Mre=debugcolor -e '/abcd^$/'
Compiling REx "abcd^$"
Final program:
   1: EXACT <abcd> (3)
   3: BOL (4)
   4: EOL (5)
   5: END (0)
anchored "abcd"$ at 0 (checking anchored) minlen 4
Freeing REx: "abcd^$"

用m:

$ perl -Mre=debugcolor -e '/abcd^$/m'
Compiling REx "abcd^$"
Final program:
   1: EXACT <abcd> (3)
   3: MBOL (4)
   4: MEOL (5)
   5: END (0)
anchored "abcd"$ at 0 (checking anchored) minlen 4
Freeing REx: "abcd^$"

您还可以尝试一些示例数据,并确保没有任何内容匹配:

$ perl -Mre=debugcolor -e '"not going to match" =~ /abcd^$/m'
Compiling REx "abcd^$"
Final program:
   1: EXACT <abcd> (3)
   3: MBOL (4)
   4: MEOL (5)
   5: END (0)
anchored "abcd"$ at 0 (checking anchored) minlen 4
Guessing start of match in sv for REx "abcd^$" against "not going to match"
Did not find anchored substr "abcd"$...
Match rejected by optimizer
Freeing REx: "abcd^$"

此处匹配失败两次:

$ perl -Mre=debug -e '"abcd\nabcd\n\n" =~ /abcd^$/m'
...
anchored "abcd"$ at 0 (checking anchored) minlen 4
Guessing start of match in sv for REx "abcd^$" against "abcd%nabcd%n%n"
Found anchored substr "abcd"$ at offset 0...
Guessed: match at offset 0
Matching REx "abcd^$" against "abcd%nabcd%n%n"
   0 <> <abcd%nabcd>         |  1:EXACT <abcd>(3)
   4 <abcd> <%nabcd%n%n>     |  3:MBOL(4)
                                  failed...
   5 <abcd%n> <abcd%n%n>     |  1:EXACT <abcd>(3)
   9 <abcd%nabcd> <%n%n>     |  3:MBOL(4)
                                  failed...
Match failed
Freeing REx: "abcd^$"

尝试自己运行,因为它的颜色更清晰 使用debugcolor。

man page

答案 3 :(得分:1)

/abcd^$/i/abcd^$/im相同,如果$*设置为true(在5.9之前的Perl中)。

我会重写它/abcd$^$/im

基本上它的作用是在一行的末尾寻找“abcd”,然后是一个空行。

除了在“^”之前需要捕获换行符的内容。

答案 4 :(得分:1)

perlre documentation

  

嵌入式换行符不会与^$匹配。

文字/abcd^$/永远无法匹配,因为^仅在字符串的开头匹配,在多线模式下的之后匹配,所以最后^$该模式需要帮助越过嵌入式换行符。

使用较旧的perl,类似的模式可以匹配:

$ cat prog
#! /usr/local/bin/perl -w

$* = 1;
$_ = "AbC\n\n";
print /abc\n^$/i  ? "Match.\n" : "No match.\n";
print /abc\s*^$/i ? "Match.\n" : "No match.\n";

$ ./prog
Use of $* is deprecated at ./prog line 3.
Match.
Match.

请注意古代perl-5.6.1中的弃用警告,以及5.10.0 release removed support for $*.这是可能的,但在病理方面。