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 const BugType BT{
this,
"Dangerous variable-length array (VLA) declaration"};
39 "Dangerous variable-length array (VLA) declaration",
41 enum VLASize_Kind { VLA_Garbage, VLA_Zero, VLA_Negative, VLA_Overflow };
52 const Expr *SizeE)
const;
70 SVal &ArraySize)
const {
71 assert(VLA &&
"Function should be called with non-null VLA argument.");
85 State = checkVLAIndexSize(
C, State, SizeE);
88 VLASizes.push_back(SizeE);
93 "Array should have at least one variably-modified dimension.");
108 if (
const llvm::APSInt *KV = SVB.
getKnownValue(State, ArrSize))
109 KnownSize = KV->getZExtValue();
111 for (
const Expr *SizeE : VLASizes) {
118 if (
auto MulNonLoc =
Mul.getAs<
NonLoc>())
119 ArrSize = *MulNonLoc;
124 if (
const llvm::APSInt *IndexLVal = SVB.
getKnownValue(State, IndexLength)) {
128 uint64_t IndexL = IndexLVal->getZExtValue();
135 if (KnownSize <= SizeMax / IndexL) {
139 reportBug(VLA_Overflow, SizeE, State,
C);
154 const Expr *SizeE)
const {
155 SVal SizeV =
C.getSVal(SizeE);
158 reportBug(VLA_Garbage, SizeE, State,
C);
171 std::tie(StateNotZero, StateZero) = State->assume(SizeD);
173 if (StateZero && !StateNotZero) {
174 reportBug(VLA_Zero, SizeE, StateZero,
C);
179 State = StateNotZero;
187 SVal LessThanZeroVal =
190 if (std::optional<DefinedSVal> LessThanZeroDVal =
194 std::tie(StateNeg, StatePos) = CM.
assumeDual(State, *LessThanZeroDVal);
195 if (StateNeg && !StatePos) {
196 reportBug(VLA_Negative, SizeE, State,
C);
203 if ((StateNeg || StateZero) &&
isTainted(State, SizeV)) {
204 reportTaintBug(SizeE, State,
C, SizeV);
219 llvm::raw_svector_ostream os(buf);
220 os <<
"Declared variable-length array (VLA) ";
221 os <<
"has tainted (attacker controlled) size that can be 0 or negative";
223 auto report = std::make_unique<PathSensitiveBugReport>(TaintBT, os.str(), N);
229 report->markInteresting(Sym);
230 C.emitReport(std::move(report));
233void VLASizeChecker::reportBug(VLASize_Kind Kind,
const Expr *SizeE,
241 llvm::raw_svector_ostream os(buf);
242 os <<
"Declared variable-length array (VLA) ";
245 os <<
"uses a garbage value as its size";
248 os <<
"has zero size";
251 os <<
"has negative size";
254 os <<
"has too large size";
258 auto report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
261 C.emitReport(std::move(report));
277 else if (
const auto *TND = dyn_cast<TypedefNameDecl>(DS->
getSingleDecl()))
278 TypeToCheck = TND->getUnderlyingType().getCanonicalType();
290 State = checkVLA(
C, State, VLA, ArraySize);
294 if (!isa<NonLoc>(ArraySize)) {
296 C.addTransition(State);
308 C.addTransition(State);
314 if (UETTE->
getKind() != UETT_SizeOf)
329 State = checkVLA(
C, State, VLA, ArraySize);
333 C.addTransition(State);
340bool 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 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)
The JSON file list parser is used to communicate input to InstallAPI.