[clang] Improve modeling of two functions in StdLibraryFunctionsChecker (PR #78079)

Ben Shi via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 16 01:01:27 PST 2024


https://github.com/benshi001 updated https://github.com/llvm/llvm-project/pull/78079

>From fd350eea466db33324f07e59469775e81479b33d Mon Sep 17 00:00:00 2001
From: Ben Shi <bennshi at tencent.com>
Date: Sun, 14 Jan 2024 12:44:45 +0800
Subject: [PATCH 1/2] [clang][analyzer] Improve modeling of two functions in
 StdLibraryFunctionsChecker

Improve 'errno' modeling of 'opendir' and 'fdopendir'.
---
 .../Checkers/StdLibraryFunctionsChecker.cpp   | 19 +++++++++-------
 .../Analysis/Inputs/system-header-simulator.h |  7 +++++-
 clang/test/Analysis/stream-errno.c            | 22 +++++++++++++++++++
 3 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 3b36565681a7f33..2f05dd6997cfad8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -2772,18 +2772,21 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
             .ArgConstraint(NotNull(ArgNo(2))));
 
     // DIR *opendir(const char *name);
-    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "opendir", Signature(ArgTypes{ConstCharPtrTy}, RetType{DirPtrTy}),
-        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
+        Summary(NoEvalCall)
+            .Case({NotNull(Ret)}, ErrnoMustNotBeChecked, GenericSuccessMsg)
+            .Case({IsNull(Ret)}, ErrnoNEZeroIrrelevant, GenericFailureMsg)
+            .ArgConstraint(NotNull(ArgNo(0))));
 
     // DIR *fdopendir(int fd);
-    // FIXME: Improve for errno modeling.
-    addToFunctionSummaryMap("fdopendir",
-                            Signature(ArgTypes{IntTy}, RetType{DirPtrTy}),
-                            Summary(NoEvalCall)
-                                .ArgConstraint(ArgumentCondition(
-                                    0, WithinRange, Range(0, IntMax))));
+    addToFunctionSummaryMap(
+        "fdopendir", Signature(ArgTypes{IntTy}, RetType{DirPtrTy}),
+        Summary(NoEvalCall)
+            .Case({NotNull(Ret)}, ErrnoMustNotBeChecked, GenericSuccessMsg)
+            .Case({IsNull(Ret)}, ErrnoNEZeroIrrelevant, GenericFailureMsg)
+            .ArgConstraint(
+                ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
     // int isatty(int fildes);
     addToFunctionSummaryMap(
diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h b/clang/test/Analysis/Inputs/system-header-simulator.h
index cd7ac616bcc67fa..ba0e09ca77bc2af 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator.h
@@ -14,8 +14,9 @@ typedef long long __int64_t;
 typedef __int64_t __darwin_off_t;
 typedef __darwin_off_t fpos_t;
 typedef int off_t;
-
 typedef struct _FILE FILE;
+typedef struct _DIR DIR;
+
 #define SEEK_SET 0 /* Seek from beginning of file. */
 #define SEEK_CUR 1 /* Seek from current position. */
 #define SEEK_END 2 /* Seek from end of file. */
@@ -68,6 +69,10 @@ int ferror(FILE *stream);
 int fileno(FILE *stream);
 int fflush(FILE *stream);
 
+DIR *opendir(const char *name);
+DIR *fdopendir(int fd);
+int closedir(DIR *dir);
+
 size_t strlen(const char *);
 
 char *strcpy(char *restrict, const char *restrict);
diff --git a/clang/test/Analysis/stream-errno.c b/clang/test/Analysis/stream-errno.c
index f44ee6070708b26..f19109a3c0b481f 100644
--- a/clang/test/Analysis/stream-errno.c
+++ b/clang/test/Analysis/stream-errno.c
@@ -248,3 +248,25 @@ void check_fflush_all(void) {
     if (errno) {}                    // no-warning
   }
 }
+
+void check_opendir(const char *Path) {
+  DIR *Dir = opendir(Path);
+  if (Dir == NULL) {
+    clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
+    if (errno) {}                    // no-warning
+  } else {
+    if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}}
+    closedir(Dir);
+  }
+}
+
+void check_fdopendir(int Fd) {
+  DIR *Dir = fdopendir(Fd);
+  if (Dir == NULL) {
+    clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
+    if (errno) {}                    // no-warning
+  } else {
+    if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}}
+    closedir(Dir);
+  }
+}

>From cf410b1d56747d5e292c3bf02c12df19f9aa03c5 Mon Sep 17 00:00:00 2001
From: Ben Shi <bennshi at tencent.com>
Date: Tue, 16 Jan 2024 17:01:04 +0800
Subject: [PATCH 2/2] [clang][analyzer] Improve modeling of two functions in
 StdLibraryFunctionsChecker

---
 .../Analysis/Inputs/system-header-simulator.h |  7 +-----
 clang/test/Analysis/stream-errno.c            | 22 -------------------
 2 files changed, 1 insertion(+), 28 deletions(-)

diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h b/clang/test/Analysis/Inputs/system-header-simulator.h
index ba0e09ca77bc2af..cd7ac616bcc67fa 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator.h
@@ -14,9 +14,8 @@ typedef long long __int64_t;
 typedef __int64_t __darwin_off_t;
 typedef __darwin_off_t fpos_t;
 typedef int off_t;
-typedef struct _FILE FILE;
-typedef struct _DIR DIR;
 
+typedef struct _FILE FILE;
 #define SEEK_SET 0 /* Seek from beginning of file. */
 #define SEEK_CUR 1 /* Seek from current position. */
 #define SEEK_END 2 /* Seek from end of file. */
@@ -69,10 +68,6 @@ int ferror(FILE *stream);
 int fileno(FILE *stream);
 int fflush(FILE *stream);
 
-DIR *opendir(const char *name);
-DIR *fdopendir(int fd);
-int closedir(DIR *dir);
-
 size_t strlen(const char *);
 
 char *strcpy(char *restrict, const char *restrict);
diff --git a/clang/test/Analysis/stream-errno.c b/clang/test/Analysis/stream-errno.c
index f19109a3c0b481f..f44ee6070708b26 100644
--- a/clang/test/Analysis/stream-errno.c
+++ b/clang/test/Analysis/stream-errno.c
@@ -248,25 +248,3 @@ void check_fflush_all(void) {
     if (errno) {}                    // no-warning
   }
 }
-
-void check_opendir(const char *Path) {
-  DIR *Dir = opendir(Path);
-  if (Dir == NULL) {
-    clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
-    if (errno) {}                    // no-warning
-  } else {
-    if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}}
-    closedir(Dir);
-  }
-}
-
-void check_fdopendir(int Fd) {
-  DIR *Dir = fdopendir(Fd);
-  if (Dir == NULL) {
-    clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
-    if (errno) {}                    // no-warning
-  } else {
-    if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}}
-    closedir(Dir);
-  }
-}



More information about the cfe-commits mailing list