21 #include "llvm/ADT/Optional.h"
22 #include "llvm/ADT/STLExtras.h"
23 #include "llvm/ADT/SmallString.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/Support/raw_ostream.h"
28 using namespace clang;
32 class UnixAPIChecker :
public Checker< check::PreStmt<CallExpr> > {
33 mutable std::unique_ptr<BugType> BT_open, BT_pthreadOnce, BT_mallocZero;
54 const char *fn_name)
const;
57 const unsigned numArgs,
58 const unsigned sizeArg,
59 const char *fn)
const;
60 void LazyInitialize(std::unique_ptr<BugType> &BT,
const char *name)
const {
84 LazyInitialize(BT_open,
"Improper use of 'open'");
86 auto Report = llvm::make_unique<BugReport>(*BT_open, Msg, N);
102 ReportOpenBug(C, state,
103 "Third argument to 'open' is not an integer",
104 Arg->getSourceRange());
108 ReportOpenBug(C, state,
109 "Call to 'open' with more than three arguments",
110 CE->
getArg(3)->getSourceRange());
116 if (!Val_O_CREAT.hasValue()) {
118 == llvm::Triple::Apple)
119 Val_O_CREAT = 0x0200;
149 std::tie(trueState, falseState) = state->assume(maskedFlags);
153 if (!(trueState && !falseState))
157 ReportOpenBug(C, trueState,
158 "Call to 'open' requires a third argument when "
159 "the 'O_CREAT' flag is set",
160 oflagsEx->getSourceRange());
190 llvm::raw_svector_ostream os(S);
191 os <<
"Call to 'pthread_once' uses";
192 if (
const VarRegion *VR = dyn_cast<VarRegion>(R))
193 os <<
" the local variable '" << VR->getDecl()->getName() <<
'\'';
195 os <<
" stack allocated memory";
196 os <<
" for the \"control\" value. Using such transient memory for "
197 "the control value is potentially dangerous.";
198 if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->
getMemorySpace()))
199 os <<
" Perhaps you intended to declare the variable as 'static'?";
201 LazyInitialize(BT_pthreadOnce,
"Improper use of 'pthread_once'");
203 auto report = llvm::make_unique<BugReport>(*BT_pthreadOnce, os.str(), N);
204 report->addRange(CE->
getArg(0)->getSourceRange());
221 std::tie(*trueState, *falseState) =
224 return (*falseState && !*trueState);
233 const char *fn_name)
const {
238 LazyInitialize(BT_mallocZero,
239 "Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)");
242 llvm::raw_svector_ostream os(S);
243 os <<
"Call to '" << fn_name <<
"' has an allocation size of 0 bytes";
244 auto report = llvm::make_unique<BugReport>(*BT_mallocZero, os.str(), N);
246 report->addRange(arg->getSourceRange());
257 const unsigned numArgs,
258 const unsigned sizeArg,
259 const char *fn)
const {
275 (void) ReportZeroByteAllocation(C, falseState, arg, fn);
280 if (trueState != state)
294 for (i = 0; i < nArgs; i++) {
305 if (ReportZeroByteAllocation(C, falseState, arg,
"calloc"))
316 if (trueState != state)
322 BasicAllocationCheck(C, CE, 1, 0,
"malloc");
327 BasicAllocationCheck(C, CE, 2, 1,
"realloc");
332 BasicAllocationCheck(C, CE, 2, 1,
"reallocf");
337 BasicAllocationCheck(C, CE, 1, 0,
"alloca");
342 BasicAllocationCheck(C, CE, 1, 0,
"valloc");
350 void UnixAPIChecker::checkPreStmt(
const CallExpr *CE,
353 if (!FD || FD->getKind() != Decl::Function)
361 llvm::StringSwitch<SubChecker>(FName)
362 .Case(
"open", &UnixAPIChecker::CheckOpen)
363 .Case(
"pthread_once", &UnixAPIChecker::CheckPthreadOnce)
364 .Case(
"calloc", &UnixAPIChecker::CheckCallocZero)
365 .Case(
"malloc", &UnixAPIChecker::CheckMallocZero)
366 .Case(
"realloc", &UnixAPIChecker::CheckReallocZero)
367 .Case(
"reallocf", &UnixAPIChecker::CheckReallocfZero)
368 .Cases(
"alloca",
"__builtin_alloca", &UnixAPIChecker::CheckAllocaZero)
369 .Case(
"valloc", &UnixAPIChecker::CheckVallocZero)
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
StringRef getCalleeName(const FunctionDecl *FunDecl) const
Get the name of the called function (path-sensitive).
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
const char *const UnixAPI
const MemSpaceRegion * getMemorySpace() const
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
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
const TargetInfo & getTargetInfo() const
bool isUnknownOrUndef() const
Expr - This represents one expression.
const ProgramStateRef & getState() const
static bool IsZeroByteAllocation(ProgramStateRef state, const SVal argVal, ProgramStateRef *trueState, ProgramStateRef *falseState)
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
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.
ASTContext & getASTContext()
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, bool IsArg=false, bool EnableNullFPSuppression=true)
Attempts to add visitors to trace a null or undefined value back to its point of origin, whether it is a symbol constrained to null or an explicit assignment.
SValBuilder & getSValBuilder()
Defines the clang::TargetInfo interface.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A trivial tuple used to represent a source range.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const LocationContext * getLocationContext() const