[clang][analyzer]Fix non-effective taint sanitation

There was a bug in alpha.security.taint.TaintPropagation checker
in Clang Static Analyzer.
Taint filtering could only sanitize const arguments.
After this patch, taint filtering is effective also
on non-const parameters.

Differential Revision: https://reviews.llvm.org/D155848
This commit is contained in:
Daniel Krupp
2023-07-19 14:01:53 +02:00
parent 2021910606
commit 26b19a67e5
3 changed files with 29 additions and 3 deletions

View File

@@ -926,7 +926,9 @@ void GenericTaintRule::process(const GenericTaintChecker &Checker,
});
/// Check for taint propagation sources.
/// A rule is relevant if PropSrcArgs is empty, or if any of its signified
/// A rule will make the destination variables tainted if PropSrcArgs
/// is empty (taints the destination
/// arguments unconditionally), or if any of its signified
/// args are tainted in context of the current CallEvent.
bool IsMatching = PropSrcArgs.isEmpty();
std::vector<SymbolRef> TaintedSymbols;
@@ -949,6 +951,8 @@ void GenericTaintRule::process(const GenericTaintChecker &Checker,
}
});
// Early return for propagation rules which dont match.
// Matching propagations, Sinks and Filters will pass this point.
if (!IsMatching)
return;
@@ -975,10 +979,13 @@ void GenericTaintRule::process(const GenericTaintChecker &Checker,
Result = F.add(Result, I);
}
// Taint property gets lost if the variable is passed as a
// non-const pointer or reference to a function which is
// not inlined. For matching rules we want to preserve the taintedness.
// TODO: We should traverse all reachable memory regions via the
// escaping parameter. Instead of doing that we simply mark only the
// referred memory region as tainted.
if (WouldEscape(V, E->getType())) {
if (WouldEscape(V, E->getType()) && getTaintedPointeeOrPointer(State, V)) {
LLVM_DEBUG(if (!Result.contains(I)) {
llvm::dbgs() << "PreCall<";
Call.dump(llvm::dbgs());

View File

@@ -69,6 +69,11 @@ Filters:
Scope: "myAnotherNamespace::"
Args: [0]
# char *str; // str is tainted
# sanitizeCmd(str) // str is not tainted anymore
- Name: sanitizeCmd
Args: [0]
# A list of sink functions
Sinks:
# int x, y; // x and y are tainted

View File

@@ -1010,7 +1010,8 @@ void mySource2(int*);
void myScanf(const char*, ...);
int myPropagator(int, int*);
int mySnprintf(char*, size_t, const char*, ...);
bool isOutOfRange(const int*);
bool isOutOfRange(const int*); // const filter function
void sanitizeCmd(char*); // non-const filter function
void mySink(int, int, int);
void testConfigurationSources1(void) {
@@ -1044,6 +1045,19 @@ void testConfigurationFilter(void) {
Buffer[x] = 1; // no-warning
}
void testConfigurationFilterNonConst(void) {
char buffer[1000];
myScanf("%s", buffer); // makes buffer tainted
system(buffer); // expected-warning {{Untrusted data is passed to a system call}}
}
void testConfigurationFilterNonConst2(void) {
char buffer[1000];
myScanf("%s", buffer); // makes buffer tainted
sanitizeCmd(buffer); // removes taintedness
system(buffer); // no-warning
}
void testConfigurationSinks(void) {
int x = mySource1();
mySink(x, 1, 2);