aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index ef85d60..1d6f97f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -105,6 +105,11 @@ class StdLibraryFunctionsChecker
/// Get a string representation of an argument index.
/// E.g.: (1) -> '1st arg', (2) - > '2nd arg'
static void printArgDesc(ArgNo, llvm::raw_ostream &Out);
+ /// Print value X of the argument in form " (which is X)",
+ /// if the value is a fixed known value, otherwise print nothing.
+ /// This is used as simple explanation of values if possible.
+ static void printArgValueInfo(ArgNo ArgN, ProgramStateRef State,
+ const CallEvent &Call, llvm::raw_ostream &Out);
/// Append textual description of a numeric range [RMin,RMax] to
/// \p Out.
static void appendInsideRangeDesc(llvm::APSInt RMin, llvm::APSInt RMax,
@@ -435,6 +440,10 @@ class StdLibraryFunctionsChecker
ProgramStateRef State, const Summary &Summary,
llvm::raw_ostream &Out) const override;
+ bool describeArgumentValue(const CallEvent &Call, ProgramStateRef State,
+ const Summary &Summary,
+ llvm::raw_ostream &Out) const override;
+
std::vector<ArgNo> getArgsToTrack() const override {
std::vector<ArgNo> Result{ArgN};
if (SizeArgN)
@@ -870,6 +879,16 @@ void StdLibraryFunctionsChecker::printArgDesc(
Out << " argument";
}
+void StdLibraryFunctionsChecker::printArgValueInfo(ArgNo ArgN,
+ ProgramStateRef State,
+ const CallEvent &Call,
+ llvm::raw_ostream &Out) {
+ if (const llvm::APSInt *Val =
+ State->getStateManager().getSValBuilder().getKnownValue(
+ State, getArgSVal(Call, ArgN)))
+ Out << " (which is " << *Val << ")";
+}
+
void StdLibraryFunctionsChecker::appendInsideRangeDesc(llvm::APSInt RMin,
llvm::APSInt RMax,
QualType ArgT,
@@ -1179,13 +1198,29 @@ void StdLibraryFunctionsChecker::BufferSizeConstraint::describe(
} else if (SizeArgN) {
Out << "the value of the ";
printArgDesc(*SizeArgN, Out);
+ printArgValueInfo(*SizeArgN, State, Call, Out);
if (SizeMultiplierArgN) {
Out << " times the ";
printArgDesc(*SizeMultiplierArgN, Out);
+ printArgValueInfo(*SizeMultiplierArgN, State, Call, Out);
}
}
}
+bool StdLibraryFunctionsChecker::BufferSizeConstraint::describeArgumentValue(
+ const CallEvent &Call, ProgramStateRef State, const Summary &Summary,
+ llvm::raw_ostream &Out) const {
+ SVal BufV = getArgSVal(Call, getArgNo());
+ SVal BufDynSize = getDynamicExtentWithOffset(State, BufV);
+ if (const llvm::APSInt *Val =
+ State->getStateManager().getSValBuilder().getKnownValue(State,
+ BufDynSize)) {
+ Out << "is a buffer with size " << *Val;
+ return true;
+ }
+ return false;
+}
+
void StdLibraryFunctionsChecker::checkPreCall(const CallEvent &Call,
CheckerContext &C) const {
std::optional<Summary> FoundSummary = findFunctionSummary(Call, C);