Regex 引擎如何为正则表达式生成 NFA?

How do Regex engines generate NFAs for regular expressions?

在此维基页面中:https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS#The_problematic_Regex_na.C3.AFve_algorithm

你可以看到正则表达式 ^(a+)+$

创建了以下 NFA:

我的问题是:从正则表达式创建这个 NFA 的过程是什么?

他们没有。

大多数正则表达式引擎不创建 NFA,而是通过 回溯
回溯是一个 re-visiting 你做出的每一个决定的过程,撤销它,并尝试另一个选择直到某些东西起作用,这很快就会变得低效。引擎通常不够智能,无法消除相似的路径,并且某些模式的性能可能呈指数级增长。

可以在 Runaway Regular Expressions: Catastrophic Backtracking 中找到很好的解释。
在输入 aaaaaaaaaaaaX^(a+)+$ 示例中,引擎将尝试所有组合:

  • aaaaaaaaaaaa
  • aaaaaaaaaaa a
  • aaaaaaaaaa aa
  • aaaaaaaaaa a a
  • ...
  • aa aaaaaaaaaa
  • a aaaaaaaaaaa
  • ...
  • a a aaaa aaaa aa

...很多。

您链接到的 OWASP 文章演示了真正的 denial-of-service 攻击,但解释纯粹是理论上的 - 这并不是攻击的实际运作方式。

可以更好地实现匹配正则表达式:关于该主题的规范文章是 Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, ...),其中还包含您问题的答案,并解释了如何构建适当的 NFA 并有效地匹配模式。

采用这种方法的一个引擎是 RE2, the regular expression library of . RE2 does build a NFA, and its performance is much better in general, but there are trade-offs:
例如,RE2 can quickly discover there is no match on ^(((a+)+)+)+$, while other flavors time out.

另请参阅: