Skip to content

Commit 6012cad

Browse files
committed
[clang][analyzer] Display buffer sizes in StdCLibraryFunctionArgs checker
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. Reviewed By: Szelethus Differential Revision: https://reviews.llvm.org/D149321
1 parent 11081a6 commit 6012cad

File tree

4 files changed

+54
-19
lines changed

4 files changed

+54
-19
lines changed

clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ class StdLibraryFunctionsChecker
105105
/// Get a string representation of an argument index.
106106
/// E.g.: (1) -> '1st arg', (2) - > '2nd arg'
107107
static void printArgDesc(ArgNo, llvm::raw_ostream &Out);
108+
/// Print value X of the argument in form " (which is X)",
109+
/// if the value is a fixed known value, otherwise print nothing.
110+
/// This is used as simple explanation of values if possible.
111+
static void printArgValueInfo(ArgNo ArgN, ProgramStateRef State,
112+
const CallEvent &Call, llvm::raw_ostream &Out);
108113
/// Append textual description of a numeric range [RMin,RMax] to
109114
/// \p Out.
110115
static void appendInsideRangeDesc(llvm::APSInt RMin, llvm::APSInt RMax,
@@ -435,6 +440,10 @@ class StdLibraryFunctionsChecker
435440
ProgramStateRef State, const Summary &Summary,
436441
llvm::raw_ostream &Out) const override;
437442

443+
bool describeArgumentValue(const CallEvent &Call, ProgramStateRef State,
444+
const Summary &Summary,
445+
llvm::raw_ostream &Out) const override;
446+
438447
std::vector<ArgNo> getArgsToTrack() const override {
439448
std::vector<ArgNo> Result{ArgN};
440449
if (SizeArgN)
@@ -870,6 +879,16 @@ void StdLibraryFunctionsChecker::printArgDesc(
870879
Out << " argument";
871880
}
872881

882+
void StdLibraryFunctionsChecker::printArgValueInfo(ArgNo ArgN,
883+
ProgramStateRef State,
884+
const CallEvent &Call,
885+
llvm::raw_ostream &Out) {
886+
if (const llvm::APSInt *Val =
887+
State->getStateManager().getSValBuilder().getKnownValue(
888+
State, getArgSVal(Call, ArgN)))
889+
Out << " (which is " << *Val << ")";
890+
}
891+
873892
void StdLibraryFunctionsChecker::appendInsideRangeDesc(llvm::APSInt RMin,
874893
llvm::APSInt RMax,
875894
QualType ArgT,
@@ -1179,13 +1198,29 @@ void StdLibraryFunctionsChecker::BufferSizeConstraint::describe(
11791198
} else if (SizeArgN) {
11801199
Out << "the value of the ";
11811200
printArgDesc(*SizeArgN, Out);
1201+
printArgValueInfo(*SizeArgN, State, Call, Out);
11821202
if (SizeMultiplierArgN) {
11831203
Out << " times the ";
11841204
printArgDesc(*SizeMultiplierArgN, Out);
1205+
printArgValueInfo(*SizeMultiplierArgN, State, Call, Out);
11851206
}
11861207
}
11871208
}
11881209

1210+
bool StdLibraryFunctionsChecker::BufferSizeConstraint::describeArgumentValue(
1211+
const CallEvent &Call, ProgramStateRef State, const Summary &Summary,
1212+
llvm::raw_ostream &Out) const {
1213+
SVal BufV = getArgSVal(Call, getArgNo());
1214+
SVal BufDynSize = getDynamicExtentWithOffset(State, BufV);
1215+
if (const llvm::APSInt *Val =
1216+
State->getStateManager().getSValBuilder().getKnownValue(State,
1217+
BufDynSize)) {
1218+
Out << "is a buffer with size " << *Val;
1219+
return true;
1220+
}
1221+
return false;
1222+
}
1223+
11891224
void StdLibraryFunctionsChecker::checkPreCall(const CallEvent &Call,
11901225
CheckerContext &C) const {
11911226
std::optional<Summary> FoundSummary = findFunctionSummary(Call, C);

clang/test/Analysis/std-c-library-functions-arg-constraints-notes.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,19 @@ void test_buffer_size(int x) {
2828
case 1: {
2929
char buf[9];
3030
__buf_size_arg_constraint_concrete(buf); // \
31-
// 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 [}}
31+
// 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 [}}
3232
break;
3333
}
3434
case 2: {
3535
char buf[3];
3636
__buf_size_arg_constraint(buf, 4); // \
37-
// 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}}
37+
// 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 (which is 4) [}}
3838
break;
3939
}
4040
case 3: {
4141
char buf[3];
4242
__buf_size_arg_constraint_mul(buf, 4, 2); // \
43-
// 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}}
43+
// 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 (which is 4) times the 3rd argument (which is 2) [}}
4444
break;
4545
}
4646
}

clang/test/Analysis/std-c-library-functions-arg-constraints-tracking-notes.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ void test_buf_size_concrete(void) {
1616
char buf[3]; // bugpath-note{{'buf' initialized here}}
1717
int s = 4; // bugpath-note{{'s' initialized to 4}}
1818
__buf_size_arg_constraint(buf, s); // \
19-
// 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}} \
20-
// 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}}
19+
// 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}} \
20+
// 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}}
2121
}
2222

2323
int __buf_size_arg_constraint_mul(const void *, size_t, size_t);
@@ -26,6 +26,6 @@ void test_buf_size_concrete_with_multiplication(void) {
2626
int s1 = 4; // bugpath-note{{'s1' initialized to 4}}
2727
int s2 = sizeof(short); // bugpath-note{{'s2' initialized to}}
2828
__buf_size_arg_constraint_mul(buf, s1, s2); // \
29-
// 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}} \
30-
// 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}}
29+
// 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 (which is 4) times the 3rd argument (which is 2)}} \
30+
// 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 (which is 4) times the 3rd argument (which is 2)}}
3131
}

clang/test/Analysis/std-c-library-functions-arg-constraints.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,9 @@ void ARR38_C_F(FILE *file) {
210210
// The 3rd parameter should be the number of elements to read, not
211211
// the size in bytes.
212212
fread(wbuf, size, nitems, file); // \
213-
// 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}} \
214-
// 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}} \
215-
// 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}}
213+
// 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 (which is 4) times the 3rd argument (which is 4096)}} \
214+
// 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 (which is 4) times the 3rd argument (which is 4096)}} \
215+
// 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 (which is 4) times the 3rd argument (which is 4096)}}
216216
}
217217

218218
int __two_constrained_args(int, int);
@@ -254,9 +254,9 @@ int __buf_size_arg_constraint(const void *, size_t);
254254
void test_buf_size_concrete(void) {
255255
char buf[3]; // bugpath-note{{'buf' initialized here}}
256256
__buf_size_arg_constraint(buf, 4); // \
257-
// 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}} \
258-
// 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}} \
259-
// 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}}
257+
// 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 (which is 4)}} \
258+
// 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 (which is 4)}} \
259+
// 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 (which is 4)}}
260260
}
261261
void test_buf_size_symbolic(int s) {
262262
char buf[3];
@@ -281,9 +281,9 @@ int __buf_size_arg_constraint_mul(const void *, size_t, size_t);
281281
void test_buf_size_concrete_with_multiplication(void) {
282282
short buf[3]; // bugpath-note{{'buf' initialized here}}
283283
__buf_size_arg_constraint_mul(buf, 4, sizeof(short)); // \
284-
// 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}} \
285-
// 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}} \
286-
// 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}}
284+
// 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 (which is 4) times the 3rd argument (which is 2)}} \
285+
// 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 (which is 4) times the 3rd argument (which is 2)}} \
286+
// 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 (which is 4) times the 3rd argument (which is 2)}}
287287
}
288288
void test_buf_size_symbolic_with_multiplication(size_t s) {
289289
short buf[3];
@@ -307,9 +307,9 @@ int __buf_size_arg_constraint_concrete(const void *);
307307
void test_min_buf_size(void) {
308308
char buf[9];// bugpath-note{{'buf' initialized here}}
309309
__buf_size_arg_constraint_concrete(buf); // \
310-
// 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}} \
311-
// 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}} \
312-
// 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}}
310+
// 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}} \
311+
// 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}} \
312+
// 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}}
313313
}
314314

315315
void test_file_fd_at_functions() {

0 commit comments

Comments
 (0)