Author: Balázs Kéri
Date: 2026-01-19T09:33:59+01:00
New Revision: dc26c7e14d49b41302fb260c269d1dd919bb48b5

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

LOG: [clang][analyzer] StdLibraryFunctionsChecker getcwd fix (#175794)

`StdLibraryFunctionsChecker` contained the following condition for
`getcwd`:
```
           .Case({NotNull(0),
                  ArgumentCondition(1, WithinRange, Range(1, SizeMax)),
                  ReturnValueCondition(BO_EQ, ArgNo(0))},
                 ErrnoMustNotBeChecked, GenericSuccessMsg)
```
In this case argument 1 should be not zero and return value is set to be
equal to argument 1. This would mean that return value is implicitly not
zero. But for unknown reason (probably analyzer inaccuracy) it can occur
that the return value is still assumable to be zero after this condition
was applied. This results in false positive if `ErrnoChecker` is enabled
because when the return value is 0 value of `errno` should be allowed to
be read but in this case it is not.
The bug is fixed by adding an extra (theoretically redundant) condition
for the return value to be non-zero.

Fixes #175136

Added: 
    clang/test/Analysis/std-c-library-functions-char-uchar-conv.c

Modified: 
    clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 844447f59f7f6..8a3ee4443eb16 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -2277,7 +2277,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
         Signature(ArgTypes{CharPtrRestrictTy, IntTy, FilePtrRestrictTy},
                   RetType{CharPtrTy}),
         Summary(NoEvalCall)
-            .Case({ReturnValueCondition(BO_EQ, ArgNo(0))},
+            .Case({NotNull(Ret), ReturnValueCondition(BO_EQ, ArgNo(0))},
                   ErrnoMustNotBeChecked, GenericSuccessMsg)
             .Case({IsNull(Ret)}, ErrnoIrrelevant, GenericFailureMsg)
             .ArgConstraint(NotNull(ArgNo(0)))
@@ -2645,7 +2645,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
     addToFunctionSummaryMap(
         "mkdtemp", Signature(ArgTypes{CharPtrTy}, RetType{CharPtrTy}),
         Summary(NoEvalCall)
-            .Case({ReturnValueCondition(BO_EQ, ArgNo(0))},
+            .Case({NotNull(Ret), ReturnValueCondition(BO_EQ, ArgNo(0))},
                   ErrnoMustNotBeChecked, GenericSuccessMsg)
             .Case({IsNull(Ret)}, ErrnoNEZeroIrrelevant, GenericFailureMsg)
             .ArgConstraint(NotNull(ArgNo(0))));
@@ -2657,7 +2657,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
         Summary(NoEvalCall)
             .Case({NotNull(0),
                    ArgumentCondition(1, WithinRange, Range(1, SizeMax)),
-                   ReturnValueCondition(BO_EQ, ArgNo(0))},
+                   ReturnValueCondition(BO_EQ, ArgNo(0)), NotNull(Ret)},
                   ErrnoMustNotBeChecked, GenericSuccessMsg)
             .Case({NotNull(0),
                    ArgumentCondition(1, WithinRange, SingleValue(0)),

diff  --git a/clang/test/Analysis/std-c-library-functions-char-uchar-conv.c 
b/clang/test/Analysis/std-c-library-functions-char-uchar-conv.c
new file mode 100644
index 0000000000000..0c70ae9a13dee
--- /dev/null
+++ b/clang/test/Analysis/std-c-library-functions-char-uchar-conv.c
@@ -0,0 +1,50 @@
+// RUN: %clang_analyze_cc1 \
+// RUN:   -analyzer-checker=core,unix.StdCLibraryFunctions,unix.Errno \
+// RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=true \
+// RUN:   -verify %s
+//
+// expected-no-diagnostics
+
+#include "Inputs/errno_var.h"
+
+typedef __typeof__(sizeof(int)) size_t;
+typedef struct {} FILE;
+char *getcwd(char *buf, size_t size);
+char *fgets(char *restrict s, int n, FILE *restrict stream);
+char *mkdtemp(char *template);
+
+int fputc(int c, FILE *stream);
+#define EOF (-1)
+
+void gh_175136(char *CharData, unsigned char *UCharData, size_t Size) {
+  if (!getcwd(CharData, Size)) {
+    if (errno == 2) {
+      return;
+    }
+  }
+
+  if (!getcwd((char*)UCharData, Size)) {
+    if (errno == 2) { // Previously there was a (false) warning from 
unix.Errno on this line
+      return;
+    }
+  }
+}
+
+void fgets_test(unsigned char *Buf, size_t Size, FILE *F) {
+  if (!fgets((char *)Buf, Size, F))
+    if (errno == 1) // Similar case for the (false) warning
+      return;
+}
+
+void mkdtemp_test(unsigned char *Buf) {
+  if (!mkdtemp((char *)Buf))
+    if (errno == 1) // Similar case for the (false) warning
+      return;
+}
+
+void fputc_test(long long c, FILE *stream) {
+  if (fputc((int)c, stream) == EOF) {
+    if (errno == 1) // This case did not produce the false warning
+      return;
+  }
+}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to