Java重做易受攻击吗?

Java重做易受攻击吗?,java,regex,security,java-11,Java,Regex,Security,Java 11,我尝试使用(a+)+//code>regexp和aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(大量a)使用jshell输入: Pattern.compile("(a+)+") .matcher("aaaaaaaaaaaaaaaaaaaaaa

我尝试使用
(a+)+//code>regexp和
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(大量
a
)使用jshell输入:

Pattern.compile("(a+)+")
    .matcher("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!")
    .matches()
但每次我尝试时,这都会很快完成。Java中的regexp实现与其他实现不同吗?或者链接的维基百科页面是错误的

(顺便说一句,如果相关的话,我正在使用Java11)

编辑:看起来它与Java版本相关,当我在Java8上尝试它时,它挂起了,但在Java9和Java11中它马上就可以工作了。这些版本之间有哪些变化会影响这一点?现在所有的正则表达式在Java中都是安全的吗


是否有一个特定的JavaJEP更改了regexp实现?我想知道对于较新的Java来说,什么样的regexp仍然是一个问题。

我目前正在运行Java 8,以下代码挂起:

Pattern.compile("(a|aa)+")
       .matcher("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab")
       .matches()
看看您是如何使用Java11的(并且也用Java9/10测试了它),并且看到它需要花费少量的时间来完成,这些版本之间显然发生了变化

通过查看Java 11中
Matcher
的源代码,我们发现Java 8中没有以下添加内容:

/**
 * Storage used by top greedy Loop node to store a specific hash set to
 * keep the beginning index of the failed repetition match. The nodes
 * themselves are stateless, so they rely on this field to hold state
 * during a match.
 */
IntHashSet[] localsPos;
这种本地存储以及添加的大量其他代码似乎是Java 9+中正则表达式的状态机完成速度比Java 8及以下版本快得多的主要原因之一。

根据文章,重做问题已在Java 9及更高版本中得到处理:

像OpenJDK 9+这样的Java运行时通过在正则表达式求值的实现中提供额外的保护来缓解这个问题。在这些运行时中,上述示例不易受攻击


如果您还没有看到它:@PM77-1我尝试了该页面的代码,它运行速度也很快,并按上面所述打印结果。您的模式适用于大多数正则表达式引擎。这种模式的唯一问题是它后面跟着其他一些模式。@WiktorStribiżew不太可能。Java的引擎可能会变得更好一些,但只要将其更改为
((a+)+)
,它就会再次挂起。而且可以证明,每增加一个嵌套,即
(((a+)+)
((((a+)+)
)都会增加复杂性,因此Java引擎还没有学会处理这种模式,它只是在嵌套迭代中变得更好了一点。@Holger Try
(a)(\1*)+x
。我怀疑许多引擎是否具有防止反向引用重复模式的保护。尽管这不是一种常见的模式。同样,它在不到一秒钟的时间内完成(并返回
false
)@KrzysztofKrasoń如果不使用JShell运行它会发生什么?它在Java 11上表现出相同的快速执行,但在Java 8上它挂起,如上文所述。IMO,这目前还不能回答问题。它也不会向同一条添加任何附加信息:|@似乎是这样的,因为OP在我回答说问题是特定于版本的之后编辑了这个问题。