steakhal updated this revision to Diff 243144.
steakhal added a comment.
- Tests added.
- Clang-format-diff applied.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D74131/new/
https://reviews.llvm.org/D74131
Files:
clang/docs/analyzer/developer-docs/DebugChecks.rst
clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
clang/test/Analysis/debug-exprinspection-istainted.c
Index: clang/test/Analysis/debug-exprinspection-istainted.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/debug-exprinspection-istainted.c
@@ -0,0 +1,19 @@
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-checker=debug.ExprInspection \
+// RUN: -analyzer-checker=alpha.security.taint
+
+int scanf(const char *restrict format, ...);
+void clang_analyzer_isTainted(char);
+void clang_analyzer_isTainted_any_suffix(char);
+
+void foo() {
+ char buf[32] = "";
+ clang_analyzer_isTainted(buf[0]); // expected-warning {{NO}}
+ clang_analyzer_isTainted_any_suffix(buf[0]); // expected-warning {{NO}}
+ scanf("%s", buf);
+ clang_analyzer_isTainted(buf[0]); // expected-warning {{YES}}
+ clang_analyzer_isTainted_any_suffix(buf[0]); // expected-warning {{YES}}
+
+ int tainted_value = buf[0]; // no-warning
+}
Index: clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ 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"
@@ -46,6 +47,7 @@
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;
@@ -73,26 +75,34 @@
// 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;
@@ -412,6 +422,17 @@
reportBug(*Str, C);
}
+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>();
}
Index: clang/docs/analyzer/developer-docs/DebugChecks.rst
===================================================================
--- clang/docs/analyzer/developer-docs/DebugChecks.rst
+++ clang/docs/analyzer/developer-docs/DebugChecks.rst
@@ -275,6 +275,24 @@
See clang_analyzer_denote().
+- ``void clang_analyzer_isTainted(a single argument of any type);``
+
+ Queries the analyzer whether the expression used as argument is tainted or not.
+ This is useful in tests, where we don't want to issue warning for all tainted
+ expressions but only check for certain expressions.
+
+ Example usage::
+
+ int read_integer() {
+ int n;
+ clang_analyzer_isTainted(n); // expected-warning{{NO}}
+ scanf("%d", &n);
+ clang_analyzer_isTainted(n); // expected-warning{{YES}}
+ clang_analyzer_isTainted(n + 2); // expected-warning{{YES}}
+ clang_analyzer_isTainted(n > 0); // expected-warning{{YES}}
+ return n;
+ }
+
Statistics
==========
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits