[clang] 52ac71f - [clang][analyzer] Improve StdCLibraryFunctions socket send/recv functions.

Balázs Kéri via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 7 01:45:43 PDT 2023


Author: Balázs Kéri
Date: 2023-08-07T10:45:09+02:00
New Revision: 52ac71f92d38f75df5cb88e9c090ac5fd5a71548

URL: https://github.com/llvm/llvm-project/commit/52ac71f92d38f75df5cb88e9c090ac5fd5a71548
DIFF: https://github.com/llvm/llvm-project/commit/52ac71f92d38f75df5cb88e9c090ac5fd5a71548.diff

LOG: [clang][analyzer] Improve StdCLibraryFunctions socket send/recv functions.

The modeling of send, recv, sendmsg, recvmsg, sendto, recvfrom is changed:
These functions do not return 0, except if the message length is 0.
(In sendmsg, recvmsg the length is not checkable but it is more likely
that a message with 0 length is invalid for these functions.)

Reviewed By: donat.nagy

Differential Revision: https://reviews.llvm.org/D155715

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
    clang/test/Analysis/std-c-library-functions-POSIX.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index d18e6f63df4484..f5f6e3a9123768 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -3096,7 +3096,10 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
     auto Recvfrom =
         Summary(NoEvalCall)
             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                   ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                   ReturnValueCondition(WithinRange, Range(1, Ssize_tMax))},
+                  ErrnoMustNotBeChecked, GenericSuccessMsg)
+            .Case({ReturnValueCondition(WithinRange, SingleValue(0)),
+                   ArgumentCondition(2, WithinRange, SingleValue(0))},
                   ErrnoMustNotBeChecked, GenericSuccessMsg)
             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
@@ -3123,7 +3126,10 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
     auto Sendto =
         Summary(NoEvalCall)
             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                   ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                   ReturnValueCondition(WithinRange, Range(1, Ssize_tMax))},
+                  ErrnoMustNotBeChecked, GenericSuccessMsg)
+            .Case({ReturnValueCondition(WithinRange, SingleValue(0)),
+                   ArgumentCondition(2, WithinRange, SingleValue(0))},
                   ErrnoMustNotBeChecked, GenericSuccessMsg)
             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
@@ -3161,7 +3167,10 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
                   RetType{Ssize_tTy}),
         Summary(NoEvalCall)
             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                   ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                   ReturnValueCondition(WithinRange, Range(1, Ssize_tMax))},
+                  ErrnoMustNotBeChecked, GenericSuccessMsg)
+            .Case({ReturnValueCondition(WithinRange, SingleValue(0)),
+                   ArgumentCondition(2, WithinRange, SingleValue(0))},
                   ErrnoMustNotBeChecked, GenericSuccessMsg)
             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
@@ -3179,7 +3188,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
         Signature(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy},
                   RetType{Ssize_tTy}),
         Summary(NoEvalCall)
-            .Case({ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+            .Case({ReturnValueCondition(WithinRange, Range(1, Ssize_tMax))},
                   ErrnoMustNotBeChecked, GenericSuccessMsg)
             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
             .ArgConstraint(
@@ -3191,7 +3200,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
         Signature(ArgTypes{IntTy, ConstStructMsghdrPtrTy, IntTy},
                   RetType{Ssize_tTy}),
         Summary(NoEvalCall)
-            .Case({ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+            .Case({ReturnValueCondition(WithinRange, Range(1, Ssize_tMax))},
                   ErrnoMustNotBeChecked, GenericSuccessMsg)
             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
             .ArgConstraint(
@@ -3233,7 +3242,10 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
                   RetType{Ssize_tTy}),
         Summary(NoEvalCall)
             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                   ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                   ReturnValueCondition(WithinRange, Range(1, Ssize_tMax))},
+                  ErrnoMustNotBeChecked, GenericSuccessMsg)
+            .Case({ReturnValueCondition(WithinRange, SingleValue(0)),
+                   ArgumentCondition(2, WithinRange, SingleValue(0))},
                   ErrnoMustNotBeChecked, GenericSuccessMsg)
             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant, GenericFailureMsg)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))

diff  --git a/clang/test/Analysis/std-c-library-functions-POSIX.c b/clang/test/Analysis/std-c-library-functions-POSIX.c
index 07cbf0f80fda53..870af4f86c27fb 100644
--- a/clang/test/Analysis/std-c-library-functions-POSIX.c
+++ b/clang/test/Analysis/std-c-library-functions-POSIX.c
@@ -141,6 +141,8 @@
 
 #include "Inputs/std-c-library-functions-POSIX.h"
 
+void clang_analyzer_eval(int);
+
 void test_open(void) {
   open(0, 0); // \
   // expected-warning{{The 1st argument to 'open' is NULL but should not be NULL}}
@@ -150,3 +152,56 @@ void test_open_additional_arg(void) {
   open(0, 0, 0); // \
   // expected-warning{{The 1st argument to 'open' is NULL but should not be NULL}}
 }
+
+void test_recvfrom(int socket, void *restrict buffer, size_t length, int flags,
+                   struct sockaddr *restrict address,
+                   socklen_t *restrict address_len) {
+  ssize_t Ret = recvfrom(socket, buffer, length, flags, address, address_len);
+  if (Ret == 0)
+    clang_analyzer_eval(length == 0); // expected-warning{{TRUE}}
+  if (Ret > 0)
+    clang_analyzer_eval(length > 0); // expected-warning{{TRUE}}
+  if (Ret == -1)
+    clang_analyzer_eval(length == 0); // expected-warning{{UNKNOWN}}
+}
+
+void test_sendto(int socket, const void *message, size_t length, int flags,
+                 const struct sockaddr *dest_addr, socklen_t dest_len) {
+  ssize_t Ret = sendto(socket, message, length, flags, dest_addr, dest_len);
+  if (Ret == 0)
+    clang_analyzer_eval(length == 0); // expected-warning{{TRUE}}
+  if (Ret > 0)
+    clang_analyzer_eval(length > 0); // expected-warning{{TRUE}}
+  if (Ret == -1)
+    clang_analyzer_eval(length == 0); // expected-warning{{UNKNOWN}}
+}
+
+void test_recv(int sockfd, void *buf, size_t len, int flags) {
+  ssize_t Ret = recv(sockfd, buf, len, flags);
+  if (Ret == 0)
+    clang_analyzer_eval(len == 0); // expected-warning{{TRUE}}
+  if (Ret > 0)
+    clang_analyzer_eval(len > 0); // expected-warning{{TRUE}}
+  if (Ret == -1)
+    clang_analyzer_eval(len == 0); // expected-warning{{UNKNOWN}}
+}
+
+void test_send(int sockfd, void *buf, size_t len, int flags) {
+  ssize_t Ret = send(sockfd, buf, len, flags);
+  if (Ret == 0)
+    clang_analyzer_eval(len == 0); // expected-warning{{TRUE}}
+  if (Ret > 0)
+    clang_analyzer_eval(len > 0); // expected-warning{{TRUE}}
+  if (Ret == -1)
+    clang_analyzer_eval(len == 0); // expected-warning{{UNKNOWN}}
+}
+
+void test_recvmsg(int sockfd, struct msghdr *msg, int flags) {
+  ssize_t Ret = recvmsg(sockfd, msg, flags);
+  clang_analyzer_eval(Ret != 0); // expected-warning{{TRUE}}
+}
+
+void test_sendmsg(int sockfd, const struct msghdr *msg, int flags) {
+  ssize_t Ret = sendmsg(sockfd, msg, flags);
+  clang_analyzer_eval(Ret != 0); // expected-warning{{TRUE}}
+}


        


More information about the cfe-commits mailing list