From 7501266165e96da46d2ac88aca019e6097d2928d Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Thu, 9 Mar 2017 18:34:27 -0800 Subject: [PATCH] Added protection against NPE and invalid values. Change-Id: I8b2b96acc9f7852a4857eabb81e4ff35f9e3a0a9 --- .../cdt/internal/core/dom/parser/ValueFactory.java | 10 ++++++---- .../core/dom/parser/cpp/semantics/EvalBinary.java | 9 +++++++-- .../dom/parser/cpp/semantics/EvalCompositeAccess.java | 2 ++ .../dom/parser/cpp/semantics/EvalFunctionCall.java | 9 +++++++-- .../dom/parser/cpp/semantics/EvalMemberAccess.java | 6 +++--- .../core/dom/parser/cpp/semantics/EvalUnary.java | 6 ++++-- .../core/dom/parser/cpp/semantics/EvalUtil.java | 8 +++++--- 7 files changed, 34 insertions(+), 16 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java index f4a5a865b34..3c838b68c0a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java @@ -297,12 +297,14 @@ public class ValueFactory { if (isInvalidValue(v)) return v; if (isDeferredValue(v)) - return null; // the value will be computed using the evaluation - if (v.numberValue().longValue() == 0) { + return null; // The value will be computed using the evaluation. + Number numericValue = v.numberValue(); + if (numericValue == null) + return IntegralValue.UNKNOWN; + if (v instanceof IntegralValue ? numericValue.longValue() == 0 : numericValue.doubleValue() == 0) return evaluate(cexpr.getNegativeResultExpression()); - } final IASTExpression pe = cexpr.getPositiveResultExpression(); - if (pe == null) // gnu-extension allows to omit the positive expression. + if (pe == null) // A gnu-extension allows to omit the positive expression. return v; return evaluate(pe); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java index 584973564f3..9447ec12a4f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java @@ -11,7 +11,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; -import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.*; +import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_assign; import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryAnd; import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryAndAssign; import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_binaryOr; @@ -461,6 +461,8 @@ public class EvalBinary extends CPPDependentEvaluation { return EvalFixed.INCOMPLETE; } } else { + if (updateable1 == EvalFixed.INCOMPLETE) + return EvalFixed.INCOMPLETE; int binaryOperator = getBinaryOperatorWithoutAssignment(fOperator); EvalBinary binaryOpEval = new EvalBinary(binaryOperator, fixed1, fixed2, getTemplateDefinition()); EvalBinary assignmentEval = new EvalBinary(op_assign, updateable1, binaryOpEval, getTemplateDefinition()); @@ -486,7 +488,10 @@ public class EvalBinary extends CPPDependentEvaluation { } return updateable1; } else if (fOperator == op_arrayAccess) { - return new EvalCompositeAccess(fixed1, fixed2.getValue(context.getPoint()).numberValue().intValue()); + Number numericValue = fixed2.getValue(context.getPoint()).numberValue(); + if (numericValue == null) + return EvalFixed.INCOMPLETE; + return new EvalCompositeAccess(fixed1, numericValue.intValue()); } else if ((isArray(fixed1, context) || isArray(fixed2, context)) && (hasIntType(fixed1, context) || hasIntType(fixed2, context))) { int offset = hasIntType(fixed1, context) ? fixed1.getValue(context.getPoint()).numberValue().intValue() : fixed2.getValue(context.getPoint()).numberValue().intValue(); EvalCompositeAccess evalCompositeAccess = new EvalCompositeAccess(isArray(fixed1, context) ? fixed1 : fixed2, offset); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompositeAccess.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompositeAccess.java index bea4209e012..29bb9162fc2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompositeAccess.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompositeAccess.java @@ -29,6 +29,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFunctionCall.ParameterPackType; +import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; /** @@ -40,6 +41,7 @@ public final class EvalCompositeAccess implements ICPPEvaluation { private final int elementId; // The index of the sub-value being accessed public EvalCompositeAccess(ICPPEvaluation parent, int elementId) { + Assert.isNotNull(parent); this.parent = parent; this.elementId = elementId; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java index 4248ec751d4..d5d57133134 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java @@ -45,6 +45,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution; import org.eclipse.cdt.internal.core.dom.parser.cpp.InstantiationContext; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics.LookupMode; +import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; public final class EvalFunctionCall extends CPPDependentEvaluation { @@ -58,6 +59,9 @@ public final class EvalFunctionCall extends CPPDependentEvaluation { public EvalFunctionCall(ICPPEvaluation[] args, ICPPEvaluation owner, IBinding templateDefinition) { super(templateDefinition); + for (int i = 0; i < args.length; i++) { + Assert.isNotNull(args[i]); + } fArguments = args; fImplicitThis = getImplicitThis() == owner ? null : owner; } @@ -247,14 +251,15 @@ public final class EvalFunctionCall extends CPPDependentEvaluation { IBinding binding = evalBinding.getBinding(); // If the binding being referenced isn't present in the activation record, // we won't be able to evaluate the function call. - if (record.getVariable(binding) == null) { + if (record.getVariable(binding) == null) return EvalFixed.INCOMPLETE; - } arg = new EvalReference(record, binding, evalBinding.getTemplateDefinition()); } else if (0 < i && i <= parameters.length && !isReference(parameters[i - 1])) { IValue copiedValue = arg.getValue(context.getPoint()).clone(); arg = new EvalFixed(arg.getType(context.getPoint()), arg.getValueCategory(context.getPoint()), copiedValue); } + if (arg == EvalFixed.INCOMPLETE) + return EvalFixed.INCOMPLETE; args[i] = arg; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java index bca7ef7db9e..44de9979fc1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java @@ -23,6 +23,8 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers; +import java.util.Collection; + import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; @@ -56,8 +58,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics.LookupMode; import org.eclipse.core.runtime.CoreException; -import java.util.Collection; - public class EvalMemberAccess extends CPPDependentEvaluation { private final IType fOwnerType; private final IBinding fMember; @@ -430,7 +430,7 @@ public class EvalMemberAccess extends CPPDependentEvaluation { EvalBinding evalBinding = new EvalBinding(fMember, fType, getTemplateDefinition()); return evalBinding; } - if (ownerEval == null) { + if (ownerEval == null || ownerEval == this) { return this; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java index 4919a2bbe1d..79c92842de8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java @@ -428,8 +428,10 @@ public class EvalUnary extends CPPDependentEvaluation { } else if (updateable instanceof EvalBinding && isStarOperatorOnArrayName(context)) { EvalBinding evalBinding = (EvalBinding) updateable; IBinding binding = evalBinding.getBinding(); - ICPPEvaluation value = record.getVariable(binding); - EvalCompositeAccess compositeAccess = new EvalCompositeAccess(value, 0); + ICPPEvaluation eval = record.getVariable(binding); + if (eval == null) + return EvalFixed.INCOMPLETE; + EvalCompositeAccess compositeAccess = new EvalCompositeAccess(eval, 0); return new EvalReference(record, compositeAccess, getTemplateDefinition()); } return evalUnary; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java index 25408a274db..bfa9a8d570d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUtil.java @@ -124,7 +124,9 @@ public class EvalUtil { updateable = eval; } ICPPEvaluation fixed = eval.computeForFunctionCall(record, context.recordStep()); - if (isUpdateable(fixed)) { + if (fixed == EvalFixed.INCOMPLETE) { + updateable = fixed; + } else if (isUpdateable(fixed)) { updateable = fixed; if (!(fixed instanceof EvalCompositeAccess)) { fixed = fixed.computeForFunctionCall(record, context); @@ -169,7 +171,7 @@ public class EvalUtil { IType nestedType = SemanticUtil.getNestedType(type, TDEF | REF | CVTYPE); IValue initialValue = variable.getInitialValue(); ICPPEvaluation valueEval = null; - + if ((initialValue != null && initialValue.getEvaluation() != null) || (initialValue == null && nestedType instanceof ICPPClassType)) { final ICPPEvaluation initializerEval = initialValue == null ? null : initialValue.getEvaluation(); @@ -185,7 +187,7 @@ public class EvalUtil { } else if (initialValue != null) { valueEval = new EvalFixed(type, ValueCategory.LVALUE, initialValue); } - + if (valueEval != null && (valueEval == EvalFixed.INCOMPLETE || valueEval.getValue(point) == IntegralValue.UNKNOWN)) { return null;