virtual SVal evalComplement(NonLoc val) = 0;
+ /// Create a new value which represents a binary expression with two non
+ /// location operands.
virtual SVal evalBinOpNN(const ProgramState *state, BinaryOperator::Opcode op,
NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
+ /// Create a new value which represents a binary expression with two memory
+ /// location operands.
virtual SVal evalBinOpLL(const ProgramState *state, BinaryOperator::Opcode op,
Loc lhs, Loc rhs, QualType resultTy) = 0;
+ /// Create a new value which represents a binary expression with a memory
+ /// location and non location operands. For example, this would be used to
+ /// evaluate a pointer arithmetic operation.
virtual SVal evalBinOpLN(const ProgramState *state, BinaryOperator::Opcode op,
Loc lhs, NonLoc rhs, QualType resultTy) = 0;
- /// getKnownValue - evaluates a given SVal. If the SVal has only one possible
- /// (integer) value, that value is returned. Otherwise, returns NULL.
+ /// Evaluates a given SVal. If the SVal has only one possible (integer) value,
+ /// that value is returned. Otherwise, returns NULL.
virtual const llvm::APSInt *getKnownValue(const ProgramState *state, SVal val) = 0;
+ /// Handles generation of the value in case the builder is not smart enough to
+ /// handle the given binary expression. Depending on the state, decides to
+ /// either keep the expression or forget the history and generate an
+ /// UnknownVal.
+ SVal generateUnknownVal(const ProgramState *state, BinaryOperator::Opcode op,
+ NonLoc lhs, NonLoc rhs, QualType resultTy);
+
SVal evalBinOp(const ProgramState *state, BinaryOperator::Opcode op,
SVal lhs, SVal rhs, QualType type);
// UnknownVal.
if ((InitVal.isUnknown() ||
!getConstraintManager().canReasonAbout(InitVal)) &&
- !VD->getType()->isReferenceType()) {
+ !VD->getType()->isReferenceType() &&
+ !Pred->getState()->isTainted(InitVal)) {
InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx,
currentBuilderContext->getCurrentBlockCount());
}
// The Environment ensures we always get a persistent APSInt in
// BasicValueFactory, so we don't need to get the APSInt from
// BasicValueFactory again.
+ assert(lhs);
assert(!Loc::isLocType(type));
return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, rhs, type));
}
NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType type) {
+ assert(lhs && rhs);
assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
assert(!Loc::isLocType(type));
return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, type));
//===----------------------------------------------------------------------===//
+SVal SValBuilder::generateUnknownVal(const ProgramState *State,
+ BinaryOperator::Opcode Op,
+ NonLoc LHS, NonLoc RHS,
+ QualType ResultTy) {
+ // If operands are tainted, create a symbol to ensure that we propagate taint.
+ if (State->isTainted(RHS) || State->isTainted(LHS)) {
+ const SymExpr *symLHS;
+ const SymExpr *symRHS;
+
+ if (const nonloc::ConcreteInt *rInt = dyn_cast<nonloc::ConcreteInt>(&RHS)) {
+ symLHS = LHS.getAsSymExpr();
+ return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);
+ }
+ // TODO: Handle the case when lhs is ConcreteInt.
+
+ symLHS = LHS.getAsSymExpr();
+ symRHS = RHS.getAsSymExpr();
+ return makeNonLoc(symLHS, Op, symRHS, ResultTy);
+ }
+ return UnknownVal();
+}
+
+
SVal SValBuilder::evalBinOp(const ProgramState *state, BinaryOperator::Opcode op,
SVal lhs, SVal rhs, QualType type) {
while (1) {
switch (lhs.getSubKind()) {
default:
- return UnknownVal();
+ return generateUnknownVal(state, op, lhs, rhs, resultTy);
case nonloc::LocAsIntegerKind: {
Loc lhsL = cast<nonloc::LocAsInteger>(lhs).getLoc();
switch (rhs.getSubKind()) {
return makeTruthVal(true, resultTy);
default:
// This case also handles pointer arithmetic.
- return UnknownVal();
+ return generateUnknownVal(state, op, lhs, rhs, resultTy);
}
}
}
dyn_cast<SymIntExpr>(selhs->getSymbolicExpression());
if (!symIntExpr)
- return UnknownVal();
+ return generateUnknownVal(state, op, lhs, rhs, resultTy);
// Is this a logical not? (!x is represented as x == 0.)
if (op == BO_EQ && rhs.isZeroConstant()) {
// For now, only handle expressions whose RHS is a constant.
const nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs);
if (!rhsInt)
- return UnknownVal();
+ return generateUnknownVal(state, op, lhs, rhs, resultTy);
// If both the LHS and the current expression are additive,
// fold their constants.
if (lhsValue == 0)
// At this point lhs and rhs have been swapped.
return rhs;
- return UnknownVal();
+ return generateUnknownVal(state, op, lhs, rhs, resultTy);
default:
- return UnknownVal();
+ return generateUnknownVal(state, op, lhs, rhs, resultTy);
}
}
}
resultTy);
}
- return UnknownVal();
+ return generateUnknownVal(state, op, lhs, rhs, resultTy);
}
}
}
scanf("%d", &n);
Buffer[n] = 1; // expected-warning {{Out of bound memory access }}
}
+
+void bufferScanfArithmetic1(int x) {
+ int n;
+ scanf("%d", &n);
+ int m = (n - 3);
+ Buffer[m] = 1; // expected-warning {{Out of bound memory access }}
+}
+
+void bufferScanfArithmetic2(int x) {
+ int n;
+ scanf("%d", &n);
+ int m = (n + 3) * x;
+ Buffer[m] = 1; // expected-warning {{Out of bound memory access }}
+}