有什么方法可以在perl RE中处理.*as.{0,1024}?

Fli*_*mzy 6 regex optimization perl

我们允许一些用户提供的RE用于过滤电子邮件.早期我们遇到了RE的一些性能问题,例如.*,在与任意大型电子邮件进行匹配时.我们发现一个简单的解决方案是s/\*/{0,1024}/用户提供的RE.但是,这不是一个完美的解决方案,因为它会破坏以下模式:

/[*]/
Run Code Online (Sandbox Code Playgroud)

而不是想出一些复杂的方法来解释用户提供的RE输入的每个可能的变化,我想限制perl对*+字符的解释,最大长度为1024个字符.

有没有办法做到这一点?

zou*_*oul 5

这并不能真正回答您的问题,但您应该了解用户提供的正则表达式的其他问题,例如参见OWASP的摘要.根据您的具体情况,编写或查找自定义简单模式匹配库可能更好?

  • +1,因为`^(a | aa){0,30} $`足以让正则表达式引擎忙于数百万次循环,其字符串如"aaaaaaaaaaaaaaaaaaaaaaaaaaaaa" (2认同)

ste*_*ema 4

更新

在量词之前添加 a (?<!\\),因为转义的 *+ 不应匹配。如果有\\*(匹配\0次或多次),替换仍然会失败。

改进将是这样的

s/(?<!\\)\*(?!(?<!\\)[^[]*?(?<!\\)\])/{0,1024}/
s/(?<!\\)\+(?!(?<!\\)[^[]*?(?<!\\)\])/{1,1024}/
Run Code Online (Sandbox Code Playgroud)

在 Regexr 上查看这里

这意味着比赛[*+],但前提是没有提前结束且在此之前]都没有。并且方括号之前不允许[\ (?<!\\)部分) 。

(?! ... )是负前瞻

(?<! ... )是消极的回顾

详情请参阅perlretut

更新 2 包括所有格量词

s/(?<!(?<!\\)[\\+*?])\+(?!(?<!\\)[^[]*?(?<!\\)\])/{1,1024}/   # for +
s/(?<!\\)\*(?!(?<!\\)[^[]*?(?<!\\)\])/{0,1024}/    # for *
Run Code Online (Sandbox Code Playgroud)

在 Regexr 上查看这里

似乎有效,但现在变得非常复杂!