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 = std::make_unique<PathSensitiveBugReport>(*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 std::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 ...
bool Zero(InterpState &S, CodePtr OpPC)
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>.