[clang] [clang][analyzer] Implement modeling of 'fputc' in the StdLibraryFunctionsChecker (PR #77435)

via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 9 01:50:36 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Ben Shi (benshi001)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/77435.diff


3 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp (+14) 
- (modified) clang/test/Analysis/Inputs/std-c-library-functions.h (+1) 
- (modified) clang/test/Analysis/errno-stdlibraryfunctions.c (+14) 


``````````diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index 034825d88a44de..f160c464dc273a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -2277,6 +2277,20 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
                                 .Case({}, ErrnoMustBeChecked)
                                 .ArgConstraint(NotNull(ArgNo(0))));
 
+    // int fputc(int c, FILE *stream);
+    addToFunctionSummaryMap(
+        "fputc", Signature(ArgTypes{IntTy, FilePtrTy}, RetType{IntTy}),
+        Summary(NoEvalCall)
+            .Case({ArgumentCondition(0, WithinRange, Range(0, UCharRangeMax)),
+                   ReturnValueCondition(BO_EQ, ArgNo(0))},
+                  ErrnoMustNotBeChecked, GenericSuccessMsg)
+            .Case({ArgumentCondition(0, OutOfRange, Range(0, UCharRangeMax)),
+                   ReturnValueCondition(WithinRange, Range(0, UCharRangeMax))},
+                  ErrnoMustNotBeChecked, GenericSuccessMsg)
+            .Case({ReturnValueCondition(WithinRange, SingleValue(EOFv))},
+                  ErrnoNEZeroIrrelevant, GenericFailureMsg)
+            .ArgConstraint(NotNull(ArgNo(1))));
+
     // void clearerr(FILE *stream);
     addToFunctionSummaryMap(
         "clearerr", Signature(ArgTypes{FilePtrTy}, RetType{VoidTy}),
diff --git a/clang/test/Analysis/Inputs/std-c-library-functions.h b/clang/test/Analysis/Inputs/std-c-library-functions.h
index 7c86c359ee21de..6cb2d1be7a9b11 100644
--- a/clang/test/Analysis/Inputs/std-c-library-functions.h
+++ b/clang/test/Analysis/Inputs/std-c-library-functions.h
@@ -37,6 +37,7 @@ int toascii(int);
 
 int getc(FILE *);
 int fgetc(FILE *);
+int fputc(int c, FILE *stream);
 int getchar(void);
 size_t fread(void *restrict, size_t, size_t, FILE *restrict);
 size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict);
diff --git a/clang/test/Analysis/errno-stdlibraryfunctions.c b/clang/test/Analysis/errno-stdlibraryfunctions.c
index 9e3d07e7aa88a0..9ece662a937072 100644
--- a/clang/test/Analysis/errno-stdlibraryfunctions.c
+++ b/clang/test/Analysis/errno-stdlibraryfunctions.c
@@ -89,3 +89,17 @@ void errno_getcwd(char *Buf, size_t Sz) {
     if (errno) {}                      // expected-warning{{An undefined value may be read from 'errno'}}
   }
 }
+
+void errno_fputc(int C, FILE *Fp) {
+  int Ret = fputc(C, Fp);
+  if (Ret == EOF) {
+    clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
+    if (errno) {}                    // no warning
+  } else if (C >= 0 && C <= 255) {
+    clang_analyzer_eval(Ret == C);   // expected-warning{{TRUE}}
+    if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}}
+  } else {
+    clang_analyzer_eval(Ret != C);   // expected-warning{{TRUE}}
+    if (errno) {}                    // expected-warning{{An undefined value may be read from 'errno'}}
+  }
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/77435


More information about the cfe-commits mailing list