-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[StaticAnalyzer] Relax the pre-condition of 'setsockopt' #130683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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)
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-static-analyzer-1 Author: Ziqing Luo (ziqingluo-90) ChangesFor the unix function 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) Full diff: https://github.com/llvm/llvm-project/pull/130683.diff 2 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 356d63e3e8b80..fef19b4547555 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 b53f3132b8687..f6d88e6c1502d 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}}
+}
|
|
CC @dtarditi |
|
While the change is straightforward, I'd like to discuss about the following two constraints:
In general, how is the negation of a constraint used? Will |
Xazax-hun
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
|
This change looks good to me. I think you could open PRs for the questions you brought up and we could sort them out in the review process. |
steakhal
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the fix. Your raised points also make sense to me.
|
Thanks for reviewing! I will create another PR for my questions. |
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)