Bug 430282 - Limit recursion depth when processing inheritance

hierarchies

Change-Id: Ia9d9f379cb61e8d8bc8d1fb33f893fcd2a0688a2
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
Reviewed-on: https://git.eclipse.org/r/23957
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
Nathan Ridge 2014-03-27 01:31:44 -04:00 committed by Sergey Prigogin
parent b4d65483ed
commit cff738fe0b
3 changed files with 32 additions and 8 deletions

View file

@ -365,4 +365,13 @@ public class AbstractClassInstantiationCheckerTest extends CheckerTestCase {
// Just check that codan runs without any exceptions being thrown.
loadCodeAndRun(getAboveComment());
}
// template <int I>
// struct S : S<I - 1> {};
//
// S<1> waldo;
public void testMaxInstantiationDepth_430282() throws Exception {
// Just check that codan runs without any exceptions being thrown.
loadCodeAndRun(getAboveComment());
}
}

View file

@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.parser.util.CollectionUtils;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
@ -197,7 +198,8 @@ public class SemanticQueries {
private Map<ICPPClassType, FinalOverriderMap> virtualBaseCache = new HashMap<ICPPClassType, FinalOverriderMap>();
public ICPPMethod[] collect(ICPPClassType root, IASTNode point) {
FinalOverriderMap finalOverriderMap = collectFinalOverriders(root, false, new HashSet<ICPPClassType>(), point);
FinalOverriderMap finalOverriderMap = collectFinalOverriders(root, false, new HashSet<ICPPClassType>(),
CPPSemantics.MAX_INHERITANCE_DEPTH, point);
return finalOverriderMap.collectPureVirtualMethods();
}
@ -212,7 +214,7 @@ public class SemanticQueries {
* @return the computed final overrider map
*/
private FinalOverriderMap collectFinalOverriders(ICPPClassType classType, boolean isVirtualBase,
Set<ICPPClassType> inheritanceChain, IASTNode point) {
Set<ICPPClassType> inheritanceChain, int maxdepth, IASTNode point) {
FinalOverriderMap result = new FinalOverriderMap();
inheritanceChain.add(classType);
@ -236,6 +238,12 @@ public class SemanticQueries {
if (inheritanceChain.contains(baseType))
continue;
// Guard against infinite recursion in inheritance
// for example A<I> deriving from A<I - 1> without
// a base case to end the recursion.
if (maxdepth <= 0)
continue;
// Collect final overrider information from the base class.
// If it's a virtual base class and we've already processed it
// in this class hierarchy, don't process it again.
@ -243,11 +251,11 @@ public class SemanticQueries {
if (base.isVirtual()) {
baseOverriderMap = virtualBaseCache.get(baseType);
if (baseOverriderMap == null) {
baseOverriderMap = collectFinalOverriders(baseType, true, inheritanceChain, point);
baseOverriderMap = collectFinalOverriders(baseType, true, inheritanceChain, maxdepth - 1, point);
virtualBaseCache.put(baseType, baseOverriderMap);
}
} else {
baseOverriderMap = collectFinalOverriders(baseType, false, inheritanceChain, point);
baseOverriderMap = collectFinalOverriders(baseType, false, inheritanceChain, maxdepth - 1, point);
}
// Merge final overrider information from base class into this class.

View file

@ -593,7 +593,8 @@ public class ClassTypeHelper {
for (ICPPBase base : bases) {
IBinding b= base.getBaseClass();
if (b instanceof ICPPClassType) {
findOverridden((ICPPClassType) b, point, mname, methodType, virtualInClass, result);
findOverridden((ICPPClassType) b, point, mname, methodType, virtualInClass,
result, CPPSemantics.MAX_INHERITANCE_DEPTH);
}
}
@ -611,7 +612,12 @@ public class ClassTypeHelper {
*/
private static boolean findOverridden(ICPPClassType classType, IASTNode point, char[] methodName,
ICPPFunctionType methodType, Map<ICPPClassType, Boolean> virtualInClass,
List<ICPPMethod> result) {
List<ICPPMethod> result, int maxdepth) {
// Prevent recursion due to a hierarchy of unbounded depth,
// e.g. A<I> deriving from A<I - 1>.
if (maxdepth <= 0)
return false;
Boolean visitedBefore= virtualInClass.get(classType);
if (visitedBefore != null)
return visitedBefore;
@ -629,13 +635,14 @@ public class ClassTypeHelper {
}
}
// Prevent recursion.
// Prevent recursion due to a class inheriting (directly or indirectly) from itself.
virtualInClass.put(classType, hasOverridden);
ICPPBase[] bases= getBases(classType, point);
for (ICPPBase base : bases) {
IBinding b= base.getBaseClass();
if (b instanceof ICPPClassType) {
if (findOverridden((ICPPClassType) b, point, methodName, methodType, virtualInClass, result)) {
if (findOverridden((ICPPClassType) b, point, methodName, methodType, virtualInClass,
result, maxdepth - 1)) {
hasOverridden= true;
}
}