23 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/ADT/SmallString.h"
25 #include "llvm/Support/raw_ostream.h"
27 using namespace clang;
31 class VLASizeChecker :
public Checker< check::PreStmt<DeclStmt> > {
32 mutable std::unique_ptr<BugType> BT;
33 enum VLASize_Kind { VLA_Garbage, VLA_Zero, VLA_Tainted, VLA_Negative };
35 void reportBug(VLASize_Kind
Kind,
44 void VLASizeChecker::reportBug(VLASize_Kind
Kind,
55 this,
"Dangerous variable-length array (VLA) declaration"));
58 llvm::raw_svector_ostream os(buf);
59 os <<
"Declared variable-length array (VLA) ";
62 os <<
"uses a garbage value as its size";
65 os <<
"has zero size";
68 os <<
"has tainted size";
71 os <<
"has negative size";
75 auto report = llvm::make_unique<BugReport>(*BT, os.str(), N);
76 report->addRange(SizeE->getSourceRange());
101 reportBug(VLA_Garbage, SE, state, C);
111 if (state->isTainted(sizeV)) {
112 reportBug(VLA_Tainted, SE,
nullptr, C);
120 std::tie(stateNotZero, stateZero) = state->assume(sizeD);
122 if (stateZero && !stateNotZero) {
123 reportBug(VLA_Zero, SE, stateZero, C);
128 state = stateNotZero;
146 std::tie(StateNeg, StatePos) = CM.
assumeDual(state, *LessThanZeroDVal);
147 if (StateNeg && !StatePos) {
148 reportBug(VLA_Negative, SE, state, C);
170 state->getRegion(VD, LC)->getExtent(svalBuilder);
173 svalBuilder.
evalEQ(state, Extent, ArraySize);
174 state = state->assume(sizeIsKnown,
true);
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph). Uses the default CheckerContex...
SVal evalCast(SVal val, QualType castTy, QualType originalType)
Expr * getSizeExpr() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond)
ExplodedNode * generateSink(ProgramStateRef State=nullptr, ExplodedNode *Pred=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a sink node. Generating a sink stops exploration of the given path.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
const ProgramStateRef & getState() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
ConstraintManager & getConstraintManager()
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
bool isSingleDecl() const
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0
const Decl * getSingleDecl() const
ASTContext & getASTContext()
const VariableArrayType * getAsVariableArrayType(QualType T) const
DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal rhs)
bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, bool IsArg=false, bool EnableNullFPSuppression=true)
SValBuilder & getSValBuilder()
QualType getElementType() const
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
const LocationContext * getLocationContext() const