23 #include "llvm/ADT/STLExtras.h" 24 #include "llvm/ADT/SmallString.h" 25 #include "llvm/Support/raw_ostream.h" 27 using namespace clang;
29 using namespace taint;
32 class VLASizeChecker :
public Checker< check::PreStmt<DeclStmt> > {
33 mutable std::unique_ptr<BugType> BT;
34 enum VLASize_Kind { VLA_Garbage, VLA_Zero, VLA_Tainted, VLA_Negative };
38 std::unique_ptr<BugReporterVisitor> Visitor =
nullptr)
const;
41 void checkPreStmt(
const DeclStmt *DS, CheckerContext &C)
const;
45 void VLASizeChecker::reportBug(
47 CheckerContext &C, std::unique_ptr<BugReporterVisitor> Visitor)
const {
49 ExplodedNode *N = C.generateErrorNode(State);
54 BT.reset(
new BuiltinBug(
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->addVisitor(std::move(Visitor));
78 bugreporter::trackExpressionValue(N, SizeE, *report);
79 C.emitReport(std::move(report));
82 void VLASizeChecker::checkPreStmt(
const DeclStmt *DS, CheckerContext &C)
const {
98 SVal sizeV = C.getSVal(SE);
100 if (sizeV.isUndef()) {
101 reportBug(VLA_Garbage, SE, state, C);
107 if (sizeV.isUnknown())
112 reportBug(VLA_Tainted, SE,
nullptr, C,
113 llvm::make_unique<TaintBugVisitor>(sizeV));
118 DefinedSVal sizeD = sizeV.castAs<DefinedSVal>();
121 std::tie(stateNotZero, stateZero) = state->assume(sizeD);
123 if (stateZero && !stateNotZero) {
124 reportBug(VLA_Zero, SE, stateZero, C);
129 state = stateNotZero;
136 SValBuilder &svalBuilder = C.getSValBuilder();
139 DefinedOrUnknownSVal Zero = svalBuilder.makeZeroVal(Ty);
141 SVal LessThanZeroVal = svalBuilder.evalBinOp(state, BO_LT, sizeD, Zero, Ty);
143 LessThanZeroVal.getAs<DefinedSVal>()) {
144 ConstraintManager &CM = C.getConstraintManager();
147 std::tie(StateNeg, StatePos) = CM.assumeDual(state, *LessThanZeroDVal);
148 if (StateNeg && !StatePos) {
149 reportBug(VLA_Negative, SE, state, C);
158 svalBuilder.evalCast(sizeD, SizeTy, SE->
getType()).castAs<NonLoc>();
162 SVal EleSizeVal = svalBuilder.makeIntVal(EleSize.
getQuantity(), SizeTy);
165 SVal ArraySizeVal = svalBuilder.evalBinOpNN(
166 state, BO_Mul, ArrayLength, EleSizeVal.castAs<NonLoc>(), SizeTy);
170 DefinedOrUnknownSVal Extent =
171 state->getRegion(VD, LC)->getExtent(svalBuilder);
172 DefinedOrUnknownSVal ArraySize = ArraySizeVal.castAs<DefinedOrUnknownSVal>();
173 DefinedOrUnknownSVal sizeIsKnown =
174 svalBuilder.evalEQ(state, Extent, ArraySize);
175 state = state->assume(sizeIsKnown,
true);
181 C.addTransition(state);
184 void ento::registerVLASizeChecker(CheckerManager &mgr) {
185 mgr.registerChecker<VLASizeChecker>();
188 bool ento::shouldRegisterVLASizeChecker(
const LangOptions &LO) {
A (possibly-)qualified type.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
QualType getElementType() const
Represents a variable declaration or definition.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
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
CharUnits - This is an opaque type for sizes expressed in character units.
Expr * getSizeExpr() const
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
This represents one expression.
bool isTainted(ProgramStateRef State, const Stmt *S, const LocationContext *LCtx, TaintTagType Kind=TaintTagGeneric)
Check if the statement has a tainted value in the given state.
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Dataflow Directional Tag Classes.
const Decl * getSingleDecl() const
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl. ...
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const VariableArrayType * getAsVariableArrayType(QualType T) const
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
Represents a C array with a specified size that is not an integer-constant-expression.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.