brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.7 KiB · 4b8d9ab Raw
211 lines · cpp
1// RUN: %clang_analyze_cc1 -std=c++11 -Wno-format-security \2// RUN:   -analyzer-checker=core,optin.taint,security.ArrayBound,debug.ExprInspection \3// RUN:   -analyzer-config optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml \4// RUN:   -verify %s5 6template <typename T> void clang_analyzer_isTainted(T);7 8#define BUFSIZE 109int Buffer[BUFSIZE];10 11int scanf(const char*, ...);12template <typename T = int> T mySource1();13int mySource3();14 15typedef struct _FILE FILE;16extern "C" {17extern FILE *stdin;18}19int fscanf(FILE *stream, const char *format, ...);20 21bool isOutOfRange2(const int*);22 23void mySink2(int);24 25// Test configuration26namespace myNamespace {27  void scanf(const char*, ...);28  void myScanf(const char*, ...);29  int mySource3();30 31  bool isOutOfRange(const int*);32  bool isOutOfRange2(const int*);33 34  void mySink(int, int, int);35  void mySink2(int);36}37 38namespace myAnotherNamespace {39  int mySource3();40 41  bool isOutOfRange2(const int*);42 43  void mySink2(int);44}45 46void testConfigurationNamespacePropagation1() {47  int x;48  // The built-in functions should be matched only for functions in49  // the global namespace50  myNamespace::scanf("%d", &x);51  Buffer[x] = 1; // no-warning52 53  scanf("%d", &x);54  Buffer[x] = 1; // expected-warning {{Potential out of bound access }}55}56 57void testConfigurationNamespacePropagation2() {58  int x = mySource3();59  Buffer[x] = 1; // no-warning60 61  int y = myNamespace::mySource3();62  Buffer[y] = 1; // expected-warning {{Potential out of bound access }}63}64 65void testConfigurationNamespacePropagation3() {66  int x = myAnotherNamespace::mySource3();67  Buffer[x] = 1; // expected-warning {{Potential out of bound access }}68}69 70void testConfigurationNamespacePropagation4() {71  int x;72  // Configured functions without scope should match for all function.73  myNamespace::myScanf("%d", &x);74  Buffer[x] = 1; // expected-warning {{Potential out of bound access }}75}76 77void testConfigurationNamespaceFilter1() {78  int x = mySource1();79  if (myNamespace::isOutOfRange2(&x))80    return;81  Buffer[x] = 1; // no-warning82 83  int y = mySource1();84  if (isOutOfRange2(&y))85    return;86  Buffer[y] = 1; // expected-warning {{Potential out of bound access }}87}88 89void testConfigurationNamespaceFilter2() {90  int x = mySource1();91  if (myAnotherNamespace::isOutOfRange2(&x))92    return;93  Buffer[x] = 1; // no-warning94}95 96void testConfigurationNamespaceFilter3() {97  int x = mySource1();98  if (myNamespace::isOutOfRange(&x))99    return;100  Buffer[x] = 1; // no-warning101}102 103void testConfigurationNamespaceSink1() {104  int x = mySource1();105  mySink2(x); // no-warning106 107  int y = mySource1();108  myNamespace::mySink2(y);109  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}110}111 112void testConfigurationNamespaceSink2() {113  int x = mySource1();114  myAnotherNamespace::mySink2(x);115  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}116}117 118void testConfigurationNamespaceSink3() {119  int x = mySource1();120  myNamespace::mySink(x, 0, 1);121  // expected-warning@-1 {{Untrusted data is passed to a user-defined sink}}122}123 124struct Foo {125    void scanf(const char*, int*);126    void myMemberScanf(const char*, int*);127};128 129void testConfigurationMemberFunc() {130  int x;131  Foo foo;132  foo.scanf("%d", &x);133  Buffer[x] = 1; // no-warning134 135  foo.myMemberScanf("%d", &x);136  Buffer[x] = 1; // expected-warning {{Potential out of bound access }}137}138 139void testReadingFromStdin(char **p) {140  int n;141  fscanf(stdin, "%d", &n);142  Buffer[n] = 1; // expected-warning {{Potential out of bound access }}143}144 145namespace gh114270 {146class Empty {};147class Aggr {148public:149  int data;150};151 152void top() {153  int Int = mySource1<int>();154  clang_analyzer_isTainted(Int); // expected-warning {{YES}}155 156  // It's fine to not propagate taint to empty classes, since they don't have any data members.157  Empty E = mySource1<Empty>();158  clang_analyzer_isTainted(E); // expected-warning {{NO}}159 160  Aggr A = mySource1<Aggr>();161  // FIXME Ideally, both A and A.data should be tainted. However, the162  //       implementation used by e5ac9145ba29 ([analyzer][taint] Recognize163  //       tainted LazyCompoundVals (4/4) (#115919), 2024-11-15) led to FPs and164  //       FNs in various scenarios and had to be reverted to fix #153782.165  clang_analyzer_isTainted(A);      // expected-warning {{NO}}166  clang_analyzer_isTainted(A.data); // expected-warning {{YES}}167}168} // namespace gh114270169 170 171namespace format_attribute {172__attribute__((__format__ (__printf__, 1, 2)))173void log_freefunc(const char *fmt, ...);174 175void test_format_attribute_freefunc() {176  int n;177  fscanf(stdin, "%d", &n); // Get a tainted value.178                           179  log_freefunc("This number is suspicious: %d\n", n); // no-warning180}181 182struct Foo {183  // When the format attribute is applied to a method, argumet '1' is the184  // implicit `this`, so e.g. in this case argument '2' specifies `fmt`.185  // Specifying '1' instead of '2' would produce a compilation error:186  // "format attribute cannot specify the implicit this argument as the format string"187  __attribute__((__format__ (__printf__, 2, 3)))188  void log_method(const char *fmt, ...);189 190  void test_format_attribute_method() {191    int n;192    fscanf(stdin, "%d", &n); // Get a tainted value.193                             194    // The analyzer used to misinterpret the parameter indices in the format195    // attribute when the format attribute is applied to a method.196    log_method("This number is suspicious: %d\n", n); // no-warning197  }198 199  __attribute__((__format__ (__printf__, 1, 2)))200  static void log_static_method(const char *fmt, ...);201 202  void test_format_attribute_static_method() {203    int n;204    fscanf(stdin, "%d", &n); // Get a tainted value.205                             206    log_static_method("This number is suspicious: %d\n", n); // no-warning207  }208};209 210} // namespace format_attribute211