Skip to content

Commit 7567541

Browse files
committed
[analyzer] Splitting TaintPropagation checker into reporting and modeling checkers
Taint propagation is a a generic modeling feature of the Clang Static Analyzer which many other checkers depend on. Therefore GenericTaintChecker is split into a TaintPropagation modeling checker and a GenericTaint reporting checker. Other checkers, which report taint related warnings, should set the TaintPropagation checker as their dependency.
1 parent 221d5c5 commit 7567541

File tree

4 files changed

+44
-18
lines changed

4 files changed

+44
-18
lines changed

clang/docs/analyzer/checkers.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ covers the SEI Cert coding standard rule `INT04-C
10131013
10141014
You can silence this warning either by bound checking the ``size`` parameter, or
10151015
by explicitly marking the ``size`` parameter as sanitized. See the
1016-
:ref:`alpha-security-taint-TaintPropagation` checker for more details.
1016+
:ref:`alpha-security-taint-GenericTaint` checker for an example.
10171017
10181018
.. code-block:: c
10191019
@@ -3011,10 +3011,10 @@ alpha.security.taint
30113011
Checkers implementing
30123012
`taint analysis <https://en.wikipedia.org/wiki/Taint_checking>`_.
30133013
3014-
.. _alpha-security-taint-TaintPropagation:
3014+
.. _alpha-security-taint-GenericTaint:
30153015
3016-
alpha.security.taint.TaintPropagation (C, C++)
3017-
""""""""""""""""""""""""""""""""""""""""""""""
3016+
alpha.security.taint.GenericTaint (C, C++)
3017+
""""""""""""""""""""""""""""""""""""""""""
30183018
30193019
Taint analysis identifies potential security vulnerabilities where the
30203020
attacker can inject malicious data to the program to execute an attack

clang/docs/analyzer/user-docs/TaintAnalysisConfiguration.rst

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
Taint Analysis Configuration
33
============================
44

5-
The Clang Static Analyzer uses taint analysis to detect security-related issues in code.
6-
The backbone of taint analysis in the Clang SA is the `GenericTaintChecker`, which the user can access via the :ref:`alpha-security-taint-TaintPropagation` checker alias and this checker has a default taint-related configuration.
7-
The built-in default settings are defined in code, and they are always in effect once the checker is enabled, either directly or via the alias.
8-
The checker also provides a configuration interface for extending the default settings by providing a configuration file in `YAML <http://llvm.org/docs/YamlIO.html#introduction-to-yaml>`_ format.
5+
The Clang Static Analyzer uses taint analysis to detect injection vulnerability related issues in code.
6+
The backbone of taint analysis in the Clang SA is the ``TaintPropagation`` modeling checker.
7+
The reports are emitted via the :ref:`alpha-security-taint-GenericTaint` checker.
8+
The ``TaintPropagation`` checker has a default taint-related configuration.
9+
The built-in default settings are defined in code, and they are always in effect.
10+
The checker also provides a configuration interface for extending the default settings via the ``alpha.security.taint.TaintPropagation:Config`` checker config parameter
11+
by providing a configuration file to the in `YAML <http://llvm.org/docs/YamlIO.html#introduction-to-yaml>`_ format.
912
This documentation describes the syntax of the configuration file and gives the informal semantics of the configuration options.
1013

1114
.. contents::
@@ -18,7 +21,7 @@ ________
1821

1922
Taint analysis works by checking for the occurrence of special operations during the symbolic execution of the program.
2023
Taint analysis defines sources, sinks, and propagation rules. It identifies errors by detecting a flow of information that originates from a taint source, reaches a taint sink, and propagates through the program paths via propagation rules.
21-
A source, sink, or an operation that propagates taint is mainly domain-specific knowledge, but there are some built-in defaults provided by :ref:`alpha-security-taint-TaintPropagation`.
24+
A source, sink, or an operation that propagates taint is mainly domain-specific knowledge, but there are some built-in defaults provided by ``TaintPropagation`` checker.
2225
It is possible to express that a statement sanitizes tainted values by providing a ``Filters`` section in the external configuration (see :ref:`clangsa-taint-configuration-example` and :ref:`clangsa-taint-filter-details`).
2326
There are no default filters defined in the built-in settings.
2427
The checker's documentation also specifies how to provide a custom taint configuration with command-line options.

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,7 @@ def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,
10711071

10721072
let ParentPackage = Taint in {
10731073

1074-
def GenericTaintChecker : Checker<"TaintPropagation">,
1074+
def TaintPropagationChecker : Checker<"TaintPropagation">, // Modelling checker
10751075
HelpText<"Generate taint information used by other checkers">,
10761076
CheckerOptions<[
10771077
CmdLineOption<String,
@@ -1080,6 +1080,12 @@ def GenericTaintChecker : Checker<"TaintPropagation">,
10801080
"",
10811081
InAlpha>,
10821082
]>,
1083+
Documentation<NotDocumented>,
1084+
Hidden;
1085+
1086+
def GenericTaintChecker : Checker<"GenericTaint">,
1087+
HelpText<"Reports potential injection vulnerabilities">,
1088+
Dependencies<[TaintPropagationChecker]>,
10831089
Documentation<HasDocumentation>;
10841090

10851091
} // end "alpha.security.taint"
@@ -1717,9 +1723,7 @@ let ParentPackage = TaintOptIn in {
17171723
def TaintedAllocChecker: Checker<"TaintedAlloc">,
17181724
HelpText<"Check for memory allocations, where the size parameter "
17191725
"might be a tainted (attacker controlled) value.">,
1720-
Dependencies<[DynamicMemoryModeling]>,
1721-
//FIXME: GenericTaintChecker should be a dependency, but only after it
1722-
//is transformed into a modeling checker
1726+
Dependencies<[DynamicMemoryModeling, TaintPropagationChecker]>,
17231727
Documentation<HasDocumentation>;
17241728

17251729
} // end "optin.taint"

clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
2828
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
2929
#include "llvm/ADT/StringExtras.h"
30+
#include "llvm/ADT/StringRef.h"
3031
#include "llvm/Support/YAMLTraits.h"
3132

3233
#include <limits>
@@ -391,8 +392,11 @@ class GenericTaintChecker : public Checker<check::PreCall, check::PostCall> {
391392
bool generateReportIfTainted(const Expr *E, StringRef Msg,
392393
CheckerContext &C) const;
393394

395+
bool isTaintReporterCheckerEnabled = false;
396+
CheckerNameRef reporterCheckerName;
397+
394398
private:
395-
const BugType BT{this, "Use of Untrusted Data", categories::TaintedData};
399+
mutable std::unique_ptr<BugType> BT;
396400

397401
bool checkUncontrolledFormatString(const CallEvent &Call,
398402
CheckerContext &C) const;
@@ -1033,20 +1037,25 @@ bool GenericTaintRule::UntrustedEnv(CheckerContext &C) {
10331037
bool GenericTaintChecker::generateReportIfTainted(const Expr *E, StringRef Msg,
10341038
CheckerContext &C) const {
10351039
assert(E);
1040+
if (!isTaintReporterCheckerEnabled)
1041+
return false;
10361042
std::optional<SVal> TaintedSVal =
10371043
getTaintedPointeeOrPointer(C.getState(), C.getSVal(E));
10381044

10391045
if (!TaintedSVal)
10401046
return false;
10411047

10421048
// Generate diagnostic.
1043-
if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
1044-
auto report = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
1049+
if (!BT)
1050+
BT.reset(new BugType(reporterCheckerName, "Use of Untrusted Data",
1051+
categories::TaintedData));
1052+
static CheckerProgramPointTag Tag(reporterCheckerName, Msg);
1053+
if (ExplodedNode *N = C.generateNonFatalErrorNode(C.getState(), &Tag)) {
1054+
auto report = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
10451055
report->addRange(E->getSourceRange());
10461056
for (auto TaintedSym : getTaintedSymbols(C.getState(), *TaintedSVal)) {
10471057
report->markInteresting(TaintedSym);
10481058
}
1049-
10501059
C.emitReport(std::move(report));
10511060
return true;
10521061
}
@@ -1122,10 +1131,20 @@ void GenericTaintChecker::taintUnsafeSocketProtocol(const CallEvent &Call,
11221131
}
11231132

11241133
/// Checker registration
1125-
void ento::registerGenericTaintChecker(CheckerManager &Mgr) {
1134+
void ento::registerTaintPropagationChecker(CheckerManager &Mgr) {
11261135
Mgr.registerChecker<GenericTaintChecker>();
11271136
}
11281137

1138+
bool ento::shouldRegisterTaintPropagationChecker(const CheckerManager &mgr) {
1139+
return true;
1140+
}
1141+
1142+
void ento::registerGenericTaintChecker(CheckerManager &Mgr) {
1143+
GenericTaintChecker *checker = Mgr.getChecker<GenericTaintChecker>();
1144+
checker->isTaintReporterCheckerEnabled = true;
1145+
checker->reporterCheckerName = Mgr.getCurrentCheckerName();
1146+
}
1147+
11291148
bool ento::shouldRegisterGenericTaintChecker(const CheckerManager &mgr) {
11301149
return true;
11311150
}

0 commit comments

Comments
 (0)