【问题标题】:Python's Regular Expression Source String LengthPython 的正则表达式源字符串长度
【发布时间】:2010-01-04 08:42:57
【问题描述】:

在 Python 正则表达式中,

re.compile("x"*50000)

给我OverflowError: regular expression code size limit exceeded

但是下面的一个没有得到任何错误,但它达到了 100% CPU,并且在我的 PC 上花了 1 分钟

>>> re.compile(".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000)
<_sre.SRE_Pattern object at 0x03FB0020>

这正常吗?

我应该假设".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000 比"x"*50000 短吗?

在 Python 2.6、Win32 上测试

更新 1:

看起来".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000 可以简化为.*?

那么,这个怎么样?

re.compile(".*?x"*50000)

它确实可以编译,如果那个也可以减少到".*?x",它应该只匹配字符串"abcx"或"x",但它不匹配。

那么,我错过了什么吗?

更新 2:

我的意思是不知道正则表达式源字符串的最大限制,我想知道溢出处理程序捕获的"x"*50000 的一些原因/概念,但不是".*?x"*50000。

这对我来说没有意义,这就是原因。

溢出检查时缺少一些东西,或者它很好,或者它真的溢出了一些东西?

任何提示/意见将不胜感激。

【问题讨论】:

  • No ".*?x"5000 不会缩减为 ".?x" - 它会缩减为包含 5000 个 x 的正则表达式,其中包含 ".*? "在每个 x 之前。这就是它不匹配“abcx”或“x”的原因——它只会匹配一个有 5000 个 x 的字符串。
  • 它提醒我,当我尝试将 SVG 路径的 ABNF 转换为正则表达式时,我达到了 PHP 正则表达式的最大长度。所以,恕我直言,很高兴知道答案。
  • @Dave Kirby,谢谢,但它是 50000 (50k)。我最初的问题是 re.compile("x"*50000) 没有被编译,但是 re.compile(".*?x"*50000) 被编译了。
  • 为什么需要知道最大正则表达式?编写您需要的正则表达式。 x{5000} 或 x{500000} 或其他。当你达到极限时,你就在那里。知道极限在哪里有什么意义?即使您编写了一个太长的真实正则表达式,您也不需要知道(不太可能)。不是这些首先不是明智的正则表达式的退化案例。
  • @S.Lott,你是对的,知道限制根本没有意义,但是,当"x"*50000 被溢出处理程序捕获时,你不认为它可能容易受到缓冲区溢出的影响,但".*?x"*50000 没有,甚至".*?x"*100000 也没有。

标签: python regex


【解决方案1】:

不同之处在于".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000可以简化为".*?",而"x"*50000必须在FSM(或正则表达式引擎使用的类似结构)中生成50000个节点。

编辑:好吧,我错了。它不是那么聪明。 "x"*50000 失败而".*?x"*50000 没有失败的原因是一个“代码项”的大小有限制。 "x"*50000 将生成一个长项,".*?x"*50000 将生成许多小项。如果你可以在不改变正则表达式含义的情况下以某种方式拆分字符串文字,它会起作用,但我想不出办法。

【讨论】:

  • 谢谢,re.compile(".*?x"*50000) 怎么样?
  • 我不太了解 Python 正则表达式引擎的内部结构,所以我不确定。正则表达式应匹配 50000 个 x 与它们之间的任何字符。我不知道它做了什么优化,但它很可能对正则表达式做了一些特别的事情。仅供参考,所有的正则表达式都可以在 Linux 上运行。
  • 感谢有关 linux 版本的信息,我刚刚检查了 _sre.c -> _compile 函数,没有针对 windows 的特定代码,所以可能是因为大小不同,例如 wchar_t 和/或你的 python 是用 Unicode=UCS4 编译的
  • "x"*50000 will generate one long item and ".*?x"*50000 will generate many small items,谢谢,有道理。
【解决方案2】:

你想匹配 50000 "x"s ,对吗???如果是这样,没有正则表达式的替代方法

if "x"*50000 in mystring:
    print "found"

如果你想用正则匹配50000个“x”,你可以使用range

>>> pat=re.compile("x{50000}")
>>> pat.search(s)
<_sre.SRE_Match object at 0xb8057a30>

在我的系统上,最大长度为 65535

>>> pat=re.compile("x{65536}")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/re.py", line 188, in compile
    return _compile(pattern, flags)
  File "/usr/lib/python2.6/re.py", line 241, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/usr/lib/python2.6/sre_compile.py", line 529, in compile
    groupindex, indexgroup
RuntimeError: invalid SRE code
>>> pat=re.compile("x{65535}")
>>>

我不知道 Python 中是否有一些调整可以用来增加这个限制。

【讨论】:

  • 感谢更新代码,但{65535} 是重复限制,这与我的有点不同。 "x"*50000和"x{50000}在我的理解上是不一样的。
  • "x"*50000 产生 50000 个 x ......某物 ?你应该用例子清楚地说明你想在你的问题中做什么......
  • @ghostdog74,你是对的,如果我想匹配 50000 个 x,我可以使用 x{50000}。我只是想知道 re.compile 是否安全并测试漏洞。就是这样。
  • 好吧,如您所见,字符串长度超过 65535(对于我的系统)会使正则表达式引擎崩溃并产生错误。我建议在将字符串传递给 re.compile 之前根据您的应用程序规范检查您的字符串。
猜你喜欢
  • 2014-10-22
  • 2017-07-30
  • 2014-05-12
  • 1970-01-01
  • 2011-09-26
  • 2013-06-04
  • 1970-01-01
  • 2014-04-23
  • 2016-03-03
相关资源
最近更新 更多