aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp95
1 files changed, 64 insertions, 31 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 17c813962a23..4225d890c47a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
+#include "Taint.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Checkers/SValExplainer.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -13,6 +14,7 @@
#include "clang/StaticAnalyzer/Core/IssueHash.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -45,13 +47,17 @@ class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols,
void analyzerHashDump(const CallExpr *CE, CheckerContext &C) const;
void analyzerDenote(const CallExpr *CE, CheckerContext &C) const;
void analyzerExpress(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerIsTainted(const CallExpr *CE, CheckerContext &C) const;
typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
CheckerContext &C) const;
- ExplodedNode *reportBug(llvm::StringRef Msg, CheckerContext &C) const;
+ // Optional parameter `ExprVal` for expression value to be marked interesting.
+ ExplodedNode *reportBug(llvm::StringRef Msg, CheckerContext &C,
+ Optional<SVal> ExprVal = None) const;
ExplodedNode *reportBug(llvm::StringRef Msg, BugReporter &BR,
- ExplodedNode *N) const;
+ ExplodedNode *N,
+ Optional<SVal> ExprVal = None) const;
public:
bool evalCall(const CallEvent &Call, CheckerContext &C) const;
@@ -72,26 +78,34 @@ bool ExprInspectionChecker::evalCall(const CallEvent &Call,
// These checks should have no effect on the surrounding environment
// (globals should not be invalidated, etc), hence the use of evalCall.
- FnCheck Handler = llvm::StringSwitch<FnCheck>(C.getCalleeName(CE))
- .Case("clang_analyzer_eval", &ExprInspectionChecker::analyzerEval)
- .Case("clang_analyzer_checkInlined",
- &ExprInspectionChecker::analyzerCheckInlined)
- .Case("clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash)
- .Case("clang_analyzer_warnIfReached",
- &ExprInspectionChecker::analyzerWarnIfReached)
- .Case("clang_analyzer_warnOnDeadSymbol",
- &ExprInspectionChecker::analyzerWarnOnDeadSymbol)
- .StartsWith("clang_analyzer_explain", &ExprInspectionChecker::analyzerExplain)
- .StartsWith("clang_analyzer_dump", &ExprInspectionChecker::analyzerDump)
- .Case("clang_analyzer_getExtent", &ExprInspectionChecker::analyzerGetExtent)
- .Case("clang_analyzer_printState",
- &ExprInspectionChecker::analyzerPrintState)
- .Case("clang_analyzer_numTimesReached",
- &ExprInspectionChecker::analyzerNumTimesReached)
- .Case("clang_analyzer_hashDump", &ExprInspectionChecker::analyzerHashDump)
- .Case("clang_analyzer_denote", &ExprInspectionChecker::analyzerDenote)
- .Case("clang_analyzer_express", &ExprInspectionChecker::analyzerExpress)
- .Default(nullptr);
+ FnCheck Handler =
+ llvm::StringSwitch<FnCheck>(C.getCalleeName(CE))
+ .Case("clang_analyzer_eval", &ExprInspectionChecker::analyzerEval)
+ .Case("clang_analyzer_checkInlined",
+ &ExprInspectionChecker::analyzerCheckInlined)
+ .Case("clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash)
+ .Case("clang_analyzer_warnIfReached",
+ &ExprInspectionChecker::analyzerWarnIfReached)
+ .Case("clang_analyzer_warnOnDeadSymbol",
+ &ExprInspectionChecker::analyzerWarnOnDeadSymbol)
+ .StartsWith("clang_analyzer_explain",
+ &ExprInspectionChecker::analyzerExplain)
+ .StartsWith("clang_analyzer_dump",
+ &ExprInspectionChecker::analyzerDump)
+ .Case("clang_analyzer_getExtent",
+ &ExprInspectionChecker::analyzerGetExtent)
+ .Case("clang_analyzer_printState",
+ &ExprInspectionChecker::analyzerPrintState)
+ .Case("clang_analyzer_numTimesReached",
+ &ExprInspectionChecker::analyzerNumTimesReached)
+ .Case("clang_analyzer_hashDump",
+ &ExprInspectionChecker::analyzerHashDump)
+ .Case("clang_analyzer_denote", &ExprInspectionChecker::analyzerDenote)
+ .Case("clang_analyzer_express",
+ &ExprInspectionChecker::analyzerExpress)
+ .StartsWith("clang_analyzer_isTainted",
+ &ExprInspectionChecker::analyzerIsTainted)
+ .Default(nullptr);
if (!Handler)
return false;
@@ -133,22 +147,28 @@ static const char *getArgumentValueString(const CallExpr *CE,
}
ExplodedNode *ExprInspectionChecker::reportBug(llvm::StringRef Msg,
- CheckerContext &C) const {
+ CheckerContext &C,
+ Optional<SVal> ExprVal) const {
ExplodedNode *N = C.generateNonFatalErrorNode();
- reportBug(Msg, C.getBugReporter(), N);
+ reportBug(Msg, C.getBugReporter(), N, ExprVal);
return N;
}
ExplodedNode *ExprInspectionChecker::reportBug(llvm::StringRef Msg,
BugReporter &BR,
- ExplodedNode *N) const {
+ ExplodedNode *N,
+ Optional<SVal> ExprVal) const {
if (!N)
return nullptr;
if (!BT)
BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
- BR.emitReport(std::make_unique<PathSensitiveBugReport>(*BT, Msg, N));
+ auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
+ if (ExprVal) {
+ R->markInteresting(*ExprVal);
+ }
+ BR.emitReport(std::move(R));
return N;
}
@@ -234,8 +254,9 @@ void ExprInspectionChecker::analyzerGetExtent(const CallExpr *CE,
}
ProgramStateRef State = C.getState();
- State = State->BindExpr(CE, C.getLocationContext(),
- MR->getExtent(C.getSValBuilder()));
+ DefinedOrUnknownSVal Size = getDynamicSize(State, MR, C.getSValBuilder());
+
+ State = State->BindExpr(CE, C.getLocationContext(), Size);
C.addTransition(State);
}
@@ -394,7 +415,8 @@ void ExprInspectionChecker::analyzerExpress(const CallExpr *CE,
return;
}
- SymbolRef Sym = C.getSVal(CE->getArg(0)).getAsSymbol();
+ SVal ArgVal = C.getSVal(CE->getArg(0));
+ SymbolRef Sym = ArgVal.getAsSymbol();
if (!Sym) {
reportBug("Not a symbol", C);
return;
@@ -407,13 +429,24 @@ void ExprInspectionChecker::analyzerExpress(const CallExpr *CE,
return;
}
- reportBug(*Str, C);
+ reportBug(*Str, C, ArgVal);
+}
+
+void ExprInspectionChecker::analyzerIsTainted(const CallExpr *CE,
+ CheckerContext &C) const {
+ if (CE->getNumArgs() != 1) {
+ reportBug("clang_analyzer_isTainted() requires exactly one argument", C);
+ return;
+ }
+ const bool IsTainted =
+ taint::isTainted(C.getState(), CE->getArg(0), C.getLocationContext());
+ reportBug(IsTainted ? "YES" : "NO", C);
}
void ento::registerExprInspectionChecker(CheckerManager &Mgr) {
Mgr.registerChecker<ExprInspectionChecker>();
}
-bool ento::shouldRegisterExprInspectionChecker(const LangOptions &LO) {
+bool ento::shouldRegisterExprInspectionChecker(const CheckerManager &mgr) {
return true;
}