24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/SmallString.h"
26#include "llvm/Support/raw_ostream.h"
35 :
public Checker<check::PreStmt<DeclStmt>,
36 check::PreStmt<UnaryExprOrTypeTraitExpr>> {
37 mutable std::unique_ptr<BugType> BT;
38 mutable std::unique_ptr<BugType> TaintBT;
39 enum VLASize_Kind { VLA_Garbage, VLA_Zero, VLA_Negative, VLA_Overflow };
50 const Expr *SizeE)
const;
68 SVal &ArraySize)
const {
69 assert(VLA &&
"Function should be called with non-null VLA argument.");
83 State = checkVLAIndexSize(
C, State, SizeE);
86 VLASizes.push_back(SizeE);
91 "Array should have at least one variably-modified dimension.");
106 if (
const llvm::APSInt *KV = SVB.
getKnownValue(State, ArrSize))
107 KnownSize = KV->getZExtValue();
109 for (
const Expr *SizeE : VLASizes) {
116 if (
auto MulNonLoc =
Mul.getAs<
NonLoc>())
117 ArrSize = *MulNonLoc;
122 if (
const llvm::APSInt *IndexLVal = SVB.
getKnownValue(State, IndexLength)) {
126 uint64_t IndexL = IndexLVal->getZExtValue();
133 if (KnownSize <= SizeMax / IndexL) {
137 reportBug(VLA_Overflow, SizeE, State,
C);
152 const Expr *SizeE)
const {
153 SVal SizeV =
C.getSVal(SizeE);
156 reportBug(VLA_Garbage, SizeE, State,
C);
167 reportTaintBug(SizeE, State,
C, SizeV);
175 std::tie(StateNotZero, StateZero) = State->assume(SizeD);
177 if (StateZero && !StateNotZero) {
178 reportBug(VLA_Zero, SizeE, StateZero,
C);
183 State = StateNotZero;
191 SVal LessThanZeroVal =
193 if (std::optional<DefinedSVal> LessThanZeroDVal =
198 std::tie(StateNeg, StatePos) = CM.
assumeDual(State, *LessThanZeroDVal);
199 if (StateNeg && !StatePos) {
200 reportBug(VLA_Negative, SizeE, State,
C);
218 new BugType(
this,
"Dangerous variable-length array (VLA) declaration",
222 llvm::raw_svector_ostream os(buf);
223 os <<
"Declared variable-length array (VLA) ";
224 os <<
"has tainted size";
226 auto report = std::make_unique<PathSensitiveBugReport>(*TaintBT, os.str(), N);
232 report->markInteresting(Sym);
233 C.emitReport(std::move(report));
236void VLASizeChecker::reportBug(VLASize_Kind Kind,
const Expr *SizeE,
245 "Dangerous variable-length array (VLA) declaration",
249 llvm::raw_svector_ostream os(buf);
250 os <<
"Declared variable-length array (VLA) ";
253 os <<
"uses a garbage value as its size";
256 os <<
"has zero size";
259 os <<
"has negative size";
262 os <<
"has too large size";
266 auto report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
269 C.emitReport(std::move(report));
285 else if (
const auto *TND = dyn_cast<TypedefNameDecl>(DS->
getSingleDecl()))
286 TypeToCheck = TND->getUnderlyingType().getCanonicalType();
298 State = checkVLA(
C, State, VLA, ArraySize);
302 if (!isa<NonLoc>(ArraySize)) {
304 C.addTransition(State);
316 C.addTransition(State);
322 if (UETTE->
getKind() != UETT_SizeOf)
337 State = checkVLA(
C, State, VLA, ArraySize);
341 C.addTransition(State);
348bool ento::shouldRegisterVLASizeChecker(
const CheckerManager &mgr) {
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getElementType() const
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
const Decl * getSingleDecl() const
This represents one expression.
A (possibly-)qualified type.
QualType getCanonicalType() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
bool isArgumentType() const
UnaryExprOrTypeTrait getKind() const
Represents a variable declaration or definition.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
const llvm::APSInt & getMaxValue(const llvm::APSInt &v)
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond)
Returns a pair of states (StTrue, StFalse) where the given condition is assumed to be true or false,...
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
virtual const llvm::APSInt * getKnownValue(ProgramStateRef state, SVal val)=0
Evaluates a given SVal.
BasicValueFactory & getBasicValueFactory()
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0
Create a new value which represents a binary expression with two non- location operands.
SVal evalCast(SVal V, QualType CastTy, QualType OriginalTy)
Cast a given SVal to another SVal using given QualType's.
QualType getConditionType() const
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
const char *const LogicError
const char *const TaintedData
std::vector< SymbolRef > getTaintedSymbols(ProgramStateRef State, const Stmt *S, const LocationContext *LCtx, TaintTagType Kind=TaintTagGeneric)
Returns the tainted Symbols for a given Statement and state.
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.
ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR, DefinedOrUnknownSVal Extent, SValBuilder &SVB)
Set the dynamic extent Extent of the region MR.
bool Zero(InterpState &S, CodePtr OpPC)
bool Mul(InterpState &S, CodePtr OpPC)