mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Protection against infinite recursion, bug 231742.
This commit is contained in:
parent
d09c6c7601
commit
def81d5ae0
7 changed files with 37 additions and 22 deletions
|
@ -10,14 +10,14 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.dom.ast;
|
||||
|
||||
import org.eclipse.cdt.core.parser.util.IObjectComparator;
|
||||
import org.eclipse.cdt.core.parser.util.IObjectMatcher;
|
||||
|
||||
public class ASTTypeComparator implements IObjectComparator {
|
||||
public class ASTTypeMatcher implements IObjectMatcher {
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the two objects are equal or represent the same type.
|
||||
*/
|
||||
public boolean isSame(Object o1, Object o2) {
|
||||
public boolean isEquivalent(Object o1, Object o2) {
|
||||
if (o1 == o2) {
|
||||
return true;
|
||||
}
|
|
@ -16,7 +16,7 @@ package org.eclipse.cdt.core.dom.ast;
|
|||
*/
|
||||
public interface IType extends Cloneable {
|
||||
public static final IType[] EMPTY_TYPE_ARRAY = new IType[0];
|
||||
public static final ASTTypeComparator TYPE_COMPARATOR = new ASTTypeComparator();
|
||||
public static final ASTTypeMatcher TYPE_MATCHER = new ASTTypeMatcher();
|
||||
|
||||
public Object clone();
|
||||
|
||||
|
|
|
@ -10,6 +10,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.util;
|
||||
|
||||
public interface IObjectComparator {
|
||||
boolean isSame(Object o1, Object o2);
|
||||
public interface IObjectMatcher {
|
||||
boolean isEquivalent(Object o1, Object o2);
|
||||
}
|
|
@ -145,14 +145,14 @@ public class ObjectMap extends ObjectTable<Object> {
|
|||
return vals;
|
||||
}
|
||||
|
||||
public boolean isSame(ObjectMap other, IObjectComparator comparator) {
|
||||
if (!super.isSame(other, comparator)) {
|
||||
public boolean isEquivalent(ObjectMap other, IObjectMatcher matcher) {
|
||||
if (!super.isEquivalent(other, matcher)) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < keyTable.length; i++) {
|
||||
Object val1 = valueTable[i];
|
||||
Object val2 = other.valueTable[i];
|
||||
if (val1 != val2 && !comparator.isSame(val1, val2)) {
|
||||
if (val1 != val2 && !matcher.isEquivalent(val1, val2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ public abstract class ObjectTable<T> extends HashTable {
|
|||
return keys;
|
||||
}
|
||||
|
||||
public boolean isSame(ObjectTable<T> other, IObjectComparator comparator) {
|
||||
public boolean isEquivalent(ObjectTable<T> other, IObjectMatcher matcher) {
|
||||
if (size() != other.size()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ public abstract class ObjectTable<T> extends HashTable {
|
|||
for (int i = 0; i < keyTable.length; i++) {
|
||||
T key1 = keyTable[i];
|
||||
T key2 = other.keyTable[i];
|
||||
if (key1 != key2 && !comparator.isSame(key1, key2)) {
|
||||
if (key1 != key2 && !matcher.isEquivalent(key1, key2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ public class CPPASTName extends CPPASTNode implements IASTName, IASTCompletionCo
|
|||
* For test-purposes, only.
|
||||
*/
|
||||
public static boolean fAllowRecursionBindings= true;
|
||||
|
||||
final static class RecursionResolvingBinding extends ProblemBinding {
|
||||
public RecursionResolvingBinding(IASTName node) {
|
||||
super(node, IProblemBinding.SEMANTIC_RECURSION_IN_LOOKUP, node.toCharArray());
|
||||
|
@ -55,7 +56,6 @@ public class CPPASTName extends CPPASTNode implements IASTName, IASTCompletionCo
|
|||
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
|
||||
|
||||
static final int MAX_RESOLUTION_DEPTH = 5;
|
||||
|
||||
|
||||
private char[] name;
|
||||
private IBinding binding = null;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
|
@ -22,12 +23,23 @@ import org.eclipse.cdt.core.parser.util.ObjectMap;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
|
||||
import org.eclipse.core.runtime.Assert;
|
||||
|
||||
/**
|
||||
* @author aniefer
|
||||
*/
|
||||
public class CPPTypedefSpecialization extends CPPSpecialization implements ITypedef, ITypeContainer {
|
||||
private IType type;
|
||||
final static class RecursionResolvingBinding extends ProblemBinding {
|
||||
public RecursionResolvingBinding(IASTNode node, char[] arg) {
|
||||
super(node, IProblemBinding.SEMANTIC_RECURSION_IN_LOOKUP, arg);
|
||||
Assert.isTrue(CPPASTName.fAllowRecursionBindings, getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static final int MAX_RESOLUTION_DEPTH = 5;
|
||||
|
||||
private IType type;
|
||||
private int fResolutionDepth;
|
||||
|
||||
/**
|
||||
* @param specialized
|
||||
|
@ -47,15 +59,18 @@ public class CPPTypedefSpecialization extends CPPSpecialization implements IType
|
|||
*/
|
||||
public IType getType() throws DOMException {
|
||||
if (type == null) {
|
||||
type = CPPTemplates.instantiateType(getTypedef().getType(), argumentMap, getScope());
|
||||
// A typedef pointing to itself is a sure recipe for an infinite loop -- replace with
|
||||
// a problem binding.
|
||||
if (type instanceof CPPTypedefSpecialization &&
|
||||
((CPPTypedefSpecialization) type).getSpecializedBinding().equals(getSpecializedBinding()) &&
|
||||
((CPPTypedefSpecialization) type).getArgumentMap().isSame(argumentMap, IType.TYPE_COMPARATOR)) {
|
||||
type = new ProblemBinding(getDefinition(), IProblemBinding.SEMANTIC_INVALID_TYPE,
|
||||
getNameCharArray());
|
||||
}
|
||||
if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
|
||||
type = new RecursionResolvingBinding(getDefinition(), getNameCharArray());
|
||||
} else {
|
||||
type = CPPTemplates.instantiateType(getTypedef().getType(), argumentMap, getScope());
|
||||
// A typedef pointing to itself is a sure recipe for an infinite loop -- replace
|
||||
// with a problem binding.
|
||||
if (type instanceof CPPTypedefSpecialization &&
|
||||
((CPPTypedefSpecialization) type).getSpecializedBinding().equals(getSpecializedBinding()) &&
|
||||
((CPPTypedefSpecialization) type).getArgumentMap().isEquivalent(argumentMap, IType.TYPE_MATCHER)) {
|
||||
type = new RecursionResolvingBinding(getDefinition(), getNameCharArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue