[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-03-06 Thread Balazs Benics via cfe-commits
Alejandro =?utf-8?q?Álvarez_Ayllón?Message-ID:
In-Reply-To: 


https://github.com/steakhal closed 
https://github.com/llvm/llvm-project/pull/83281
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-03-06 Thread Balazs Benics via cfe-commits
Alejandro =?utf-8?q?Álvarez_Ayllón?Message-ID:
In-Reply-To: 


https://github.com/steakhal updated 
https://github.com/llvm/llvm-project/pull/83281

>From a9419bc3ffa3d383a9373f0a116795162632dd40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20=C3=81lvarez=20Ayll=C3=B3n?=
 
Date: Wed, 28 Feb 2024 16:49:35 +0100
Subject: [PATCH 1/2] Reapply "[clang][analyzer] StreamChecker: Model getc,
 vfscanf, putc, vfprintf (#82476)"

This reverts commit 570bc5d291f92e19f6264262b02ddff1a2f2e09b
---
 .../StaticAnalyzer/Checkers/StreamChecker.cpp | 34 ---
 ...ystem-header-simulator-for-simple-stream.h |  2 +-
 .../system-header-simulator-for-valist.h  |  6 +++
 .../Analysis/Inputs/system-header-simulator.h |  3 ++
 clang/test/Analysis/stream-invalidate.c   | 42 +++
 clang/test/Analysis/stream.c  | 39 -
 6 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 65bdc4cac30940..f9928e1325c53d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -348,18 +348,30 @@ class StreamChecker : public CheckergetType();
-  if (!T->isIntegralOrEnumerationType() && !T->isPointerType())
+  if (!T->isIntegralOrEnumerationType() && !T->isPointerType() &&
+  T.getCanonicalType() != VaListType)
 return nullptr;
 }
 
@@ -600,6 +615,11 @@ class StreamChecker : public CheckerPreFn)
@@ -1038,10 +1059,13 @@ void StreamChecker::evalFscanf(const FnDescription 
*Desc, const CallEvent ,
 if (!StateNotFailed)
   return;
 
-SmallVector EscArgs;
-for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
-  EscArgs.push_back(EscArg);
-StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+if (auto const *Callee = Call.getCalleeIdentifier();
+!Callee || !Callee->getName().equals("vfscanf")) {
+  SmallVector EscArgs;
+  for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
+EscArgs.push_back(EscArg);
+  StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+}
 
 if (StateNotFailed)
   C.addTransition(StateNotFailed);
diff --git 
a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h 
b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
index 098a2208fecbe9..c26d3582149120 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
@@ -5,7 +5,7 @@
 // suppressed.
 #pragma clang system_header
 
-typedef struct __sFILE {
+typedef struct _FILE {
   unsigned char *_p;
 } FILE;
 FILE *fopen(const char *restrict, const char *restrict) __asm("_" "fopen" );
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h 
b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
index 7299b61353d460..720944abb8ad47 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
@@ -10,6 +10,8 @@
 #define restrict /*restrict*/
 #endif
 
+typedef struct _FILE FILE;
+
 typedef __builtin_va_list va_list;
 
 #define va_start(ap, param) __builtin_va_start(ap, param)
@@ -21,6 +23,10 @@ int vprintf (const char *restrict format, va_list arg);
 
 int vsprintf (char *restrict s, const char *restrict format, va_list arg);
 
+int vfprintf(FILE *stream, const char *format, va_list ap);
+
+int vfscanf(FILE *stream, const char *format, va_list ap);
+
 int some_library_function(int n, va_list arg);
 
 // No warning from system header.
diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h 
b/clang/test/Analysis/Inputs/system-header-simulator.h
index 15986984802c0e..8fd51449ecc0a4 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator.h
@@ -73,6 +73,9 @@ int ferror(FILE *stream);
 int fileno(FILE *stream);
 int fflush(FILE *stream);
 
+
+int getc(FILE *stream);
+
 size_t strlen(const char *);
 
 char *strcpy(char *restrict, const char *restrict);
diff --git a/clang/test/Analysis/stream-invalidate.c 
b/clang/test/Analysis/stream-invalidate.c
index 6745d11a2fe701..5046a356d0583d 100644
--- a/clang/test/Analysis/stream-invalidate.c
+++ b/clang/test/Analysis/stream-invalidate.c
@@ -4,6 +4,7 @@
 // RUN: -analyzer-checker=debug.ExprInspection
 
 #include "Inputs/system-header-simulator.h"
+#include "Inputs/system-header-simulator-for-valist.h"
 
 void clang_analyzer_eval(int);
 void clang_analyzer_dump(int);
@@ -145,3 +146,44 @@ void test_fgetpos() {
 
   fclose(F);
 }
+
+void test_fprintf() {
+  FILE *F1 = tmpfile();
+  if (!F1)
+return;
+
+  unsigned a = 42;
+  char *output = "HELLO";
+  int r = fprintf(F1, "%s\t%u\n", output, a);
+  // fprintf does not invalidate any of its input
+  // 69 is ascii 

[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-03-06 Thread Balazs Benics via cfe-commits
Alejandro =?utf-8?q?=C3=81lvarez_Ayll=C3=B3n?=
Message-ID:
In-Reply-To: 


https://github.com/steakhal approved this pull request.


https://github.com/llvm/llvm-project/pull/83281
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-03-06 Thread Alejandro Álvarez Ayllón via cfe-commits

alejandro-alvarez-sonarsource wrote:

Well, the test now runs for 4 different platforms and the PR checks are all 
green, so I guess we can merge.

https://github.com/llvm/llvm-project/pull/83281
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-03-05 Thread Balazs Benics via cfe-commits
Alejandro =?utf-8?q?=C3=81lvarez_Ayll=C3=B3n?=
Message-ID:
In-Reply-To: 


steakhal wrote:

@alejandro-alvarez-sonarsource Should we merge this, and give it a try?

https://github.com/llvm/llvm-project/pull/83281
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-02-29 Thread Alejandro Álvarez Ayllón via cfe-commits

alejandro-alvarez-sonarsource wrote:

@balazske @steakhal I broke some tests on aarch64 since there 
`__builtin_valist` is a struct and not a pointer to struct, so `lookupFn` was 
not matching `vfprintf` nor `vfscanf`, and the NULL pointer dereference 
triggered on the `fclose`. I have fixed that and modified `stream.c` to always 
run with four different target architectures, to make sure different `va_list` 
are handled.

Not sure if that is the best way, though.

https://github.com/llvm/llvm-project/pull/83281
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-02-28 Thread Alejandro Álvarez Ayllón via cfe-commits

https://github.com/alejandro-alvarez-sonarsource updated 
https://github.com/llvm/llvm-project/pull/83281

From a9419bc3ffa3d383a9373f0a116795162632dd40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20=C3=81lvarez=20Ayll=C3=B3n?=
 
Date: Wed, 28 Feb 2024 16:49:35 +0100
Subject: [PATCH 1/2] Reapply "[clang][analyzer] StreamChecker: Model getc,
 vfscanf, putc, vfprintf (#82476)"

This reverts commit 570bc5d291f92e19f6264262b02ddff1a2f2e09b
---
 .../StaticAnalyzer/Checkers/StreamChecker.cpp | 34 ---
 ...ystem-header-simulator-for-simple-stream.h |  2 +-
 .../system-header-simulator-for-valist.h  |  6 +++
 .../Analysis/Inputs/system-header-simulator.h |  3 ++
 clang/test/Analysis/stream-invalidate.c   | 42 +++
 clang/test/Analysis/stream.c  | 39 -
 6 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 65bdc4cac30940..f9928e1325c53d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -348,18 +348,30 @@ class StreamChecker : public CheckergetType();
-  if (!T->isIntegralOrEnumerationType() && !T->isPointerType())
+  if (!T->isIntegralOrEnumerationType() && !T->isPointerType() &&
+  T.getCanonicalType() != VaListType)
 return nullptr;
 }
 
@@ -600,6 +615,11 @@ class StreamChecker : public CheckerPreFn)
@@ -1038,10 +1059,13 @@ void StreamChecker::evalFscanf(const FnDescription 
*Desc, const CallEvent ,
 if (!StateNotFailed)
   return;
 
-SmallVector EscArgs;
-for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
-  EscArgs.push_back(EscArg);
-StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+if (auto const *Callee = Call.getCalleeIdentifier();
+!Callee || !Callee->getName().equals("vfscanf")) {
+  SmallVector EscArgs;
+  for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
+EscArgs.push_back(EscArg);
+  StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+}
 
 if (StateNotFailed)
   C.addTransition(StateNotFailed);
diff --git 
a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h 
b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
index 098a2208fecbe9..c26d3582149120 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
@@ -5,7 +5,7 @@
 // suppressed.
 #pragma clang system_header
 
-typedef struct __sFILE {
+typedef struct _FILE {
   unsigned char *_p;
 } FILE;
 FILE *fopen(const char *restrict, const char *restrict) __asm("_" "fopen" );
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h 
b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
index 7299b61353d460..720944abb8ad47 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
@@ -10,6 +10,8 @@
 #define restrict /*restrict*/
 #endif
 
+typedef struct _FILE FILE;
+
 typedef __builtin_va_list va_list;
 
 #define va_start(ap, param) __builtin_va_start(ap, param)
@@ -21,6 +23,10 @@ int vprintf (const char *restrict format, va_list arg);
 
 int vsprintf (char *restrict s, const char *restrict format, va_list arg);
 
+int vfprintf(FILE *stream, const char *format, va_list ap);
+
+int vfscanf(FILE *stream, const char *format, va_list ap);
+
 int some_library_function(int n, va_list arg);
 
 // No warning from system header.
diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h 
b/clang/test/Analysis/Inputs/system-header-simulator.h
index 15986984802c0e..8fd51449ecc0a4 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator.h
@@ -73,6 +73,9 @@ int ferror(FILE *stream);
 int fileno(FILE *stream);
 int fflush(FILE *stream);
 
+
+int getc(FILE *stream);
+
 size_t strlen(const char *);
 
 char *strcpy(char *restrict, const char *restrict);
diff --git a/clang/test/Analysis/stream-invalidate.c 
b/clang/test/Analysis/stream-invalidate.c
index 6745d11a2fe701..5046a356d0583d 100644
--- a/clang/test/Analysis/stream-invalidate.c
+++ b/clang/test/Analysis/stream-invalidate.c
@@ -4,6 +4,7 @@
 // RUN: -analyzer-checker=debug.ExprInspection
 
 #include "Inputs/system-header-simulator.h"
+#include "Inputs/system-header-simulator-for-valist.h"
 
 void clang_analyzer_eval(int);
 void clang_analyzer_dump(int);
@@ -145,3 +146,44 @@ void test_fgetpos() {
 
   fclose(F);
 }
+
+void test_fprintf() {
+  FILE *F1 = tmpfile();
+  if (!F1)
+return;
+
+  unsigned a = 42;
+  char *output = "HELLO";
+  int r = fprintf(F1, "%s\t%u\n", output, a);
+  // fprintf does not invalidate any of its input
+  // 69 is ascii for 'E'
+  clang_analyzer_dump(a); // 

[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-02-28 Thread Alejandro Álvarez Ayllón via cfe-commits

https://github.com/alejandro-alvarez-sonarsource updated 
https://github.com/llvm/llvm-project/pull/83281

From a9419bc3ffa3d383a9373f0a116795162632dd40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20=C3=81lvarez=20Ayll=C3=B3n?=
 
Date: Wed, 28 Feb 2024 16:49:35 +0100
Subject: [PATCH] Reapply "[clang][analyzer] StreamChecker: Model getc,
 vfscanf, putc, vfprintf (#82476)"

This reverts commit 570bc5d291f92e19f6264262b02ddff1a2f2e09b
---
 .../StaticAnalyzer/Checkers/StreamChecker.cpp | 34 ---
 ...ystem-header-simulator-for-simple-stream.h |  2 +-
 .../system-header-simulator-for-valist.h  |  6 +++
 .../Analysis/Inputs/system-header-simulator.h |  3 ++
 clang/test/Analysis/stream-invalidate.c   | 42 +++
 clang/test/Analysis/stream.c  | 39 -
 6 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 65bdc4cac30940..f9928e1325c53d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -348,18 +348,30 @@ class StreamChecker : public CheckergetType();
-  if (!T->isIntegralOrEnumerationType() && !T->isPointerType())
+  if (!T->isIntegralOrEnumerationType() && !T->isPointerType() &&
+  T.getCanonicalType() != VaListType)
 return nullptr;
 }
 
@@ -600,6 +615,11 @@ class StreamChecker : public CheckerPreFn)
@@ -1038,10 +1059,13 @@ void StreamChecker::evalFscanf(const FnDescription 
*Desc, const CallEvent ,
 if (!StateNotFailed)
   return;
 
-SmallVector EscArgs;
-for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
-  EscArgs.push_back(EscArg);
-StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+if (auto const *Callee = Call.getCalleeIdentifier();
+!Callee || !Callee->getName().equals("vfscanf")) {
+  SmallVector EscArgs;
+  for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
+EscArgs.push_back(EscArg);
+  StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+}
 
 if (StateNotFailed)
   C.addTransition(StateNotFailed);
diff --git 
a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h 
b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
index 098a2208fecbe9..c26d3582149120 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
@@ -5,7 +5,7 @@
 // suppressed.
 #pragma clang system_header
 
-typedef struct __sFILE {
+typedef struct _FILE {
   unsigned char *_p;
 } FILE;
 FILE *fopen(const char *restrict, const char *restrict) __asm("_" "fopen" );
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h 
b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
index 7299b61353d460..720944abb8ad47 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
@@ -10,6 +10,8 @@
 #define restrict /*restrict*/
 #endif
 
+typedef struct _FILE FILE;
+
 typedef __builtin_va_list va_list;
 
 #define va_start(ap, param) __builtin_va_start(ap, param)
@@ -21,6 +23,10 @@ int vprintf (const char *restrict format, va_list arg);
 
 int vsprintf (char *restrict s, const char *restrict format, va_list arg);
 
+int vfprintf(FILE *stream, const char *format, va_list ap);
+
+int vfscanf(FILE *stream, const char *format, va_list ap);
+
 int some_library_function(int n, va_list arg);
 
 // No warning from system header.
diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h 
b/clang/test/Analysis/Inputs/system-header-simulator.h
index 15986984802c0e..8fd51449ecc0a4 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator.h
@@ -73,6 +73,9 @@ int ferror(FILE *stream);
 int fileno(FILE *stream);
 int fflush(FILE *stream);
 
+
+int getc(FILE *stream);
+
 size_t strlen(const char *);
 
 char *strcpy(char *restrict, const char *restrict);
diff --git a/clang/test/Analysis/stream-invalidate.c 
b/clang/test/Analysis/stream-invalidate.c
index 6745d11a2fe701..5046a356d0583d 100644
--- a/clang/test/Analysis/stream-invalidate.c
+++ b/clang/test/Analysis/stream-invalidate.c
@@ -4,6 +4,7 @@
 // RUN: -analyzer-checker=debug.ExprInspection
 
 #include "Inputs/system-header-simulator.h"
+#include "Inputs/system-header-simulator-for-valist.h"
 
 void clang_analyzer_eval(int);
 void clang_analyzer_dump(int);
@@ -145,3 +146,44 @@ void test_fgetpos() {
 
   fclose(F);
 }
+
+void test_fprintf() {
+  FILE *F1 = tmpfile();
+  if (!F1)
+return;
+
+  unsigned a = 42;
+  char *output = "HELLO";
+  int r = fprintf(F1, "%s\t%u\n", output, a);
+  // fprintf does not invalidate any of its input
+  // 69 is ascii for 'E'
+  clang_analyzer_dump(a); // 

[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-02-28 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 680c780a367bfe1c0cdf786250fd7f565ef6d23d 
ddbe895e3d2893060ac54bc6c984eea22e09b460 -- 
clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp 
clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h 
clang/test/Analysis/Inputs/system-header-simulator-for-valist.h 
clang/test/Analysis/Inputs/system-header-simulator.h 
clang/test/Analysis/stream-invalidate.c clang/test/Analysis/stream.c
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index f9928e1325..f2f7a0f83b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -616,8 +616,7 @@ private:
   }
 
   void initVaListType(CheckerContext ) const {
-VaListType =
-C.getASTContext().getBuiltinVaListType().getCanonicalType();
+VaListType = C.getASTContext().getBuiltinVaListType().getCanonicalType();
   }
 
   /// Searches for the ExplodedNode where the file descriptor was acquired for

``




https://github.com/llvm/llvm-project/pull/83281
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-02-28 Thread via cfe-commits

llvmbot wrote:




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

Author: Alejandro Álvarez Ayllón (alejandro-alvarez-sonarsource)


Changes

…vfprintf (#82476)"

`va_list` is a platform-specific type. On some, it is a struct instead of a 
pointer to a struct, so `lookupFn` was ignoring calls to `vfprintf` and 
`vfscanf`.

`stream.c` now runs in four different platforms to make sure the logic works 
across targets.

This reverts commit 570bc5d291f92e19f6264262b02ddff1a2f2e09b.



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


6 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp (+29-5) 
- (modified) 
clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h (+1-1) 
- (modified) clang/test/Analysis/Inputs/system-header-simulator-for-valist.h 
(+6) 
- (modified) clang/test/Analysis/Inputs/system-header-simulator.h (+3) 
- (modified) clang/test/Analysis/stream-invalidate.c (+42) 
- (modified) clang/test/Analysis/stream.c (+10-331) 


``diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 65bdc4cac30940..f9928e1325c53d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -348,18 +348,30 @@ class StreamChecker : public CheckergetType();
-  if (!T->isIntegralOrEnumerationType() && !T->isPointerType())
+  if (!T->isIntegralOrEnumerationType() && !T->isPointerType() &&
+  T.getCanonicalType() != VaListType)
 return nullptr;
 }
 
@@ -600,6 +615,11 @@ class StreamChecker : public CheckerPreFn)
@@ -1038,10 +1059,13 @@ void StreamChecker::evalFscanf(const FnDescription 
*Desc, const CallEvent ,
 if (!StateNotFailed)
   return;
 
-SmallVector EscArgs;
-for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
-  EscArgs.push_back(EscArg);
-StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+if (auto const *Callee = Call.getCalleeIdentifier();
+!Callee || !Callee->getName().equals("vfscanf")) {
+  SmallVector EscArgs;
+  for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
+EscArgs.push_back(EscArg);
+  StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+}
 
 if (StateNotFailed)
   C.addTransition(StateNotFailed);
diff --git 
a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h 
b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
index 098a2208fecbe9..c26d3582149120 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
@@ -5,7 +5,7 @@
 // suppressed.
 #pragma clang system_header
 
-typedef struct __sFILE {
+typedef struct _FILE {
   unsigned char *_p;
 } FILE;
 FILE *fopen(const char *restrict, const char *restrict) __asm("_" "fopen" );
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h 
b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
index 7299b61353d460..720944abb8ad47 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
@@ -10,6 +10,8 @@
 #define restrict /*restrict*/
 #endif
 
+typedef struct _FILE FILE;
+
 typedef __builtin_va_list va_list;
 
 #define va_start(ap, param) __builtin_va_start(ap, param)
@@ -21,6 +23,10 @@ int vprintf (const char *restrict format, va_list arg);
 
 int vsprintf (char *restrict s, const char *restrict format, va_list arg);
 
+int vfprintf(FILE *stream, const char *format, va_list ap);
+
+int vfscanf(FILE *stream, const char *format, va_list ap);
+
 int some_library_function(int n, va_list arg);
 
 // No warning from system header.
diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h 
b/clang/test/Analysis/Inputs/system-header-simulator.h
index 15986984802c0e..8fd51449ecc0a4 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator.h
@@ -73,6 +73,9 @@ int ferror(FILE *stream);
 int fileno(FILE *stream);
 int fflush(FILE *stream);
 
+
+int getc(FILE *stream);
+
 size_t strlen(const char *);
 
 char *strcpy(char *restrict, const char *restrict);
diff --git a/clang/test/Analysis/stream-invalidate.c 
b/clang/test/Analysis/stream-invalidate.c
index 6745d11a2fe701..5046a356d0583d 100644
--- a/clang/test/Analysis/stream-invalidate.c
+++ b/clang/test/Analysis/stream-invalidate.c
@@ -4,6 +4,7 @@
 // RUN: -analyzer-checker=debug.ExprInspection
 
 #include "Inputs/system-header-simulator.h"
+#include "Inputs/system-header-simulator-for-valist.h"
 
 void clang_analyzer_eval(int);
 void clang_analyzer_dump(int);
@@ -145,3 +146,44 @@ void test_fgetpos() {
 
   fclose(F);
 }
+
+void test_fprintf() {
+  FILE *F1 = tmpfile();
+  if (!F1)
+return;
+
+  unsigned a = 42;
+  char *output = "HELLO";
+  int r = 

[clang] Reapply "[clang][analyzer] StreamChecker: Model getc, vfscanf, putc, … (PR #83281)

2024-02-28 Thread Alejandro Álvarez Ayllón via cfe-commits

https://github.com/alejandro-alvarez-sonarsource created 
https://github.com/llvm/llvm-project/pull/83281

…vfprintf (#82476)"

`va_list` is a platform-specific type. On some, it is a struct instead of a 
pointer to a struct, so `lookupFn` was ignoring calls to `vfprintf` and 
`vfscanf`.

`stream.c` now runs in four different platforms to make sure the logic works 
across targets.

This reverts commit 570bc5d291f92e19f6264262b02ddff1a2f2e09b.



From ddbe895e3d2893060ac54bc6c984eea22e09b460 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alejandro=20=C3=81lvarez=20Ayll=C3=B3n?=
 
Date: Wed, 28 Feb 2024 16:43:25 +0100
Subject: [PATCH] Reapply "[clang][analyzer] StreamChecker: Model getc,
 vfscanf, putc, vfprintf (#82476)"

This reverts commit 570bc5d291f92e19f6264262b02ddff1a2f2e09b.
---
 .../StaticAnalyzer/Checkers/StreamChecker.cpp |  34 +-
 ...ystem-header-simulator-for-simple-stream.h |   2 +-
 .../system-header-simulator-for-valist.h  |   6 +
 .../Analysis/Inputs/system-header-simulator.h |   3 +
 clang/test/Analysis/stream-invalidate.c   |  42 +++
 clang/test/Analysis/stream.c  | 341 +-
 6 files changed, 91 insertions(+), 337 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 65bdc4cac30940..f9928e1325c53d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -348,18 +348,30 @@ class StreamChecker : public CheckergetType();
-  if (!T->isIntegralOrEnumerationType() && !T->isPointerType())
+  if (!T->isIntegralOrEnumerationType() && !T->isPointerType() &&
+  T.getCanonicalType() != VaListType)
 return nullptr;
 }
 
@@ -600,6 +615,11 @@ class StreamChecker : public CheckerPreFn)
@@ -1038,10 +1059,13 @@ void StreamChecker::evalFscanf(const FnDescription 
*Desc, const CallEvent ,
 if (!StateNotFailed)
   return;
 
-SmallVector EscArgs;
-for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
-  EscArgs.push_back(EscArg);
-StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+if (auto const *Callee = Call.getCalleeIdentifier();
+!Callee || !Callee->getName().equals("vfscanf")) {
+  SmallVector EscArgs;
+  for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
+EscArgs.push_back(EscArg);
+  StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+}
 
 if (StateNotFailed)
   C.addTransition(StateNotFailed);
diff --git 
a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h 
b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
index 098a2208fecbe9..c26d3582149120 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
@@ -5,7 +5,7 @@
 // suppressed.
 #pragma clang system_header
 
-typedef struct __sFILE {
+typedef struct _FILE {
   unsigned char *_p;
 } FILE;
 FILE *fopen(const char *restrict, const char *restrict) __asm("_" "fopen" );
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h 
b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
index 7299b61353d460..720944abb8ad47 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
@@ -10,6 +10,8 @@
 #define restrict /*restrict*/
 #endif
 
+typedef struct _FILE FILE;
+
 typedef __builtin_va_list va_list;
 
 #define va_start(ap, param) __builtin_va_start(ap, param)
@@ -21,6 +23,10 @@ int vprintf (const char *restrict format, va_list arg);
 
 int vsprintf (char *restrict s, const char *restrict format, va_list arg);
 
+int vfprintf(FILE *stream, const char *format, va_list ap);
+
+int vfscanf(FILE *stream, const char *format, va_list ap);
+
 int some_library_function(int n, va_list arg);
 
 // No warning from system header.
diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h 
b/clang/test/Analysis/Inputs/system-header-simulator.h
index 15986984802c0e..8fd51449ecc0a4 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator.h
@@ -73,6 +73,9 @@ int ferror(FILE *stream);
 int fileno(FILE *stream);
 int fflush(FILE *stream);
 
+
+int getc(FILE *stream);
+
 size_t strlen(const char *);
 
 char *strcpy(char *restrict, const char *restrict);
diff --git a/clang/test/Analysis/stream-invalidate.c 
b/clang/test/Analysis/stream-invalidate.c
index 6745d11a2fe701..5046a356d0583d 100644
--- a/clang/test/Analysis/stream-invalidate.c
+++ b/clang/test/Analysis/stream-invalidate.c
@@ -4,6 +4,7 @@
 // RUN: -analyzer-checker=debug.ExprInspection
 
 #include "Inputs/system-header-simulator.h"
+#include "Inputs/system-header-simulator-for-valist.h"
 
 void clang_analyzer_eval(int);
 void clang_analyzer_dump(int);
@@ -145,3 +146,44 @@ void