mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 18:26:01 +02:00
Bug 479138 - Impose a global template instantiation depth limit
This protects against rogue template metaprograms that don't terminate. Change-Id: I9558ceaaed17baddbed84aac67a3c72397b62b64 Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
parent
9bcb71b26a
commit
069d106ab4
2 changed files with 43 additions and 0 deletions
|
@ -2847,4 +2847,27 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
|
|||
// intermediate results cannot be collapsed into a single value.
|
||||
checkBindings();
|
||||
}
|
||||
|
||||
// template<long _Ax> struct _GcdX {
|
||||
// static const long value = _GcdX<_Ax - 1>::value;
|
||||
// };
|
||||
//
|
||||
// template<long _Ax> struct R {
|
||||
// static const long value = _Ax;
|
||||
// };
|
||||
//
|
||||
// template<class _R1> struct Operation {
|
||||
// static const long _N1 = _R1::value;
|
||||
// typedef R<_GcdX<_N1>::value> value;
|
||||
// };
|
||||
//
|
||||
// typedef Operation< R<1> >::value MYTYPE;
|
||||
|
||||
// // empty file
|
||||
// // special:allowRecursionBindings
|
||||
public void testRecursiveTemplateInstantiation_479138c() throws Exception {
|
||||
// This tests that a template metaprogram that doesn't terminate at all
|
||||
// (e.g. because the author omitted a base case) doesn't cause a stack overflow.
|
||||
checkBindings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPAliasTemplateInstance;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassInstance;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassSpecialization;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassSpecialization.RecursionResolvingBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplatePartialSpecialization;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplatePartialSpecializationSpecialization;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplateSpecialization;
|
||||
|
@ -195,6 +196,15 @@ public class CPPTemplates {
|
|||
static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE;
|
||||
|
||||
static enum TypeSelection { PARAMETERS, RETURN_TYPE, PARAMETERS_AND_RETURN_TYPE }
|
||||
|
||||
// Infrastructure to protect against rogue template metaprograms that don't terminate.
|
||||
private static final int TEMPLATE_INSTANTIATION_DEPTH_LIMIT = 256;
|
||||
private static final ThreadLocal<Integer> fTemplateInstantiationDepth = new ThreadLocal<Integer>() {
|
||||
@Override
|
||||
protected Integer initialValue() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiates a class template with the given arguments. May return {@code null}.
|
||||
|
@ -901,6 +911,13 @@ public class CPPTemplates {
|
|||
public static IBinding createSpecialization(ICPPClassSpecialization owner, IBinding decl, IASTNode point) {
|
||||
IBinding spec = null;
|
||||
final ICPPTemplateParameterMap tpMap= owner.getTemplateParameterMap();
|
||||
// Guard against infinite recursion during template instantiation with a depth limit.
|
||||
int instantiationDepth = fTemplateInstantiationDepth.get();
|
||||
if (instantiationDepth > TEMPLATE_INSTANTIATION_DEPTH_LIMIT) {
|
||||
return RecursionResolvingBinding.createFor(decl, point);
|
||||
}
|
||||
// Increment the instantiation depth for the duration of this call.
|
||||
fTemplateInstantiationDepth.set(instantiationDepth + 1);
|
||||
try {
|
||||
if (decl instanceof ICPPClassTemplatePartialSpecialization) {
|
||||
try {
|
||||
|
@ -1007,6 +1024,9 @@ public class CPPTemplates {
|
|||
}
|
||||
} catch (DOMException e) {
|
||||
CCorePlugin.log(e);
|
||||
} finally {
|
||||
// Restore original instantiation depth.
|
||||
fTemplateInstantiationDepth.set(instantiationDepth);
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue