你可以看到正则表达式^(a+)+$
创建了以下NFA:
我的问题是:从正则表达式创建此NFA的过程是什么?
答案 0 :(得分:3)
他们没有。
大多数正则表达式引擎都不会创建NFA,而是通过回溯来工作。
回溯是一个重新访问你所做的每一个决定,撤消它,并尝试另一个选项直到某些东西工作的过程,这很快就会变得低效。发动机通常不够智能以消除类似的路径,某些模式的性能可能成为指数。
可以在Runaway Regular Expressions: Catastrophic Backtracking中找到一个很好的解释
在^(a+)+$
输入aaaaaaaaaaaaX
的示例中,引擎会尝试所有组合:
aaaaaaaaaaaa
aaaaaaaaaaa
a
aaaaaaaaaa
aa
aaaaaaaaaa
a
a
aa
aaaaaaaaaa
a
aaaaaaaaaaa
a
a
aaaa
aaaa
aa
......这很多。
您所关联的OWASP文章正在展示真正的拒绝服务攻击,但解释纯粹是理论上的 - 这不是攻击的实际工作方式。
匹配正则表达式可以更好地实现:关于该主题的规范性文章是Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, ...),其中还包含您的问题的答案,解释了如何有效地构建正确的NFA和匹配模式。
采用这种方法的一个引擎是RE2,golang的正则表达式库。 RE2确实构建了NFA,其性能总体上要好得多,但需要权衡:RE2 does not have common features like lookarounds and back-references。
例如,RE2 can quickly discover there is no match on ^(((a+)+)+)+$
,而other flavors time out。
另见:
\s+$
(真的)而无法响应。