diff options
author | Ziqing Luo <ziqing@udel.edu> | 2025-03-11 10:23:03 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-11 10:23:03 -0700 |
commit | 65016475084f6435dbf252997d53853c2bfdf9be (patch) | |
tree | abad2b1f1ffc57a57cc621e272f0269397fdb0c9 /clang | |
parent | f10a8706a1443dec834929dadcce837082df64b7 (diff) | |
download | llvm-65016475084f6435dbf252997d53853c2bfdf9be.zip llvm-65016475084f6435dbf252997d53853c2bfdf9be.tar.gz llvm-65016475084f6435dbf252997d53853c2bfdf9be.tar.bz2 |
[StaticAnalyzer] Relax the pre-condition of 'setsockopt' (#130683)
For the unix function
`int setsockopt(int, int, int, const void *, socklen_t);`, the last two
parameters represent a buffer and a size.
In case the size is zero, buffer can be null. Previously, the hard-coded
pre-condition requires the buffer to never be null, which can cause
false positives.
(rdar://146678142)
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp | 5 | ||||
-rw-r--r-- | clang/test/Analysis/std-c-library-functions-POSIX.c | 11 |
2 files changed, 14 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 356d63e..fef19b4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -1797,7 +1797,8 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( auto IsNull = [&](ArgNo ArgN) { return std::make_shared<NotNullConstraint>(ArgN, false); }; - auto NotNullBuffer = [&](ArgNo ArgN, ArgNo SizeArg1N, ArgNo SizeArg2N) { + auto NotNullBuffer = [&](ArgNo ArgN, ArgNo SizeArg1N, + std::optional<ArgNo> SizeArg2N = std::nullopt) { return std::make_shared<NotNullBufferConstraint>(ArgN, SizeArg1N, SizeArg2N); }; @@ -3365,7 +3366,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( Summary(NoEvalCall) .Case(ReturnsZero, ErrnoMustNotBeChecked, GenericSuccessMsg) .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg) - .ArgConstraint(NotNull(ArgNo(3))) + .ArgConstraint(NotNullBuffer(ArgNo(3), ArgNo(4))) .ArgConstraint( BufferSize(/*Buffer=*/ArgNo(3), /*BufSize=*/ArgNo(4))) .ArgConstraint( diff --git a/clang/test/Analysis/std-c-library-functions-POSIX.c b/clang/test/Analysis/std-c-library-functions-POSIX.c index b53f313..f6d88e6 100644 --- a/clang/test/Analysis/std-c-library-functions-POSIX.c +++ b/clang/test/Analysis/std-c-library-functions-POSIX.c @@ -237,3 +237,14 @@ void test_readlinkat_bufsize_zero(int fd, char *Buf, size_t Bufsize) { else clang_analyzer_eval(Bufsize == 0); // expected-warning{{UNKNOWN}} } + +void test_setsockopt_bufptr_null(int x) { + char buf[10] = {0}; + + setsockopt(1, 2, 3, 0, 0); + setsockopt(1, 2, 3, buf, 10); + if (x) + setsockopt(1, 2, 3, buf, 11); // expected-warning{{The 4th argument to 'setsockopt' is a buffer with size 10 but should be a buffer with size equal to or greater than the value of the 5th argument (which is 11)}} + else + setsockopt(1, 2, 3, 0, 10); // expected-warning{{The 4th argument to 'setsockopt' is NULL but should not be NULL}} +} |