Skip to content

Commit 6002e2f

Browse files
authored
[analyzer] Split TaintPropagation checker into reporting and modeling checkers (#98157)
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.
1 parent deeb936 commit 6002e2f

File tree

4 files changed

+42
-22
lines changed

4 files changed

+42
-22
lines changed

clang/docs/analyzer/checkers.rst

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,17 +1003,14 @@ array new C++ operator is tainted (potentially attacker controlled).
10031003
If an attacker can inject a large value as the size parameter, memory exhaustion
10041004
denial of service attack can be carried out.
10051005
1006-
The ``alpha.security.taint.TaintPropagation`` checker also needs to be enabled for
1007-
this checker to give warnings.
1008-
10091006
The analyzer emits warning only if it cannot prove that the size parameter is
10101007
within reasonable bounds (``<= SIZE_MAX/4``). This functionality partially
10111008
covers the SEI Cert coding standard rule `INT04-C
10121009
<https://wiki.sei.cmu.edu/confluence/display/c/INT04-C.+Enforce+limits+on+integer+values+originating+from+tainted+sources>`_.
10131010
10141011
You can silence this warning either by bound checking the ``size`` parameter, or
10151012
by explicitly marking the ``size`` parameter as sanitized. See the
1016-
:ref:`alpha-security-taint-TaintPropagation` checker for more details.
1013+
:ref:`alpha-security-taint-GenericTaint` checker for an example.
10171014
10181015
.. code-block:: c
10191016
@@ -3011,10 +3008,10 @@ alpha.security.taint
30113008
Checkers implementing
30123009
`taint analysis <https://en.wikipedia.org/wiki/Taint_checking>`_.
30133010
3014-
.. _alpha-security-taint-TaintPropagation:
3011+
.. _alpha-security-taint-GenericTaint:
30153012
3016-
alpha.security.taint.TaintPropagation (C, C++)
3017-
""""""""""""""""""""""""""""""""""""""""""""""
3013+
alpha.security.taint.GenericTaint (C, C++)
3014+
""""""""""""""""""""""""""""""""""""""""""
30183015
30193016
Taint analysis identifies potential security vulnerabilities where the
30203017
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 the ``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: 22 additions & 6 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,9 +392,10 @@ class GenericTaintChecker : public Checker<check::PreCall, check::PostCall> {
391392
bool generateReportIfTainted(const Expr *E, StringRef Msg,
392393
CheckerContext &C) const;
393394

394-
private:
395-
const BugType BT{this, "Use of Untrusted Data", categories::TaintedData};
395+
bool isTaintReporterCheckerEnabled = false;
396+
std::optional<BugType> BT;
396397

398+
private:
397399
bool checkUncontrolledFormatString(const CallEvent &Call,
398400
CheckerContext &C) const;
399401

@@ -1033,20 +1035,23 @@ bool GenericTaintRule::UntrustedEnv(CheckerContext &C) {
10331035
bool GenericTaintChecker::generateReportIfTainted(const Expr *E, StringRef Msg,
10341036
CheckerContext &C) const {
10351037
assert(E);
1038+
if (!isTaintReporterCheckerEnabled)
1039+
return false;
10361040
std::optional<SVal> TaintedSVal =
10371041
getTaintedPointeeOrPointer(C.getState(), C.getSVal(E));
10381042

10391043
if (!TaintedSVal)
10401044
return false;
10411045

10421046
// Generate diagnostic.
1043-
if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
1044-
auto report = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
1047+
assert(BT);
1048+
static CheckerProgramPointTag Tag(BT->getCheckerName(), Msg);
1049+
if (ExplodedNode *N = C.generateNonFatalErrorNode(C.getState(), &Tag)) {
1050+
auto report = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
10451051
report->addRange(E->getSourceRange());
10461052
for (auto TaintedSym : getTaintedSymbols(C.getState(), *TaintedSVal)) {
10471053
report->markInteresting(TaintedSym);
10481054
}
1049-
10501055
C.emitReport(std::move(report));
10511056
return true;
10521057
}
@@ -1122,10 +1127,21 @@ void GenericTaintChecker::taintUnsafeSocketProtocol(const CallEvent &Call,
11221127
}
11231128

11241129
/// Checker registration
1125-
void ento::registerGenericTaintChecker(CheckerManager &Mgr) {
1130+
void ento::registerTaintPropagationChecker(CheckerManager &Mgr) {
11261131
Mgr.registerChecker<GenericTaintChecker>();
11271132
}
11281133

1134+
bool ento::shouldRegisterTaintPropagationChecker(const CheckerManager &mgr) {
1135+
return true;
1136+
}
1137+
1138+
void ento::registerGenericTaintChecker(CheckerManager &Mgr) {
1139+
GenericTaintChecker *checker = Mgr.getChecker<GenericTaintChecker>();
1140+
checker->isTaintReporterCheckerEnabled = true;
1141+
checker->BT.emplace(Mgr.getCurrentCheckerName(), "Use of Untrusted Data",
1142+
categories::TaintedData);
1143+
}
1144+
11291145
bool ento::shouldRegisterGenericTaintChecker(const CheckerManager &mgr) {
11301146
return true;
11311147
}

0 commit comments

Comments
 (0)