Tue, 10 Jun 2014 10:22:26 +0100
8043725: javac fails with StackOverflowException
Summary: loose type comparison test should be protected against infinite recursion with fbounds
Reviewed-by: vromero
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java Thu May 29 10:48:00 2014 +0200 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Tue Jun 10 10:22:26 2014 +0100 1.3 @@ -1221,14 +1221,35 @@ 1.4 TypeRelation isSameTypeLoose = new LooseSameTypeVisitor(); 1.5 1.6 private class LooseSameTypeVisitor extends SameTypeVisitor { 1.7 + 1.8 + /** cache of the type-variable pairs being (recursively) tested. */ 1.9 + private Set<TypePair> cache = new HashSet<>(); 1.10 + 1.11 @Override 1.12 boolean sameTypeVars(TypeVar tv1, TypeVar tv2) { 1.13 - return tv1.tsym == tv2.tsym && visit(tv1.getUpperBound(), tv2.getUpperBound()); 1.14 + return tv1.tsym == tv2.tsym && checkSameBounds(tv1, tv2); 1.15 } 1.16 @Override 1.17 protected boolean containsTypes(List<Type> ts1, List<Type> ts2) { 1.18 return containsTypeEquivalent(ts1, ts2); 1.19 } 1.20 + 1.21 + /** 1.22 + * Since type-variable bounds can be recursive, we need to protect against 1.23 + * infinite loops - where the same bounds are checked over and over recursively. 1.24 + */ 1.25 + private boolean checkSameBounds(TypeVar tv1, TypeVar tv2) { 1.26 + TypePair p = new TypePair(tv1, tv2, true); 1.27 + if (cache.add(p)) { 1.28 + try { 1.29 + return visit(tv1.getUpperBound(), tv2.getUpperBound()); 1.30 + } finally { 1.31 + cache.remove(p); 1.32 + } 1.33 + } else { 1.34 + return false; 1.35 + } 1.36 + } 1.37 }; 1.38 1.39 /** 1.40 @@ -3376,9 +3397,16 @@ 1.41 class TypePair { 1.42 final Type t1; 1.43 final Type t2; 1.44 + boolean strict; 1.45 + 1.46 TypePair(Type t1, Type t2) { 1.47 + this(t1, t2, false); 1.48 + } 1.49 + 1.50 + TypePair(Type t1, Type t2, boolean strict) { 1.51 this.t1 = t1; 1.52 this.t2 = t2; 1.53 + this.strict = strict; 1.54 } 1.55 @Override 1.56 public int hashCode() { 1.57 @@ -3389,8 +3417,8 @@ 1.58 if (!(obj instanceof TypePair)) 1.59 return false; 1.60 TypePair typePair = (TypePair)obj; 1.61 - return isSameType(t1, typePair.t1) 1.62 - && isSameType(t2, typePair.t2); 1.63 + return isSameType(t1, typePair.t1, strict) 1.64 + && isSameType(t2, typePair.t2, strict); 1.65 } 1.66 } 1.67 Set<TypePair> mergeCache = new HashSet<TypePair>();
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/tools/javac/generics/inference/8043725/T8043725.java Tue Jun 10 10:22:26 2014 +0100 2.3 @@ -0,0 +1,36 @@ 2.4 +/* 2.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +/** 2.28 + * @test 2.29 + * @bug 8043725 2.30 + * @summary javac fails with StackOverflowException 2.31 + * @compile T8043725.java 2.32 + */ 2.33 +class T8043725 { 2.34 + <T extends Comparable<T>> T m(T v) { 2.35 + //this will generate two upper bounds, T and Comparable<T'> respectively 2.36 + //causing infinite recursion in lub (because of JLS 18.3.1). 2.37 + return m(v); 2.38 + } 2.39 +}