mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
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:
parent
b4d65483ed
commit
cff738fe0b
3 changed files with 32 additions and 8 deletions
|
@ -365,4 +365,13 @@ public class AbstractClassInstantiationCheckerTest extends CheckerTestCase {
|
||||||
// Just check that codan runs without any exceptions being thrown.
|
// Just check that codan runs without any exceptions being thrown.
|
||||||
loadCodeAndRun(getAboveComment());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.parser.util.CollectionUtils;
|
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.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.CPPTemplates;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
|
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>();
|
private Map<ICPPClassType, FinalOverriderMap> virtualBaseCache = new HashMap<ICPPClassType, FinalOverriderMap>();
|
||||||
|
|
||||||
public ICPPMethod[] collect(ICPPClassType root, IASTNode point) {
|
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();
|
return finalOverriderMap.collectPureVirtualMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +214,7 @@ public class SemanticQueries {
|
||||||
* @return the computed final overrider map
|
* @return the computed final overrider map
|
||||||
*/
|
*/
|
||||||
private FinalOverriderMap collectFinalOverriders(ICPPClassType classType, boolean isVirtualBase,
|
private FinalOverriderMap collectFinalOverriders(ICPPClassType classType, boolean isVirtualBase,
|
||||||
Set<ICPPClassType> inheritanceChain, IASTNode point) {
|
Set<ICPPClassType> inheritanceChain, int maxdepth, IASTNode point) {
|
||||||
FinalOverriderMap result = new FinalOverriderMap();
|
FinalOverriderMap result = new FinalOverriderMap();
|
||||||
|
|
||||||
inheritanceChain.add(classType);
|
inheritanceChain.add(classType);
|
||||||
|
@ -236,6 +238,12 @@ public class SemanticQueries {
|
||||||
if (inheritanceChain.contains(baseType))
|
if (inheritanceChain.contains(baseType))
|
||||||
continue;
|
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.
|
// Collect final overrider information from the base class.
|
||||||
// If it's a virtual base class and we've already processed it
|
// If it's a virtual base class and we've already processed it
|
||||||
// in this class hierarchy, don't process it again.
|
// in this class hierarchy, don't process it again.
|
||||||
|
@ -243,11 +251,11 @@ public class SemanticQueries {
|
||||||
if (base.isVirtual()) {
|
if (base.isVirtual()) {
|
||||||
baseOverriderMap = virtualBaseCache.get(baseType);
|
baseOverriderMap = virtualBaseCache.get(baseType);
|
||||||
if (baseOverriderMap == null) {
|
if (baseOverriderMap == null) {
|
||||||
baseOverriderMap = collectFinalOverriders(baseType, true, inheritanceChain, point);
|
baseOverriderMap = collectFinalOverriders(baseType, true, inheritanceChain, maxdepth - 1, point);
|
||||||
virtualBaseCache.put(baseType, baseOverriderMap);
|
virtualBaseCache.put(baseType, baseOverriderMap);
|
||||||
}
|
}
|
||||||
} else {
|
} 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.
|
// Merge final overrider information from base class into this class.
|
||||||
|
|
|
@ -593,7 +593,8 @@ public class ClassTypeHelper {
|
||||||
for (ICPPBase base : bases) {
|
for (ICPPBase base : bases) {
|
||||||
IBinding b= base.getBaseClass();
|
IBinding b= base.getBaseClass();
|
||||||
if (b instanceof ICPPClassType) {
|
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,
|
private static boolean findOverridden(ICPPClassType classType, IASTNode point, char[] methodName,
|
||||||
ICPPFunctionType methodType, Map<ICPPClassType, Boolean> virtualInClass,
|
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);
|
Boolean visitedBefore= virtualInClass.get(classType);
|
||||||
if (visitedBefore != null)
|
if (visitedBefore != null)
|
||||||
return visitedBefore;
|
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);
|
virtualInClass.put(classType, hasOverridden);
|
||||||
ICPPBase[] bases= getBases(classType, point);
|
ICPPBase[] bases= getBases(classType, point);
|
||||||
for (ICPPBase base : bases) {
|
for (ICPPBase base : bases) {
|
||||||
IBinding b= base.getBaseClass();
|
IBinding b= base.getBaseClass();
|
||||||
if (b instanceof ICPPClassType) {
|
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;
|
hasOverridden= true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue