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