Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

Conversation

benshi001
Copy link
Member

No description provided.

@benshi001 benshi001 requested review from steakhal and balazske January 9, 2024 09:50
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:static analyzer labels Jan 9, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 9, 2024

@llvm/pr-subscribers-clang-static-analyzer-1

@llvm/pr-subscribers-clang

Author: Ben Shi (benshi001)

Changes

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 --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'}}
+  }
+}

@balazske
Copy link
Collaborator

balazske commented Jan 9, 2024

I have already a patch to add these functions: #76979. The conditions for fputc are not the same, this can be clarified at the other patch.

@benshi001
Copy link
Member Author

I have already a patch to add these functions: #76979. The conditions for fputc are not the same, this can be clarified at the other patch.

I see. It would be better to close this PR, and supplement my parts in your PR.

@benshi001 benshi001 closed this Jan 10, 2024
@benshi001 benshi001 deleted the csa-fputc branch January 10, 2024 02:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:static analyzer clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants