balazske created this revision.
Herald added subscribers: steakhal, manas, ASDenysPetrov, martong, gamesh411,
dkrupp, donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet,
baloghadamsoftware, xazax.hun.
Herald added a reviewer: Szelethus.
Herald added a reviewer: NoQ.
Herald added a project: All.
balazske requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
If a wrong (too small) buffer argument is found, the dynamic buffer size and
values of connected arguments are displayed in the warning message, if
these are simple known integer values.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D149321
Files:
clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
clang/test/Analysis/std-c-library-functions-arg-constraints-notes.cpp
clang/test/Analysis/std-c-library-functions-arg-constraints-tracking-notes.c
clang/test/Analysis/std-c-library-functions-arg-constraints.c
Index: clang/test/Analysis/std-c-library-functions-arg-constraints.c
===================================================================
--- clang/test/Analysis/std-c-library-functions-arg-constraints.c
+++ clang/test/Analysis/std-c-library-functions-arg-constraints.c
@@ -210,9 +210,9 @@
// The 3rd parameter should be the number of elements to read, not
// the size in bytes.
fread(wbuf, size, nitems, file); // \
- // report-warning{{The 1st argument to 'fread' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}} \
- // bugpath-warning{{The 1st argument to 'fread' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}} \
- // bugpath-note{{The 1st argument to 'fread' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}}
+ // report-warning{{The 1st argument to 'fread' is a buffer with size 4096 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4) times the 3rd argument (that is 4096)}} \
+ // bugpath-warning{{The 1st argument to 'fread' is a buffer with size 4096 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4) times the 3rd argument (that is 4096)}} \
+ // bugpath-note{{The 1st argument to 'fread' is a buffer with size 4096 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4) times the 3rd argument (that is 4096)}}
}
int __two_constrained_args(int, int);
@@ -254,9 +254,9 @@
void test_buf_size_concrete(void) {
char buf[3]; // bugpath-note{{'buf' initialized here}}
__buf_size_arg_constraint(buf, 4); // \
- // report-warning{{The 1st argument to '__buf_size_arg_constraint' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument}} \
- // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument}} \
- // bugpath-note{{The 1st argument to '__buf_size_arg_constraint' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument}}
+ // report-warning{{The 1st argument to '__buf_size_arg_constraint' is a buffer with size 3 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4)}} \
+ // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint' is a buffer with size 3 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4)}} \
+ // bugpath-note{{The 1st argument to '__buf_size_arg_constraint' is a buffer with size 3 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4)}}
}
void test_buf_size_symbolic(int s) {
char buf[3];
@@ -281,9 +281,9 @@
void test_buf_size_concrete_with_multiplication(void) {
short buf[3]; // bugpath-note{{'buf' initialized here}}
__buf_size_arg_constraint_mul(buf, 4, sizeof(short)); // \
- // report-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}} \
- // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}} \
- // bugpath-note{{The 1st argument to '__buf_size_arg_constraint_mul' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}}
+ // report-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4) times the 3rd argument (that is 2)}} \
+ // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4) times the 3rd argument (that is 2)}} \
+ // bugpath-note{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4) times the 3rd argument (that is 2)}}
}
void test_buf_size_symbolic_with_multiplication(size_t s) {
short buf[3];
@@ -307,9 +307,9 @@
void test_min_buf_size(void) {
char buf[9];// bugpath-note{{'buf' initialized here}}
__buf_size_arg_constraint_concrete(buf); // \
- // report-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' is out of the accepted range; It should be a buffer with size equal to or greater than 10}} \
- // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' is out of the accepted range; It should be a buffer with size equal to or greater than 10}} \
- // bugpath-note{{The 1st argument to '__buf_size_arg_constraint_concrete' is out of the accepted range; It should be a buffer with size equal to or greater than 10}}
+ // report-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' is a buffer with size 9 but should be a buffer with size equal to or greater than 10}} \
+ // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' is a buffer with size 9 but should be a buffer with size equal to or greater than 10}} \
+ // bugpath-note{{The 1st argument to '__buf_size_arg_constraint_concrete' is a buffer with size 9 but should be a buffer with size equal to or greater than 10}}
}
void test_file_fd_at_functions() {
Index: clang/test/Analysis/std-c-library-functions-arg-constraints-tracking-notes.c
===================================================================
--- clang/test/Analysis/std-c-library-functions-arg-constraints-tracking-notes.c
+++ clang/test/Analysis/std-c-library-functions-arg-constraints-tracking-notes.c
@@ -16,8 +16,8 @@
char buf[3]; // bugpath-note{{'buf' initialized here}}
int s = 4; // bugpath-note{{'s' initialized to 4}}
__buf_size_arg_constraint(buf, s); // \
- // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument}} \
- // bugpath-note{{The 1st argument to '__buf_size_arg_constraint' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument}}
+ // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint' is a buffer with size 3 but should be a buffer with size equal to or greater than the value of the 2nd argument}} \
+ // bugpath-note{{The 1st argument to '__buf_size_arg_constraint' is a buffer with size 3 but should be a buffer with size equal to or greater than the value of the 2nd argument}}
}
int __buf_size_arg_constraint_mul(const void *, size_t, size_t);
@@ -26,6 +26,6 @@
int s1 = 4; // bugpath-note{{'s1' initialized to 4}}
int s2 = sizeof(short); // bugpath-note{{'s2' initialized to}}
__buf_size_arg_constraint_mul(buf, s1, s2); // \
- // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}} \
- // bugpath-note{{The 1st argument to '__buf_size_arg_constraint_mul' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}}
+ // bugpath-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4) times the 3rd argument (that is 2)}} \
+ // bugpath-note{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 6 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4) times the 3rd argument (that is 2)}}
}
Index: clang/test/Analysis/std-c-library-functions-arg-constraints-notes.cpp
===================================================================
--- clang/test/Analysis/std-c-library-functions-arg-constraints-notes.cpp
+++ clang/test/Analysis/std-c-library-functions-arg-constraints-notes.cpp
@@ -28,19 +28,19 @@
case 1: {
char buf[9];
__buf_size_arg_constraint_concrete(buf); // \
- // expected-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' is out of the accepted range; It should be a buffer with size equal to or greater than 10 [}}
+ // expected-warning{{The 1st argument to '__buf_size_arg_constraint_concrete' is a buffer with size 9 but should be a buffer with size equal to or greater than 10 [}}
break;
}
case 2: {
char buf[3];
__buf_size_arg_constraint(buf, 4); // \
- // expected-warning{{The 1st argument to '__buf_size_arg_constraint' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument}}
+ // expected-warning{{The 1st argument to '__buf_size_arg_constraint' is a buffer with size 3 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4) [}}
break;
}
case 3: {
char buf[3];
__buf_size_arg_constraint_mul(buf, 4, 2); // \
- // expected-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is out of the accepted range; It should be a buffer with size equal to or greater than the value of the 2nd argument times the 3rd argument}}
+ // expected-warning{{The 1st argument to '__buf_size_arg_constraint_mul' is a buffer with size 3 but should be a buffer with size equal to or greater than the value of the 2nd argument (that is 4) times the 3rd argument (that is 2) [}}
break;
}
}
Index: clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -105,6 +105,11 @@
/// 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 " (that 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 @@
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 @@
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 << " (that is " << *Val << ")";
+}
+
void StdLibraryFunctionsChecker::appendInsideRangeDesc(llvm::APSInt RMin,
llvm::APSInt RMax,
QualType ArgT,
@@ -1179,13 +1198,29 @@
} 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);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits