diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp | 103 |
1 files changed, 68 insertions, 35 deletions
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp index 53810ee..bf7ba18 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp @@ -12,18 +12,20 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/Basic/TargetInfo.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/AST/StmtVisitor.h" -#include "llvm/Support/raw_ostream.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; using namespace ento; static bool isArc4RandomAvailable(const ASTContext &Ctx) { - const llvm::Triple &T = Ctx.Target.getTriple(); + const llvm::Triple &T = Ctx.getTargetInfo().getTriple(); return T.getVendor() == llvm::Triple::Apple || T.getOS() == llvm::Triple::FreeBSD || T.getOS() == llvm::Triple::NetBSD || @@ -34,14 +36,16 @@ static bool isArc4RandomAvailable(const ASTContext &Ctx) { namespace { class WalkAST : public StmtVisitor<WalkAST> { BugReporter &BR; + AnalysisContext* AC; enum { num_setids = 6 }; IdentifierInfo *II_setid[num_setids]; const bool CheckRand; public: - WalkAST(BugReporter &br) : BR(br), II_setid(), - CheckRand(isArc4RandomAvailable(BR.getContext())) {} + WalkAST(BugReporter &br, AnalysisContext* ac) + : BR(br), AC(ac), II_setid(), + CheckRand(isArc4RandomAvailable(BR.getContext())) {} // Statement visitor methods. void VisitCallExpr(CallExpr *CE); @@ -52,7 +56,6 @@ public: void VisitChildren(Stmt *S); // Helpers. - IdentifierInfo *getIdentifier(IdentifierInfo *& II, const char *str); bool checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD); typedef void (WalkAST::*FnCheck)(const CallExpr *, @@ -67,22 +70,12 @@ public: void checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD); void checkCall_rand(const CallExpr *CE, const FunctionDecl *FD); void checkCall_random(const CallExpr *CE, const FunctionDecl *FD); + void checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD); void checkUncheckedReturnValue(CallExpr *CE); }; } // end anonymous namespace //===----------------------------------------------------------------------===// -// Helper methods. -//===----------------------------------------------------------------------===// - -IdentifierInfo *WalkAST::getIdentifier(IdentifierInfo *& II, const char *str) { - if (!II) - II = &BR.getContext().Idents.get(str); - - return II; -} - -//===----------------------------------------------------------------------===// // AST walking. //===----------------------------------------------------------------------===// @@ -103,7 +96,7 @@ void WalkAST::VisitCallExpr(CallExpr *CE) { IdentifierInfo *II = FD->getIdentifier(); if (!II) // if no identifier, not a simple C function return; - llvm::StringRef Name = II->getName(); + StringRef Name = II->getName(); if (Name.startswith("__builtin_")) Name = Name.substr(10); @@ -124,6 +117,7 @@ void WalkAST::VisitCallExpr(CallExpr *CE) { .Case("rand", &WalkAST::checkCall_rand) .Case("rand_r", &WalkAST::checkCall_rand) .Case("random", &WalkAST::checkCall_random) + .Case("vfork", &WalkAST::checkCall_vfork) .Default(NULL); // If the callee isn't defined, it is not of security concern. @@ -247,7 +241,7 @@ void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) { // referenced the compared variable. const DeclRefExpr *drCond = vdLHS == drInc->getDecl() ? drLHS : drRHS; - llvm::SmallVector<SourceRange, 2> ranges; + SmallVector<SourceRange, 2> ranges; llvm::SmallString<256> sbuf; llvm::raw_svector_ostream os(sbuf); @@ -259,8 +253,11 @@ void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) { ranges.push_back(drInc->getSourceRange()); const char *bugType = "Floating point variable used as loop counter"; + + PathDiagnosticLocation FSLoc = + PathDiagnosticLocation::createBegin(FS, BR.getSourceManager(), AC); BR.EmitBasicReport(bugType, "Security", os.str(), - FS->getLocStart(), ranges.data(), ranges.size()); + FSLoc, ranges.data(), ranges.size()); } //===----------------------------------------------------------------------===// @@ -290,11 +287,13 @@ void WalkAST::checkCall_gets(const CallExpr *CE, const FunctionDecl *FD) { // Issue a warning. SourceRange R = CE->getCallee()->getSourceRange(); + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); BR.EmitBasicReport("Potential buffer overflow in call to 'gets'", "Security", "Call to function 'gets' is extremely insecure as it can " "always result in a buffer overflow", - CE->getLocStart(), &R, 1); + CELoc, &R, 1); } //===----------------------------------------------------------------------===// @@ -326,11 +325,13 @@ void WalkAST::checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD) { // Issue a warning. SourceRange R = CE->getCallee()->getSourceRange(); + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); BR.EmitBasicReport("Potential buffer overflow in call to 'getpw'", "Security", "The getpw() function is dangerous as it may overflow the " "provided buffer. It is obsoleted by getpwuid().", - CE->getLocStart(), &R, 1); + CELoc, &R, 1); } //===----------------------------------------------------------------------===// @@ -359,11 +360,13 @@ void WalkAST::checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) { // Issue a waring. SourceRange R = CE->getCallee()->getSourceRange(); + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); BR.EmitBasicReport("Potential insecure temporary file in call 'mktemp'", "Security", "Call to function 'mktemp' is insecure as it always " "creates or uses insecure temporary file. Use 'mkstemp' instead", - CE->getLocStart(), &R, 1); + CELoc, &R, 1); } //===----------------------------------------------------------------------===// @@ -378,6 +381,8 @@ void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) { // Issue a warning. SourceRange R = CE->getCallee()->getSourceRange(); + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); BR.EmitBasicReport("Potential insecure memory buffer bounds restriction in " "call 'strcpy'", "Security", @@ -385,7 +390,7 @@ void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) { "provide bounding of the memory buffer. Replace " "unbounded copy functions with analogous functions that " "support length arguments such as 'strncpy'. CWE-119.", - CE->getLocStart(), &R, 1); + CELoc, &R, 1); } //===----------------------------------------------------------------------===// @@ -400,6 +405,8 @@ void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) { // Issue a warning. SourceRange R = CE->getCallee()->getSourceRange(); + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); BR.EmitBasicReport("Potential insecure memory buffer bounds restriction in " "call 'strcat'", "Security", @@ -407,7 +414,7 @@ void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) { "provide bounding of the memory buffer. Replace " "unbounded copy functions with analogous functions that " "support length arguments such as 'strncat'. CWE-119.", - CE->getLocStart(), &R, 1); + CELoc, &R, 1); } //===----------------------------------------------------------------------===// @@ -470,16 +477,18 @@ void WalkAST::checkCall_rand(const CallExpr *CE, const FunctionDecl *FD) { // Issue a warning. llvm::SmallString<256> buf1; llvm::raw_svector_ostream os1(buf1); - os1 << '\'' << FD << "' is a poor random number generator"; + os1 << '\'' << *FD << "' is a poor random number generator"; llvm::SmallString<256> buf2; llvm::raw_svector_ostream os2(buf2); - os2 << "Function '" << FD + os2 << "Function '" << *FD << "' is obsolete because it implements a poor random number generator." << " Use 'arc4random' instead"; SourceRange R = CE->getCallee()->getSourceRange(); - BR.EmitBasicReport(os1.str(), "Security", os2.str(),CE->getLocStart(), &R, 1); + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); + BR.EmitBasicReport(os1.str(), "Security", os2.str(), CELoc, &R, 1); } //===----------------------------------------------------------------------===// @@ -502,11 +511,33 @@ void WalkAST::checkCall_random(const CallExpr *CE, const FunctionDecl *FD) { // Issue a warning. SourceRange R = CE->getCallee()->getSourceRange(); + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); BR.EmitBasicReport("'random' is not a secure random number generator", "Security", "The 'random' function produces a sequence of values that " "an adversary may be able to predict. Use 'arc4random' " - "instead", CE->getLocStart(), &R, 1); + "instead", CELoc, &R, 1); +} + +//===----------------------------------------------------------------------===// +// Check: 'vfork' should not be used. +// POS33-C: Do not use vfork(). +//===----------------------------------------------------------------------===// + +void WalkAST::checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD) { + // All calls to vfork() are insecure, issue a warning. + SourceRange R = CE->getCallee()->getSourceRange(); + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); + BR.EmitBasicReport("Potential insecure implementation-specific behavior in " + "call 'vfork'", + "Security", + "Call to function 'vfork' is insecure as it can lead to " + "denial of service situations in the parent process. " + "Replace calls to vfork with calls to the safer " + "'posix_spawn' function", + CELoc, &R, 1); } //===----------------------------------------------------------------------===// @@ -557,16 +588,18 @@ void WalkAST::checkUncheckedReturnValue(CallExpr *CE) { // Issue a warning. llvm::SmallString<256> buf1; llvm::raw_svector_ostream os1(buf1); - os1 << "Return value is not checked in call to '" << FD << '\''; + os1 << "Return value is not checked in call to '" << *FD << '\''; llvm::SmallString<256> buf2; llvm::raw_svector_ostream os2(buf2); - os2 << "The return value from the call to '" << FD - << "' is not checked. If an error occurs in '" << FD + os2 << "The return value from the call to '" << *FD + << "' is not checked. If an error occurs in '" << *FD << "', the following code may execute with unexpected privileges"; SourceRange R = CE->getCallee()->getSourceRange(); - BR.EmitBasicReport(os1.str(), "Security", os2.str(),CE->getLocStart(), &R, 1); + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC); + BR.EmitBasicReport(os1.str(), "Security", os2.str(), CELoc, &R, 1); } //===----------------------------------------------------------------------===// @@ -578,7 +611,7 @@ class SecuritySyntaxChecker : public Checker<check::ASTCodeBody> { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR) const { - WalkAST walker(BR); + WalkAST walker(BR, mgr.getAnalysisContext(D)); walker.Visit(D->getBody()); } }; |