From cff738fe0b184a0c26c937f08f3a04e9d8d56a5e Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Thu, 27 Mar 2014 01:31:44 -0400 Subject: [PATCH] Bug 430282 - Limit recursion depth when processing inheritance hierarchies Change-Id: Ia9d9f379cb61e8d8bc8d1fb33f893fcd2a0688a2 Signed-off-by: Nathan Ridge Reviewed-on: https://git.eclipse.org/r/23957 Reviewed-by: Sergey Prigogin IP-Clean: Sergey Prigogin Tested-by: Sergey Prigogin --- .../AbstractClassInstantiationCheckerTest.java | 9 +++++++++ .../cdt/core/dom/ast/cpp/SemanticQueries.java | 16 ++++++++++++---- .../core/dom/parser/cpp/ClassTypeHelper.java | 15 +++++++++++---- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/AbstractClassInstantiationCheckerTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/AbstractClassInstantiationCheckerTest.java index 8833857aecc..9e03659a85f 100644 --- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/AbstractClassInstantiationCheckerTest.java +++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/AbstractClassInstantiationCheckerTest.java @@ -365,4 +365,13 @@ public class AbstractClassInstantiationCheckerTest extends CheckerTestCase { // Just check that codan runs without any exceptions being thrown. loadCodeAndRun(getAboveComment()); } + + // template + // struct S : S {}; + // + // S<1> waldo; + public void testMaxInstantiationDepth_430282() throws Exception { + // Just check that codan runs without any exceptions being thrown. + loadCodeAndRun(getAboveComment()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/SemanticQueries.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/SemanticQueries.java index 7d397029c6c..9c21eff49df 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/SemanticQueries.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/SemanticQueries.java @@ -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 virtualBaseCache = new HashMap(); public ICPPMethod[] collect(ICPPClassType root, IASTNode point) { - FinalOverriderMap finalOverriderMap = collectFinalOverriders(root, false, new HashSet(), point); + FinalOverriderMap finalOverriderMap = collectFinalOverriders(root, false, new HashSet(), + 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 inheritanceChain, IASTNode point) { + Set 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 deriving from A 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. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java index a8111ee3ed5..cf14fb8472a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java @@ -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 virtualInClass, - List result) { + List result, int maxdepth) { + // Prevent recursion due to a hierarchy of unbounded depth, + // e.g. A deriving from A. + 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; } }