Author: Balázs Kéri
Date: 2025-05-23T09:26:31+02:00
New Revision: be50ada9d008673a041a5e675f9d9d70a4572aaa

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

LOG: [clang][analyzer] Refine modeling of 'getcwd' in StdCLibraryFunctions 
checker (#141076)

Add extra branches for the case when the buffer argument is NULL.

Fixes #135720

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
    clang/test/Analysis/errno-stdlibraryfunctions.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 3c6c3123f5cdd..6dae817fe89b5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -2651,16 +2651,22 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
     addToFunctionSummaryMap(
         "getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}),
         Summary(NoEvalCall)
-            .Case({ArgumentCondition(1, WithinRange, Range(1, SizeMax)),
+            .Case({NotNull(0),
+                   ArgumentCondition(1, WithinRange, Range(1, SizeMax)),
                    ReturnValueCondition(BO_EQ, ArgNo(0))},
                   ErrnoMustNotBeChecked, GenericSuccessMsg)
-            .Case({ArgumentCondition(1, WithinRange, SingleValue(0)),
+            .Case({NotNull(0),
+                   ArgumentCondition(1, WithinRange, SingleValue(0)),
                    IsNull(Ret)},
                   ErrnoNEZeroIrrelevant, "Assuming that argument 'size' is 0")
-            .Case({ArgumentCondition(1, WithinRange, Range(1, SizeMax)),
+            .Case({NotNull(0),
+                   ArgumentCondition(1, WithinRange, Range(1, SizeMax)),
                    IsNull(Ret)},
                   ErrnoNEZeroIrrelevant, GenericFailureMsg)
-            .ArgConstraint(NotNull(ArgNo(0)))
+            .Case({IsNull(0), NotNull(Ret)}, ErrnoMustNotBeChecked,
+                  GenericSuccessMsg)
+            .Case({IsNull(0), IsNull(Ret)}, ErrnoNEZeroIrrelevant,
+                  GenericFailureMsg)
             .ArgConstraint(
                 BufferSize(/*Buffer*/ ArgNo(0), /*BufSize*/ ArgNo(1)))
             .ArgConstraint(

diff  --git a/clang/test/Analysis/errno-stdlibraryfunctions.c 
b/clang/test/Analysis/errno-stdlibraryfunctions.c
index 657aa37a42670..72d167f68a1f4 100644
--- a/clang/test/Analysis/errno-stdlibraryfunctions.c
+++ b/clang/test/Analysis/errno-stdlibraryfunctions.c
@@ -99,7 +99,9 @@ void errno_mkdtemp3(CHAR_PTR template) {
   }
 }
 
-void errno_getcwd(char *Buf, size_t Sz) {
+void errno_getcwd_buf_nonnull(char *Buf, size_t Sz) {
+  if (Buf == NULL)
+    return;
   char *Path = getcwd(Buf, Sz);
   if (Sz == 0) {
     clang_analyzer_eval(errno != 0);   // expected-warning{{TRUE}}
@@ -114,6 +116,17 @@ void errno_getcwd(char *Buf, size_t Sz) {
   }
 }
 
+void errno_getcwd_buf_null() {
+  // POSIX does not mention this case but many implementations (Linux, 
FreeBSD) work this way.
+  char *Path = getcwd(NULL, 1);
+  if (Path == 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'}}
+  }
+}
+
 void errno_execv(char *Path, char * Argv[]) {
   int Ret = execv(Path, Argv);
   clang_analyzer_eval(Ret == -1);  // expected-warning{{TRUE}}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to