21 #include "llvm/ADT/SmallString.h" 22 #include "llvm/Support/raw_ostream.h" 24 using namespace clang;
28 class UndefResultChecker
29 :
public Checker< check::PostStmt<BinaryOperator> > {
31 mutable std::unique_ptr<BugType> BT;
41 if (!isa<ArraySubscriptExpr>(Ex))
56 ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements,
true);
57 ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements,
false);
58 return StOutBound && !StInBound;
72 return (
unsigned)RHS->getZExtValue() > LHS->countLeadingZeros();
94 new BuiltinBug(
this,
"Result of operation is garbage or undefined"));
97 llvm::raw_svector_ostream OS(sbuf);
98 const Expr *Ex =
nullptr;
111 OS <<
"The " << (isLeft ?
"left" :
"right") <<
" operand of '" 113 <<
"' is a garbage value";
115 OS <<
" due to array index out of bounds";
118 if ((B->
getOpcode() == BinaryOperatorKind::BO_Shl ||
119 B->
getOpcode() == BinaryOperatorKind::BO_Shr) &&
121 OS <<
"The result of the " 122 << ((B->
getOpcode() == BinaryOperatorKind::BO_Shl) ?
"left" 124 <<
" shift is undefined because the right operand is negative";
125 }
else if ((B->
getOpcode() == BinaryOperatorKind::BO_Shl ||
126 B->
getOpcode() == BinaryOperatorKind::BO_Shr) &&
129 OS <<
"The result of the " 130 << ((B->
getOpcode() == BinaryOperatorKind::BO_Shl) ?
"left" 132 <<
" shift is undefined due to shifting by ";
135 const llvm::APSInt *I =
138 OS <<
"a value that is";
139 else if (I->isUnsigned())
140 OS <<
'\'' << I->getZExtValue() <<
"\', which is";
142 OS <<
'\'' << I->getSExtValue() <<
"\', which is";
144 OS <<
" greater or equal to the width of type '" 146 }
else if (B->
getOpcode() == BinaryOperatorKind::BO_Shl &&
148 OS <<
"The result of the left shift is undefined because the left " 149 "operand is negative";
150 }
else if (B->
getOpcode() == BinaryOperatorKind::BO_Shl &&
154 const llvm::APSInt *LHS =
156 const llvm::APSInt *RHS =
158 OS <<
"The result of the left shift is undefined due to shifting \'" 159 << LHS->getSExtValue() <<
"\' by \'" << RHS->getZExtValue()
160 <<
"\', which is unrepresentable in the unsigned version of " 164 OS <<
"The result of the '" 166 <<
"' expression is undefined";
169 auto report = llvm::make_unique<BugReport>(*BT, OS.str(), N);
172 bugreporter::trackNullOrUndefValue(N, Ex, *report);
175 bugreporter::trackNullOrUndefValue(N, B, *report);
virtual DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state, const MemRegion *region, QualType EleTy)
Represents a function declaration or definition.
MemRegion - The root abstract class for all memory regions.
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
const MemRegion * getSuperRegion() const
StringRef getCalleeName(const FunctionDecl *FunDecl) const
Get the name of the called function (path-sensitive).
bool isGreaterOrEqual(const Expr *E, unsigned long long Val)
Returns true if the value of E is greater than or equal to Val under unsigned comparison.
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
static bool isShiftOverflow(const BinaryOperator *B, CheckerContext &C)
StringRef getOpcodeStr() const
static bool isArrayIndexOutOfBounds(CheckerContext &C, const Expr *Ex)
A builtin binary operation expression such as "x + y" or "x <= y".
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
static bool isLeftShiftResultUnrepresentable(const BinaryOperator *B, CheckerContext &C)
Expr - This represents one expression.
CHECKER * registerChecker(AT... Args)
Used to register checkers.
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
StoreManager & getStoreManager()
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Dataflow Directional Tag Classes.
ASTContext & getASTContext()
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
const Decl * getDecl() const
unsigned getIntWidth(QualType T) const
const StackFrameContext * getStackFrame() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
const ProgramStateRef & getState() const
bool isNegative(const Expr *E)
Returns true if the value of E is negative.
QualType getValueType() const override
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SValBuilder & getSValBuilder()
ElementRegin is used to represent both array elements and casts.
virtual const llvm::APSInt * getKnownValue(ProgramStateRef state, SVal val)=0
Evaluates a given SVal.