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;
|
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.
|
* 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) {
|
if (o1 == o2) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ package org.eclipse.cdt.core.dom.ast;
|
||||||
*/
|
*/
|
||||||
public interface IType extends Cloneable {
|
public interface IType extends Cloneable {
|
||||||
public static final IType[] EMPTY_TYPE_ARRAY = new IType[0];
|
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();
|
public Object clone();
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.parser.util;
|
package org.eclipse.cdt.core.parser.util;
|
||||||
|
|
||||||
public interface IObjectComparator {
|
public interface IObjectMatcher {
|
||||||
boolean isSame(Object o1, Object o2);
|
boolean isEquivalent(Object o1, Object o2);
|
||||||
}
|
}
|
|
@ -145,14 +145,14 @@ public class ObjectMap extends ObjectTable<Object> {
|
||||||
return vals;
|
return vals;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSame(ObjectMap other, IObjectComparator comparator) {
|
public boolean isEquivalent(ObjectMap other, IObjectMatcher matcher) {
|
||||||
if (!super.isSame(other, comparator)) {
|
if (!super.isEquivalent(other, matcher)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < keyTable.length; i++) {
|
for (int i = 0; i < keyTable.length; i++) {
|
||||||
Object val1 = valueTable[i];
|
Object val1 = valueTable[i];
|
||||||
Object val2 = other.valueTable[i];
|
Object val2 = other.valueTable[i];
|
||||||
if (val1 != val2 && !comparator.isSame(val1, val2)) {
|
if (val1 != val2 && !matcher.isEquivalent(val1, val2)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,7 +154,7 @@ public abstract class ObjectTable<T> extends HashTable {
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSame(ObjectTable<T> other, IObjectComparator comparator) {
|
public boolean isEquivalent(ObjectTable<T> other, IObjectMatcher matcher) {
|
||||||
if (size() != other.size()) {
|
if (size() != other.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,7 @@ public abstract class ObjectTable<T> extends HashTable {
|
||||||
for (int i = 0; i < keyTable.length; i++) {
|
for (int i = 0; i < keyTable.length; i++) {
|
||||||
T key1 = keyTable[i];
|
T key1 = keyTable[i];
|
||||||
T key2 = other.keyTable[i];
|
T key2 = other.keyTable[i];
|
||||||
if (key1 != key2 && !comparator.isSame(key1, key2)) {
|
if (key1 != key2 && !matcher.isEquivalent(key1, key2)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ public class CPPASTName extends CPPASTNode implements IASTName, IASTCompletionCo
|
||||||
* For test-purposes, only.
|
* For test-purposes, only.
|
||||||
*/
|
*/
|
||||||
public static boolean fAllowRecursionBindings= true;
|
public static boolean fAllowRecursionBindings= true;
|
||||||
|
|
||||||
final static class RecursionResolvingBinding extends ProblemBinding {
|
final static class RecursionResolvingBinding extends ProblemBinding {
|
||||||
public RecursionResolvingBinding(IASTName node) {
|
public RecursionResolvingBinding(IASTName node) {
|
||||||
super(node, IProblemBinding.SEMANTIC_RECURSION_IN_LOOKUP, node.toCharArray());
|
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$
|
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
|
||||||
|
|
||||||
static final int MAX_RESOLUTION_DEPTH = 5;
|
static final int MAX_RESOLUTION_DEPTH = 5;
|
||||||
|
|
||||||
|
|
||||||
private char[] name;
|
private char[] name;
|
||||||
private IBinding binding = null;
|
private IBinding binding = null;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
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.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
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.ITypeContainer;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||||
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.core.runtime.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author aniefer
|
* @author aniefer
|
||||||
*/
|
*/
|
||||||
public class CPPTypedefSpecialization extends CPPSpecialization implements ITypedef, ITypeContainer {
|
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
|
* @param specialized
|
||||||
|
@ -47,15 +59,18 @@ public class CPPTypedefSpecialization extends CPPSpecialization implements IType
|
||||||
*/
|
*/
|
||||||
public IType getType() throws DOMException {
|
public IType getType() throws DOMException {
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
type = CPPTemplates.instantiateType(getTypedef().getType(), argumentMap, getScope());
|
if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
|
||||||
// A typedef pointing to itself is a sure recipe for an infinite loop -- replace with
|
type = new RecursionResolvingBinding(getDefinition(), getNameCharArray());
|
||||||
// a problem binding.
|
} else {
|
||||||
if (type instanceof CPPTypedefSpecialization &&
|
type = CPPTemplates.instantiateType(getTypedef().getType(), argumentMap, getScope());
|
||||||
((CPPTypedefSpecialization) type).getSpecializedBinding().equals(getSpecializedBinding()) &&
|
// A typedef pointing to itself is a sure recipe for an infinite loop -- replace
|
||||||
((CPPTypedefSpecialization) type).getArgumentMap().isSame(argumentMap, IType.TYPE_COMPARATOR)) {
|
// with a problem binding.
|
||||||
type = new ProblemBinding(getDefinition(), IProblemBinding.SEMANTIC_INVALID_TYPE,
|
if (type instanceof CPPTypedefSpecialization &&
|
||||||
getNameCharArray());
|
((CPPTypedefSpecialization) type).getSpecializedBinding().equals(getSpecializedBinding()) &&
|
||||||
}
|
((CPPTypedefSpecialization) type).getArgumentMap().isEquivalent(argumentMap, IType.TYPE_MATCHER)) {
|
||||||
|
type = new RecursionResolvingBinding(getDefinition(), getNameCharArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue