Files
TheRock/compiler/amd-llvm/clang/test/Analysis/taint-generic.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

211 lines
5.7 KiB
C++

// RUN: %clang_analyze_cc1 -std=c++11 -Wno-format-security \
// RUN: -analyzer-checker=core,optin.taint,security.ArrayBound,debug.ExprInspection \
// RUN: -analyzer-config optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml \
// RUN: -verify %s
template <typename T> void clang_analyzer_isTainted(T);
#define BUFSIZE 10
int Buffer[BUFSIZE];
int scanf(const char*, ...);
template <typename T = int> T 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 }}
}
namespace gh114270 {
class Empty {};
class Aggr {
public:
int data;
};
void top() {
int Int = mySource1<int>();
clang_analyzer_isTainted(Int); // expected-warning {{YES}}
// It's fine to not propagate taint to empty classes, since they don't have any data members.
Empty E = mySource1<Empty>();
clang_analyzer_isTainted(E); // expected-warning {{NO}}
Aggr A = mySource1<Aggr>();
// FIXME Ideally, both A and A.data should be tainted. However, the
// implementation used by e5ac9145ba29 ([analyzer][taint] Recognize
// tainted LazyCompoundVals (4/4) (#115919), 2024-11-15) led to FPs and
// FNs in various scenarios and had to be reverted to fix #153782.
clang_analyzer_isTainted(A); // expected-warning {{NO}}
clang_analyzer_isTainted(A.data); // expected-warning {{YES}}
}
} // namespace gh114270
namespace format_attribute {
__attribute__((__format__ (__printf__, 1, 2)))
void log_freefunc(const char *fmt, ...);
void test_format_attribute_freefunc() {
int n;
fscanf(stdin, "%d", &n); // Get a tainted value.
log_freefunc("This number is suspicious: %d\n", n); // no-warning
}
struct Foo {
// When the format attribute is applied to a method, argumet '1' is the
// implicit `this`, so e.g. in this case argument '2' specifies `fmt`.
// Specifying '1' instead of '2' would produce a compilation error:
// "format attribute cannot specify the implicit this argument as the format string"
__attribute__((__format__ (__printf__, 2, 3)))
void log_method(const char *fmt, ...);
void test_format_attribute_method() {
int n;
fscanf(stdin, "%d", &n); // Get a tainted value.
// The analyzer used to misinterpret the parameter indices in the format
// attribute when the format attribute is applied to a method.
log_method("This number is suspicious: %d\n", n); // no-warning
}
__attribute__((__format__ (__printf__, 1, 2)))
static void log_static_method(const char *fmt, ...);
void test_format_attribute_static_method() {
int n;
fscanf(stdin, "%d", &n); // Get a tainted value.
log_static_method("This number is suspicious: %d\n", n); // no-warning
}
};
} // namespace format_attribute