1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-30 21:55:31 +02:00

Safe guards against infinite recursions for value computation, bug 250788.

This commit is contained in:
Markus Schorn 2008-10-16 15:19:22 +00:00
parent d7e75c1559
commit 0cd1be7cee
14 changed files with 152 additions and 121 deletions

View file

@ -101,8 +101,12 @@ public abstract class ASTEnumerator extends ASTNode implements IASTEnumerator, I
public IValue getIntegralValue() {
if (integralValue == null) {
IASTNode parent= getParent();
if (parent instanceof IASTEnumerationSpecifier)
createEnumValues((IASTEnumerationSpecifier) parent);
if (parent instanceof IASTInternalEnumerationSpecifier) {
IASTInternalEnumerationSpecifier ies= (IASTInternalEnumerationSpecifier) parent;
if (ies.startValueComputation()) { // prevents infinite recursions
createEnumValues((IASTEnumerationSpecifier) parent);
}
}
if (integralValue == null) {
integralValue= Value.UNKNOWN;
}
@ -118,7 +122,7 @@ public abstract class ASTEnumerator extends ASTNode implements IASTEnumerator, I
cv++;
IASTExpression expr= etor.getValue();
if (expr != null) {
IValue val= Value.create(expr);
IValue val= Value.create(expr, Value.MAX_RECURSION_DEPTH);
Long nv= val.numericalValue();
isknown= false;
if (nv != null) {

View file

@ -18,13 +18,10 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.internal.core.dom.parser.c.ICInternalBinding;
import org.eclipse.cdt.internal.core.dom.parser.c.ICInternalFunction;
import org.eclipse.cdt.internal.core.dom.parser.c.ICInternalVariable;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalVariable;
/**
* Access to methods on scopes and bindings internal to the parser.
@ -94,16 +91,6 @@ public class ASTInternal {
return func.isStatic();
}
public static boolean isStatic(IVariable var) throws DOMException {
if (var instanceof ICPPInternalVariable) {
return ((ICPPInternalVariable)var).isStatic();
}
if (var instanceof ICInternalVariable) {
return ((ICInternalVariable)var).isStatic();
}
return var.isStatic();
}
public static void setFullyResolved(IBinding binding, boolean val) {
if (binding instanceof ICInternalFunction) {
((ICInternalFunction) binding).setFullyResolved(true);

View file

@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
/**
* Internal interface for c- or c++ enumeration specifiers.
*/
public interface IASTInternalEnumerationSpecifier extends IASTEnumerationSpecifier {
/**
* Notifies that the value computation for the enumeration is started. Returns whether this is the
* first attempt to do so.
*/
boolean startValueComputation();
}

View file

@ -0,0 +1,26 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.IVariable;
/**
* Internal interface for bindings in the ast that have values.
*/
public interface IInternalVariable extends IVariable {
/**
* Returns the value of the variable, or <code>null</code>.
* If the recursion depth is reached {@link Value#UNKNOWN} will be returned.
*/
IValue getInitialValue(int maxRecursionDepth);
}

View file

@ -36,11 +36,13 @@ import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalExce
* is to support instantiation of templates with non-type template parameters.
*/
public class Value implements IValue {
public static final int MAX_RECURSION_DEPTH = 25;
public final static IValue UNKNOWN= new Value("<unknown>"); //$NON-NLS-1$
private final static IValue[] TYPICAL= {new Value(String.valueOf(0)),
new Value(String.valueOf(1)), new Value(String.valueOf(2)), new Value(String.valueOf(3)),
new Value(String.valueOf(4)), new Value(String.valueOf(5)), new Value(String.valueOf(6))};
private static class UnknownValueException extends Exception {}
private static UnknownValueException UNKNOWN_EX= new UnknownValueException();
@ -67,9 +69,9 @@ public class Value implements IValue {
return new Value(String.valueOf(value));
}
public static IValue create(IASTExpression expr) {
public static IValue create(IASTExpression expr, int maxRecursionDepth) {
try {
Object obj= evaluate(expr, 20);
Object obj= evaluate(expr, maxRecursionDepth);
if (obj instanceof Long)
return create(((Long) obj).longValue());
return new Value(obj.toString());
@ -132,31 +134,31 @@ public class Value implements IValue {
return o + "," + evaluate(cexpr.getNegativeResultExpression(), maxdepth) + "," + po + '?';
}
if (e instanceof IASTIdExpression) {
if (e instanceof IASTIdExpression) {
IBinding b= ((IASTIdExpression) e).getName().resolveBinding();
if (b instanceof ICPPTemplateParameter) {
if (b instanceof ICPPTemplateNonTypeParameter) {
return evaluate((ICPPTemplateParameter) b);
}
throw UNKNOWN_EX;
} else if (b instanceof IVariable) {
IValue cv= ((IVariable) b).getInitialValue();
if (cv != null) {
return toObject(cv);
}
} else if (b instanceof IEnumerator) {
IValue cv= ((IEnumerator) b).getValue();
return toObject(cv);
}
try {
if (b instanceof ICPPBinding)
return ((ICPPBinding) b).getQualifiedName();
return b.getName();
} catch (DOMException e1) {
throw UNKNOWN_EX;
IBinding b= ((IASTIdExpression) e).getName().resolveBinding();
if (b instanceof ICPPTemplateParameter) {
if (b instanceof ICPPTemplateNonTypeParameter) {
return evaluate((ICPPTemplateParameter) b);
}
throw UNKNOWN_EX;
}
IValue cv= null;
if (b instanceof IInternalVariable) {
cv= ((IInternalVariable) b).getInitialValue(maxdepth-1);
} else if (b instanceof IVariable) {
cv= ((IVariable) b).getInitialValue();
} else if (b instanceof IEnumerator) {
cv= ((IEnumerator) b).getValue();
}
if (cv != null)
return toObject(cv);
try {
if (b instanceof ICPPBinding)
return ((ICPPBinding) b).getQualifiedName();
return b.getName();
} catch (DOMException e1) {
throw UNKNOWN_EX;
}
return evaluate(e, --maxdepth); // prevent recursion
}
if (e instanceof IASTLiteralExpression) {
if (e.getExpressionType() instanceof IBasicType) {

View file

@ -6,9 +6,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Rational Software - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Yuan Zhang / Beth Tibbitts (IBM Research)
* John Camelon (IBM Rational Software) - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Yuan Zhang / Beth Tibbitts (IBM Research)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c;
@ -16,14 +16,16 @@ import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.c.ICASTEnumerationSpecifier;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalEnumerationSpecifier;
/**
* @author jcamelon
* AST node for enumeration specifiers.
*/
public class CASTEnumerationSpecifier extends CASTBaseDeclSpecifier implements
ICASTEnumerationSpecifier {
public class CASTEnumerationSpecifier extends CASTBaseDeclSpecifier
implements IASTInternalEnumerationSpecifier, ICASTEnumerationSpecifier {
private IASTName name;
private boolean valuesComputed= false;
public CASTEnumerationSpecifier() {
@ -33,6 +35,14 @@ public class CASTEnumerationSpecifier extends CASTBaseDeclSpecifier implements
setName(name);
}
public boolean startValueComputation() {
if (valuesComputed)
return false;
valuesComputed= true;
return true;
}
public void addEnumerator(IASTEnumerator enumerator) {
if (enumerator != null) {
enumerator.setParent(this);

View file

@ -29,14 +29,15 @@ import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.IInternalVariable;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.core.runtime.PlatformObject;
/**
* Represents a global or a local variable.
* Binding for a global or a local variable, serves as base class for fields.
*/
public class CVariable extends PlatformObject implements IVariable, ICInternalVariable {
public class CVariable extends PlatformObject implements IInternalVariable, ICInternalBinding {
public static class CVariableProblem extends ProblemBinding implements IVariable {
public CVariableProblem( IASTNode node, int id, char[] arg ) {
super( node, id, arg );
@ -161,11 +162,15 @@ public class CVariable extends PlatformObject implements IVariable, ICInternalVa
}
public IValue getInitialValue() {
return getInitialValue(Value.MAX_RECURSION_DEPTH);
}
public IValue getInitialValue(int maxDepth) {
if (declarations != null) {
for (IASTName decl : declarations) {
if (decl == null)
break;
final IValue val= getInitialValue(decl);
final IValue val= getInitialValue(decl, maxDepth);
if (val != null)
return val;
}
@ -173,14 +178,14 @@ public class CVariable extends PlatformObject implements IVariable, ICInternalVa
return null;
}
private IValue getInitialValue(IASTName name) {
private IValue getInitialValue(IASTName name, int maxDepth) {
IASTDeclarator dtor= findDeclarator(name);
if (dtor != null) {
IASTInitializer init= dtor.getInitializer();
if (init instanceof IASTInitializerExpression) {
IASTExpression expr= ((IASTInitializerExpression) init).getExpression();
if (expr != null)
return Value.create(expr);
return Value.create(expr, maxDepth);
}
if (init != null)
return Value.UNKNOWN;

View file

@ -1,26 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c;
import org.eclipse.cdt.core.dom.ast.DOMException;
/**
* Interface for ast-internal implementations of variable bindings.
* @since 5.0
*/
public interface ICInternalVariable extends ICInternalBinding {
/**
* Returns whether there is a static declaration for this variable.
*/
public boolean isStatic() throws DOMException;
}

View file

@ -6,22 +6,24 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalEnumerationSpecifier;
/**
* @author jcamelon
* AST node for c++ enumeration specifiers.
*/
public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier
implements IASTEnumerationSpecifier {
implements IASTInternalEnumerationSpecifier {
private IASTName name;
private boolean valuesComputed= false;
public CPPASTEnumerationSpecifier() {
@ -30,6 +32,14 @@ public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier
public CPPASTEnumerationSpecifier(IASTName name) {
setName(name);
}
public boolean startValueComputation() {
if (valuesComputed)
return false;
valuesComputed= true;
return true;
}
public void addEnumerator(IASTEnumerator enumerator) {
if (enumerator != null) {

View file

@ -19,11 +19,13 @@ import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.IInternalVariable;
import org.eclipse.cdt.internal.core.dom.parser.Value;
/**
* Binding for a specialization of a field.
*/
public class CPPFieldSpecialization extends CPPSpecialization implements ICPPField {
public class CPPFieldSpecialization extends CPPSpecialization implements ICPPField, IInternalVariable {
private IType type = null;
private IValue value= null;
@ -79,8 +81,19 @@ public class CPPFieldSpecialization extends CPPSpecialization implements ICPPFie
}
public IValue getInitialValue() {
return getInitialValue(Value.MAX_RECURSION_DEPTH);
}
public IValue getInitialValue(int maxRecursionDepth) {
if (value == null) {
value= specializeValue(getField().getInitialValue());
ICPPField field= getField();
IValue v;
if (field instanceof IInternalVariable) {
v= ((IInternalVariable) field).getInitialValue(maxRecursionDepth);
} else {
v= specializeValue(getField().getInitialValue());
}
value= specializeValue(v);
}
return value;
}

View file

@ -37,6 +37,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IInternalVariable;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
@ -46,7 +47,7 @@ import org.eclipse.core.runtime.PlatformObject;
/**
* @author aniefer
*/
public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInternalVariable {
public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInternalBinding, IInternalVariable {
public static class CPPVariableProblem extends ProblemBinding implements ICPPVariable{
public CPPVariableProblem(IASTNode node, int id, char[] arg) {
super(node, id, arg);
@ -376,8 +377,12 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
}
public IValue getInitialValue() {
return getInitialValue(Value.MAX_RECURSION_DEPTH);
}
public IValue getInitialValue(int maxDepth) {
if (definition != null) {
final IValue val= getInitialValue(definition);
final IValue val= getInitialValue(definition, maxDepth);
if (val != null)
return val;
}
@ -385,7 +390,7 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
for (IASTName decl : declarations) {
if (decl == null)
break;
final IValue val= getInitialValue(decl);
final IValue val= getInitialValue(decl, maxDepth);
if (val != null)
return val;
}
@ -393,20 +398,20 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
return null;
}
private IValue getInitialValue(IASTName name) {
private IValue getInitialValue(IASTName name, int maxDepth) {
IASTDeclarator dtor= findDeclarator(name);
if (dtor != null) {
IASTInitializer init= dtor.getInitializer();
if (init instanceof IASTInitializerExpression) {
IASTExpression expr= ((IASTInitializerExpression) init).getExpression();
if (expr != null)
return Value.create(expr);
return Value.create(expr, maxDepth);
} else if (init instanceof ICPPASTConstructorInitializer) {
IType type= SemanticUtil.getUltimateTypeUptoPointers(getType());
if (type instanceof IPointerType || type instanceof IBasicType) {
IASTExpression expr= ((ICPPASTConstructorInitializer) init).getExpression();
if (expr != null)
return Value.create(expr);
return Value.create(expr, maxDepth);
}
}
if (init != null)

View file

@ -1,27 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007, 2008 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
/**
* Interface for ast-internal implementations of variable bindings.
* @since 5.0
*/
public interface ICPPInternalVariable extends ICPPInternalBinding {
/**
* Returns whether there is a static declaration for this variable.
*/
public boolean isStatic() throws DOMException;
}

View file

@ -2227,8 +2227,7 @@ public class CPPVisitor {
public static String[] getQualifiedName(IBinding binding) {
String[] ns = null;
try {
IBinding owner= binding.getOwner();
while (owner != null) {
for (IBinding owner= binding.getOwner(); owner != null; owner= owner.getOwner()) {
String n= owner.getName();
if (n == null)
break;
@ -2238,7 +2237,6 @@ public class CPPVisitor {
continue;
ns = (String[]) ArrayUtil.append(String.class, ns, n);
owner = owner.getOwner();
}
} catch (DOMException e) {
}

View file

@ -229,7 +229,7 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
boolean requireDefinition= false;
if (binding instanceof IVariable) {
if (!(binding instanceof IField)) {
checkInSourceOnly= ASTInternal.isStatic((IVariable) binding);
checkInSourceOnly= ((IVariable) binding).isStatic();
}
} else if (binding instanceof IFunction) {
IFunction f= (IFunction) binding;