1
0
Fork 0
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:
Nathan Ridge 2015-11-26 20:46:50 -05:00 committed by Sergey Prigogin
parent 9bcb71b26a
commit 069d106ab4
2 changed files with 43 additions and 0 deletions

View file

@ -2847,4 +2847,27 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
// intermediate results cannot be collapsed into a single value. // intermediate results cannot be collapsed into a single value.
checkBindings(); 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();
}
} }

View file

@ -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.CPPArrayType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassInstance; 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;
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.CPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplatePartialSpecializationSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplatePartialSpecializationSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplateSpecialization; 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 final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE;
static enum TypeSelection { PARAMETERS, RETURN_TYPE, PARAMETERS_AND_RETURN_TYPE } 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}. * 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) { public static IBinding createSpecialization(ICPPClassSpecialization owner, IBinding decl, IASTNode point) {
IBinding spec = null; IBinding spec = null;
final ICPPTemplateParameterMap tpMap= owner.getTemplateParameterMap(); 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 { try {
if (decl instanceof ICPPClassTemplatePartialSpecialization) { if (decl instanceof ICPPClassTemplatePartialSpecialization) {
try { try {
@ -1007,6 +1024,9 @@ public class CPPTemplates {
} }
} catch (DOMException e) { } catch (DOMException e) {
CCorePlugin.log(e); CCorePlugin.log(e);
} finally {
// Restore original instantiation depth.
fTemplateInstantiationDepth.set(instantiationDepth);
} }
return spec; return spec;
} }