xref: /llvm-project/clang/test/Analysis/taint-generic.cpp (revision e5ac9145ba2951b6454b13499f375284bdbde689)
1 // RUN: %clang_analyze_cc1 -std=c++11 -Wno-format-security \
2 // RUN:   -analyzer-checker=core,optin.taint,alpha.security.ArrayBoundV2,debug.ExprInspection \
3 // RUN:   -analyzer-config optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml \
4 // RUN:   -verify %s
5 
6 template <typename T> void clang_analyzer_isTainted(T);
7 
8 #define BUFSIZE 10
9 int Buffer[BUFSIZE];
10 
11 int scanf(const char*, ...);
12 template <typename T = int> T mySource1();
13 int mySource3();
14 
15 typedef struct _FILE FILE;
16 extern "C" {
17 extern FILE *stdin;
18 }
19 int fscanf(FILE *stream, const char *format, ...);
20 
21 bool isOutOfRange2(const int*);
22 
23 void mySink2(int);
24 
25 // Test configuration
26 namespace myNamespace {
27   void scanf(const char*, ...);
28   void myScanf(const char*, ...);
29   int mySource3();
30 
31   bool isOutOfRange(const int*);
32   bool isOutOfRange2(const int*);
33 
34   void mySink(int, int, int);
35   void mySink2(int);
36 }
37 
38 namespace myAnotherNamespace {
39   int mySource3();
40 
41   bool isOutOfRange2(const int*);
42 
43   void mySink2(int);
44 }
45 
46 void testConfigurationNamespacePropagation1() {
47   int x;
48   // The built-in functions should be matched only for functions in
49   // the global namespace
50   myNamespace::scanf("%d", &x);
51   Buffer[x] = 1; // no-warning
52 
53   scanf("%d", &x);
54   Buffer[x] = 1; // expected-warning {{Potential out of bound access }}
55 }
56 
57 void testConfigurationNamespacePropagation2() {
58   int x = mySource3();
59   Buffer[x] = 1; // no-warning
60 
61   int y = myNamespace::mySource3();
62   Buffer[y] = 1; // expected-warning {{Potential out of bound access }}
63 }
64 
65 void testConfigurationNamespacePropagation3() {
66   int x = myAnotherNamespace::mySource3();
67   Buffer[x] = 1; // expected-warning {{Potential out of bound access }}
68 }
69 
70 void testConfigurationNamespacePropagation4() {
71   int x;
72   // Configured functions without scope should match for all function.
73   myNamespace::myScanf("%d", &x);
74   Buffer[x] = 1; // expected-warning {{Potential out of bound access }}
75 }
76 
77 void testConfigurationNamespaceFilter1() {
78   int x = mySource1();
79   if (myNamespace::isOutOfRange2(&x))
80     return;
81   Buffer[x] = 1; // no-warning
82 
83   int y = mySource1();
84   if (isOutOfRange2(&y))
85     return;
86   Buffer[y] = 1; // expected-warning {{Potential out of bound access }}
87 }
88 
89 void testConfigurationNamespaceFilter2() {
90   int x = mySource1();
91   if (myAnotherNamespace::isOutOfRange2(&x))
92     return;
93   Buffer[x] = 1; // no-warning
94 }
95 
96 void testConfigurationNamespaceFilter3() {
97   int x = mySource1();
98   if (myNamespace::isOutOfRange(&x))
99     return;
100   Buffer[x] = 1; // no-warning
101 }
102 
103 void testConfigurationNamespaceSink1() {
104   int x = mySource1();
105   mySink2(x); // no-warning
106 
107   int y = mySource1();
108   myNamespace::mySink2(y);
109   // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
110 }
111 
112 void testConfigurationNamespaceSink2() {
113   int x = mySource1();
114   myAnotherNamespace::mySink2(x);
115   // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
116 }
117 
118 void testConfigurationNamespaceSink3() {
119   int x = mySource1();
120   myNamespace::mySink(x, 0, 1);
121   // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
122 }
123 
124 struct Foo {
125     void scanf(const char*, int*);
126     void myMemberScanf(const char*, int*);
127 };
128 
129 void testConfigurationMemberFunc() {
130   int x;
131   Foo foo;
132   foo.scanf("%d", &x);
133   Buffer[x] = 1; // no-warning
134 
135   foo.myMemberScanf("%d", &x);
136   Buffer[x] = 1; // expected-warning {{Potential out of bound access }}
137 }
138 
139 void testReadingFromStdin(char **p) {
140   int n;
141   fscanf(stdin, "%d", &n);
142   Buffer[n] = 1; // expected-warning {{Potential out of bound access }}
143 }
144 
145 namespace gh114270 {
146 class Empty {};
147 class Aggr {
148 public:
149   int data;
150 };
151 
152 void top() {
153   int Int = mySource1<int>();
154   clang_analyzer_isTainted(Int); // expected-warning {{YES}}
155 
156   Empty E = mySource1<Empty>();
157   clang_analyzer_isTainted(E); // expected-warning {{YES}}
158 
159   Aggr A = mySource1<Aggr>();
160   clang_analyzer_isTainted(A);      // expected-warning {{YES}}
161   clang_analyzer_isTainted(A.data); // expected-warning {{YES}}
162 }
163 } // namespace gh114270
164