1 // RUN: %clang_analyze_cc1  -analyzer-checker=alpha.security.taint,core,alpha.security.ArrayBoundV2 -analyzer-config alpha.security.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify -std=c++11 %s
2 
3 #define BUFSIZE 10
4 int Buffer[BUFSIZE];
5 
6 int scanf(const char*, ...);
7 int mySource1();
8 int mySource3();
9 
10 bool isOutOfRange2(const int*);
11 
12 void mySink2(int);
13 
14 // Test configuration
15 namespace myNamespace {
16   void scanf(const char*, ...);
17   void myScanf(const char*, ...);
18   int mySource3();
19 
20   bool isOutOfRange(const int*);
21   bool isOutOfRange2(const int*);
22 
23   void mySink(int, int, int);
24   void mySink2(int);
25 }
26 
27 namespace myAnotherNamespace {
28   int mySource3();
29 
30   bool isOutOfRange2(const int*);
31 
32   void mySink2(int);
33 }
34 
testConfigurationNamespacePropagation1()35 void testConfigurationNamespacePropagation1() {
36   int x;
37   // The built-in functions should be matched only for functions in
38   // the global namespace
39   myNamespace::scanf("%d", &x);
40   Buffer[x] = 1; // no-warning
41 
42   scanf("%d", &x);
43   Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
44 }
45 
testConfigurationNamespacePropagation2()46 void testConfigurationNamespacePropagation2() {
47   int x = mySource3();
48   Buffer[x] = 1; // no-warning
49 
50   int y = myNamespace::mySource3();
51   Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
52 }
53 
testConfigurationNamespacePropagation3()54 void testConfigurationNamespacePropagation3() {
55   int x = myAnotherNamespace::mySource3();
56   Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
57 }
58 
testConfigurationNamespacePropagation4()59 void testConfigurationNamespacePropagation4() {
60   int x;
61   // Configured functions without scope should match for all function.
62   myNamespace::myScanf("%d", &x);
63   Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
64 }
65 
testConfigurationNamespaceFilter1()66 void testConfigurationNamespaceFilter1() {
67   int x = mySource1();
68   if (myNamespace::isOutOfRange2(&x))
69     return;
70   Buffer[x] = 1; // no-warning
71 
72   int y = mySource1();
73   if (isOutOfRange2(&y))
74     return;
75   Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
76 }
77 
testConfigurationNamespaceFilter2()78 void testConfigurationNamespaceFilter2() {
79   int x = mySource1();
80   if (myAnotherNamespace::isOutOfRange2(&x))
81     return;
82   Buffer[x] = 1; // no-warning
83 }
84 
testConfigurationNamespaceFilter3()85 void testConfigurationNamespaceFilter3() {
86   int x = mySource1();
87   if (myNamespace::isOutOfRange(&x))
88     return;
89   Buffer[x] = 1; // no-warning
90 }
91 
testConfigurationNamespaceSink1()92 void testConfigurationNamespaceSink1() {
93   int x = mySource1();
94   mySink2(x); // no-warning
95 
96   int y = mySource1();
97   myNamespace::mySink2(y);
98   // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
99 }
100 
testConfigurationNamespaceSink2()101 void testConfigurationNamespaceSink2() {
102   int x = mySource1();
103   myAnotherNamespace::mySink2(x);
104   // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
105 }
106 
testConfigurationNamespaceSink3()107 void testConfigurationNamespaceSink3() {
108   int x = mySource1();
109   myNamespace::mySink(x, 0, 1);
110   // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}
111 }
112 
113 struct Foo {
114     void scanf(const char*, int*);
115     void myMemberScanf(const char*, int*);
116 };
117 
testConfigurationMemberFunc()118 void testConfigurationMemberFunc() {
119   int x;
120   Foo foo;
121   foo.scanf("%d", &x);
122   Buffer[x] = 1; // no-warning
123 
124   foo.myMemberScanf("%d", &x);
125   Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
126 }
127