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 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 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 54 void testConfigurationNamespacePropagation3() { 55 int x = myAnotherNamespace::mySource3(); 56 Buffer[x] = 1; // expected-warning {{Out of bound memory access }} 57 } 58 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 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 78 void testConfigurationNamespaceFilter2() { 79 int x = mySource1(); 80 if (myAnotherNamespace::isOutOfRange2(&x)) 81 return; 82 Buffer[x] = 1; // no-warning 83 } 84 85 void testConfigurationNamespaceFilter3() { 86 int x = mySource1(); 87 if (myNamespace::isOutOfRange(&x)) 88 return; 89 Buffer[x] = 1; // no-warning 90 } 91 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 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 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 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