[clang] [clang][analyzer] Improve 'errno' modeling of 'mkdtemp' (PR #76671)

Ben Shi via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 3 01:13:51 PST 2024


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

>From 0c586914ac977920140472d172ee357dea43f2c5 Mon Sep 17 00:00:00 2001
From: Ben Shi <bennshi at tencent.com>
Date: Mon, 1 Jan 2024 18:48:27 +0800
Subject: [PATCH 1/2] [clang][analyzer] Improve 'errno' modeling of 'mkdtemp'

---
 .../Checkers/StdLibraryFunctionsChecker.cpp   |  6 ++--
 .../test/Analysis/errno-stdlibraryfunctions.c | 29 +++++++++++++++----
 2 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 4ca49b9c0546d9..6f249b6b880283 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -2511,10 +2511,12 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // char *mkdtemp(char *template);
-    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "mkdtemp", Signature(ArgTypes{CharPtrTy}, RetType{CharPtrTy}),
-        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
+        Summary(NoEvalCall)
+            .Case({NotNull(Ret)}, ErrnoMustNotBeChecked, GenericSuccessMsg)
+            .Case({IsNull(Ret)}, ErrnoNEZeroIrrelevant, GenericFailureMsg)
+            .ArgConstraint(NotNull(ArgNo(0))));
 
     // char *getcwd(char *buf, size_t size);
     // FIXME: Improve for errno modeling.
diff --git a/clang/test/Analysis/errno-stdlibraryfunctions.c b/clang/test/Analysis/errno-stdlibraryfunctions.c
index dafda764af9f38..de31de8cfea39b 100644
--- a/clang/test/Analysis/errno-stdlibraryfunctions.c
+++ b/clang/test/Analysis/errno-stdlibraryfunctions.c
@@ -7,12 +7,9 @@
 // RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true
 
 #include "Inputs/errno_var.h"
+#include "Inputs/std-c-library-functions-POSIX.h"
 
-typedef typeof(sizeof(int)) size_t;
-typedef __typeof(sizeof(int)) off_t;
-typedef size_t ssize_t;
-ssize_t send(int sockfd, const void *buf, size_t len, int flags);
-off_t lseek(int fildes, off_t offset, int whence);
+#define NULL ((void *) 0)
 
 void clang_analyzer_warnIfReached();
 void clang_analyzer_eval(int);
@@ -54,3 +51,25 @@ int errno_lseek(int fildes, off_t offset) {
   }
   return 0;
 }
+
+void errno_mkstemp(char *template) {
+  int FD = mkstemp(template);
+  if (FD >= 0) {
+    if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}}
+    close(FD);
+  } else {
+    clang_analyzer_eval(FD == -1);   // expected-warning{{TRUE}}
+    clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
+    if (errno) {}                    // no warning
+  }
+}
+
+void errno_mkdtemp(char *template) {
+  char *Dir = mkdtemp(template);
+  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'}}
+  }
+}

>From 47dce8c0c13bda1753aa7f5bdb4bd9cc45d707be Mon Sep 17 00:00:00 2001
From: Ben Shi <bennshi at tencent.com>
Date: Wed, 3 Jan 2024 17:13:29 +0800
Subject: [PATCH 2/2] [clang][analyzer] Improve 'errno' modeling of 'mkdtemp'

---
 .../StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp | 3 ++-
 clang/test/Analysis/errno-stdlibraryfunctions.c            | 7 ++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 6f249b6b880283..4adc91b85071a8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -2514,7 +2514,8 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
     addToFunctionSummaryMap(
         "mkdtemp", Signature(ArgTypes{CharPtrTy}, RetType{CharPtrTy}),
         Summary(NoEvalCall)
-            .Case({NotNull(Ret)}, ErrnoMustNotBeChecked, GenericSuccessMsg)
+            .Case({ReturnValueCondition(BO_EQ, ArgNo(0))},
+                  ErrnoMustNotBeChecked, GenericSuccessMsg)
             .Case({IsNull(Ret)}, ErrnoNEZeroIrrelevant, GenericFailureMsg)
             .ArgConstraint(NotNull(ArgNo(0))));
 
diff --git a/clang/test/Analysis/errno-stdlibraryfunctions.c b/clang/test/Analysis/errno-stdlibraryfunctions.c
index de31de8cfea39b..80e14c4e2923ca 100644
--- a/clang/test/Analysis/errno-stdlibraryfunctions.c
+++ b/clang/test/Analysis/errno-stdlibraryfunctions.c
@@ -67,9 +67,10 @@ void errno_mkstemp(char *template) {
 void errno_mkdtemp(char *template) {
   char *Dir = mkdtemp(template);
   if (Dir == NULL) {
-    clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
-    if (errno) {}                    // no warning
+    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'}}
+    clang_analyzer_eval(Dir == template); // expected-warning{{TRUE}}
+    if (errno) {}                         // expected-warning{{An undefined value may be read from 'errno'}}
   }
 }



More information about the cfe-commits mailing list