273e674252
This patch introduces the namespaces for the configured functions and also enables the use of the member functions. I added an optional Scope field for every configured function. Functions without Scope match for every function regardless of the namespace. Functions with Scope will match if the full name of the function starts with the Scope. Multiple functions can exist with the same name. Differential Revision: https://reviews.llvm.org/D70878
127 lines
3.1 KiB
C++
127 lines
3.1 KiB
C++
// 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();
|
|
|
|
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 {{Out of bound memory access }}
|
|
}
|
|
|
|
void testConfigurationNamespacePropagation2() {
|
|
int x = mySource3();
|
|
Buffer[x] = 1; // no-warning
|
|
|
|
int y = myNamespace::mySource3();
|
|
Buffer[y] = 1; // expected-warning {{Out of bound memory access }}
|
|
}
|
|
|
|
void testConfigurationNamespacePropagation3() {
|
|
int x = myAnotherNamespace::mySource3();
|
|
Buffer[x] = 1; // expected-warning {{Out of bound memory access }}
|
|
}
|
|
|
|
void testConfigurationNamespacePropagation4() {
|
|
int x;
|
|
// Configured functions without scope should match for all function.
|
|
myNamespace::myScanf("%d", &x);
|
|
Buffer[x] = 1; // expected-warning {{Out of bound memory 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 {{Out of bound memory 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 {{Out of bound memory access }}
|
|
}
|