Skip to content

Commit 4c6af03

Browse files
author
Vicente Romero
committed
8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy
Reviewed-by: mcimadamore
1 parent 2f455ed commit 4c6af03

File tree

2 files changed

+102
-6
lines changed

2 files changed

+102
-6
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,7 +1346,7 @@ public boolean isSameType(Type t, Type s) {
13461346
* Type-equality relation - type variables are considered
13471347
* equals if they share the same object identity.
13481348
*/
1349-
TypeRelation isSameTypeVisitor = new TypeRelation() {
1349+
abstract class TypeEqualityVisitor extends TypeRelation {
13501350

13511351
public Boolean visitType(Type t, Type s) {
13521352
if (t.equalsIgnoreMetadata(s))
@@ -1385,10 +1385,12 @@ public Boolean visitWildcardType(WildcardType t, Type s) {
13851385
} else {
13861386
WildcardType t2 = (WildcardType)s;
13871387
return (t.kind == t2.kind || (t.isExtendsBound() && s.isExtendsBound())) &&
1388-
isSameType(t.type, t2.type);
1388+
sameTypeComparator(t.type, t2.type);
13891389
}
13901390
}
13911391

1392+
abstract boolean sameTypeComparator(Type t, Type s);
1393+
13921394
@Override
13931395
public Boolean visitClassType(ClassType t, Type s) {
13941396
if (t == s)
@@ -1419,9 +1421,11 @@ public Boolean visitClassType(ClassType t, Type s) {
14191421
}
14201422
return t.tsym == s.tsym
14211423
&& visit(t.getEnclosingType(), s.getEnclosingType())
1422-
&& containsTypeEquivalent(t.getTypeArguments(), s.getTypeArguments());
1424+
&& sameTypeArguments(t.getTypeArguments(), s.getTypeArguments());
14231425
}
14241426

1427+
abstract boolean sameTypeArguments(List<Type> ts, List<Type> ss);
1428+
14251429
@Override
14261430
public Boolean visitArrayType(ArrayType t, Type s) {
14271431
if (t == s)
@@ -1477,6 +1481,16 @@ public Boolean visitUndetVar(UndetVar t, Type s) {
14771481
public Boolean visitErrorType(ErrorType t, Type s) {
14781482
return true;
14791483
}
1484+
}
1485+
1486+
TypeEqualityVisitor isSameTypeVisitor = new TypeEqualityVisitor() {
1487+
boolean sameTypeComparator(Type t, Type s) {
1488+
return isSameType(t, s);
1489+
}
1490+
1491+
boolean sameTypeArguments(List<Type> ts, List<Type> ss) {
1492+
return containsTypeEquivalent(ts, ss);
1493+
}
14801494
};
14811495

14821496
// </editor-fold>
@@ -3862,7 +3876,7 @@ public List<Type> intersect(List<Type> cl1, List<Type> cl2) {
38623876
// where
38633877
class TypePair {
38643878
final Type t1;
3865-
final Type t2;;
3879+
final Type t2;
38663880

38673881
TypePair(Type t1, Type t2) {
38683882
this.t1 = t1;
@@ -3875,10 +3889,28 @@ public int hashCode() {
38753889
@Override
38763890
public boolean equals(Object obj) {
38773891
return (obj instanceof TypePair typePair)
3878-
&& isSameType(t1, typePair.t1)
3879-
&& isSameType(t2, typePair.t2);
3892+
&& exactTypeVisitor.visit(t1, typePair.t1)
3893+
&& exactTypeVisitor.visit(t2, typePair.t2);
38803894
}
38813895
}
3896+
3897+
TypeEqualityVisitor exactTypeVisitor = new TypeEqualityVisitor() {
3898+
@Override
3899+
boolean sameTypeArguments(List<Type> ts, List<Type> ss) {
3900+
while (ts.nonEmpty() && ss.nonEmpty()
3901+
&& sameTypeComparator(ts.head, ss.head)) {
3902+
ts = ts.tail;
3903+
ss = ss.tail;
3904+
}
3905+
return ts.isEmpty() && ss.isEmpty();
3906+
}
3907+
3908+
@Override
3909+
boolean sameTypeComparator(Type t, Type s) {
3910+
return exactTypeVisitor.visit(t, s);
3911+
}
3912+
};
3913+
38823914
Set<TypePair> mergeCache = new HashSet<>();
38833915
private Type merge(Type c1, Type c2) {
38843916
ClassType class1 = (ClassType) c1;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8337142
27+
* @summary StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy
28+
* @compile SOEForDeeplyNestedTypeTest.java
29+
*/
30+
31+
import java.util.List;
32+
33+
public class SOEForDeeplyNestedTypeTest {
34+
class T {
35+
List<M<?, ?>> xs = List.of(new M<>(One.class), new M<>(Two.class), new M<>(Two.class));
36+
}
37+
38+
class M<R extends Eight, I extends Nine<? extends R>> {
39+
M(Class<? extends I> c) {}
40+
}
41+
42+
class One implements Three<Five>, Six<One> {}
43+
class Two implements Four<Seven>, Six<Two> {}
44+
interface Three<R extends Eight> extends Nine<R> {}
45+
interface Four<R extends Eight> extends Nine<R> {}
46+
class Five extends Ten<Five> implements Eleven<Twelve>, Thirteen {}
47+
interface Six<FullKeyT extends TwentyTwo> extends TwentyTwo {}
48+
class Seven extends Ten<Seven> implements Eleven<Fourteen>, Thirteen {}
49+
interface Eight {}
50+
interface Nine<R extends Eight> extends TwentyTwo {}
51+
class Ten<K extends TwentyTwo> implements TwentyTwo {}
52+
interface Eleven<PkT extends Twenty> extends Twenty {}
53+
class Twelve extends Ten<Twelve> implements Eleven<Sixteen>, Thirteen {}
54+
interface Thirteen extends Seventeen {}
55+
class Fourteen extends Ten<Fourteen> implements Eleven<Fifteen>, Thirteen {}
56+
class Fifteen extends Ten<Fifteen> implements Eleven<Twelve>, Thirteen {}
57+
class Sixteen extends Nineteen<Sixteen> implements Eighteen, Thirteen {}
58+
interface Seventeen extends Twenty {}
59+
interface Eighteen extends Twenty {}
60+
class Nineteen<K extends Twenty> extends Ten<K> implements Twenty {}
61+
interface Twenty extends TwentyTwo {}
62+
class TwentyOne<R extends Eight> {}
63+
interface TwentyTwo extends Eight {}
64+
}

0 commit comments

Comments
 (0)