1
0
Fork 0
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:
Sergey Prigogin 2008-06-02 06:12:17 +00:00
parent d09c6c7601
commit def81d5ae0
7 changed files with 37 additions and 22 deletions

View file

@ -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;
}

View file

@ -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();

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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;
}