Author: Balazs Benics Date: 2024-11-15T10:56:04+01:00 New Revision: e5ac9145ba2951b6454b13499f375284bdbde689
URL: https://github.com/llvm/llvm-project/commit/e5ac9145ba2951b6454b13499f375284bdbde689 DIFF: https://github.com/llvm/llvm-project/commit/e5ac9145ba2951b6454b13499f375284bdbde689.diff LOG: [analyzer][taint] Recognize tainted LazyCompoundVals (4/4) (#115919) returned by-value from opaque function calls. If a struct is returned by-value from an opaque call, the "value" of the whole struct is represented by a Conjured symbol. Later fields may slice off smaller subregions by creating Derived symbols of that Conjured symbol, but those are handled well, and "isTainted" returns true as expected. However, passing the whole struct to "isTainted" would be false, because LazyCompoundVals and CompoundVals are not handled. This patch addresses this. Fixes #114270 Split from #114835 Added: Modified: clang/lib/StaticAnalyzer/Checkers/Taint.cpp clang/test/Analysis/taint-generic.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Checkers/Taint.cpp b/clang/lib/StaticAnalyzer/Checkers/Taint.cpp index 0bb5739db4b756..e55d064253b844 100644 --- a/clang/lib/StaticAnalyzer/Checkers/Taint.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/Taint.cpp @@ -207,6 +207,14 @@ std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State, return getTaintedSymbolsImpl(State, Sym, Kind, returnFirstOnly); if (const MemRegion *Reg = V.getAsRegion()) return getTaintedSymbolsImpl(State, Reg, Kind, returnFirstOnly); + + if (auto LCV = V.getAs<nonloc::LazyCompoundVal>()) { + StoreManager &StoreMgr = State->getStateManager().getStoreManager(); + if (auto DefaultVal = StoreMgr.getDefaultBinding(*LCV)) { + return getTaintedSymbolsImpl(State, *DefaultVal, Kind, returnFirstOnly); + } + } + return {}; } diff --git a/clang/test/Analysis/taint-generic.cpp b/clang/test/Analysis/taint-generic.cpp index 8092ac6f270b2a..881c5baf889f6c 100644 --- a/clang/test/Analysis/taint-generic.cpp +++ b/clang/test/Analysis/taint-generic.cpp @@ -1,10 +1,15 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=optin.taint,core,alpha.security.ArrayBoundV2 -analyzer-config optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify -std=c++11 %s +// RUN: %clang_analyze_cc1 -std=c++11 -Wno-format-security \ +// RUN: -analyzer-checker=core,optin.taint,alpha.security.ArrayBoundV2,debug.ExprInspection \ +// RUN: -analyzer-config optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml \ +// RUN: -verify %s + +template <typename T> void clang_analyzer_isTainted(T); #define BUFSIZE 10 int Buffer[BUFSIZE]; int scanf(const char*, ...); -int mySource1(); +template <typename T = int> T mySource1(); int mySource3(); typedef struct _FILE FILE; @@ -136,3 +141,23 @@ void testReadingFromStdin(char **p) { fscanf(stdin, "%d", &n); Buffer[n] = 1; // expected-warning {{Potential out of bound access }} } + +namespace gh114270 { +class Empty {}; +class Aggr { +public: + int data; +}; + +void top() { + int Int = mySource1<int>(); + clang_analyzer_isTainted(Int); // expected-warning {{YES}} + + Empty E = mySource1<Empty>(); + clang_analyzer_isTainted(E); // expected-warning {{YES}} + + Aggr A = mySource1<Aggr>(); + clang_analyzer_isTainted(A); // expected-warning {{YES}} + clang_analyzer_isTainted(A.data); // expected-warning {{YES}} +} +} // namespace gh114270 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits