diff --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp --- a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -36,6 +36,7 @@ enum OOB_Kind { OOB_Precedes, OOB_Excedes, OOB_Tainted }; void reportOOB(CheckerContext &C, ProgramStateRef errorState, OOB_Kind kind, + SVal InterestingValue = UndefinedVal(), std::unique_ptr Visitor = nullptr) const; public: @@ -207,6 +208,7 @@ SVal ByteOffset = rawOffset.getByteOffset(); if (isTainted(state, ByteOffset)) { reportOOB(checkerContext, state_exceedsUpperBound, OOB_Tainted, + *upperboundToCheck, std::make_unique(ByteOffset)); return; } @@ -228,7 +230,7 @@ void ArrayBoundCheckerV2::reportOOB( CheckerContext &checkerContext, ProgramStateRef errorState, OOB_Kind kind, - std::unique_ptr Visitor) const { + SVal InterestingValue, std::unique_ptr Visitor) const { ExplodedNode *errorNode = checkerContext.generateErrorNode(errorState); if (!errorNode) @@ -256,6 +258,7 @@ } auto BR = std::make_unique(*BT, os.str(), errorNode); + BR->markInteresting(InterestingValue); BR->addVisitor(std::move(Visitor)); checkerContext.emitReport(std::move(BR)); } diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -60,6 +60,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Lexer.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Checkers/Taint.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Core/Checker.h" @@ -1763,6 +1764,15 @@ // Set the region's extent. State = setDynamicExtent(State, RetVal.getAsRegion(), Size.castAs(), svalBuilder); + if (taint::isTainted(State, Size)) { + const NoteTag *Note = + C.getNoteTag([Size](PathSensitiveBugReport &BR) -> std::string { + if (BR.isInteresting(Size)) + return "Allocating tainted amount of memory"; + return ""; + }); + Pred = C.addTransition(State, Pred, Note); + } return MallocUpdateRefState(C, CE, State, Pred, Family); } diff --git a/clang/test/Analysis/taint-diagnostic-visitor.c b/clang/test/Analysis/taint-diagnostic-visitor.c --- a/clang/test/Analysis/taint-diagnostic-visitor.c +++ b/clang/test/Analysis/taint-diagnostic-visitor.c @@ -4,6 +4,9 @@ int scanf(const char *restrict format, ...); int system(const char *command); +typedef __typeof(sizeof(int)) size_t; +void *malloc(size_t size); +void free(void *ptr); void taintDiagnostic(void) { @@ -34,3 +37,19 @@ int vla[x]; // expected-warning {{Declared variable-length array (VLA) has tainted size}} // expected-note@-1 {{Declared variable-length array (VLA) has tainted size}} } + +void taintDiagnosticMalloc(int conj) { + int x; + scanf("%d", &x); + // expected-note@-1 2 {{Taint originated here}} Once for malloc(tainted), once for BoundsV2. + + int *p = (int *)malloc(x + conj); // Generic taint checker forbids tainted allocation. + // expected-warning@-1 {{Untrusted data is used to specify the buffer size}} + // expected-note@-2 {{Untrusted data is used to specify the buffer size}} + // expected-note@-3 {{Allocating tainted amount of memory}} + + p[1] = 1; // BoundsV2 checker can not prove that the access is safe. + // expected-warning@-1 {{Out of bound memory access (index is tainted)}} + // expected-note@-2 {{Out of bound memory access (index is tainted)}} + free(p); + }