brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.8 KiB · f4811ef Raw
275 lines · c
1// RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-checker=core,security.ArrayBound,debug.ExprInspection -verify %s2 3// Miscellaneous tests for `security.ArrayBound` where we only test the4// presence or absence of a bug report. If a test doesn't fit in a more5// specific file and doesn't need to verify the details of 'note' diagnostics,6// then it should be placed here.7 8void clang_analyzer_value(int);9 10// Tests doing an out-of-bounds access after the end of an array using:11// - constant integer index12// - constant integer size for buffer13void test1(int x) {14  int buf[100];15  buf[100] = 1; // expected-warning{{Out of bound access to memory}}16}17 18void test1_ok(int x) {19  int buf[100];20  buf[99] = 1; // no-warning21}22 23const char test1_strings_underrun(int x) {24  const char *mystr = "mary had a little lamb";25  return mystr[-1]; // expected-warning{{Out of bound access to memory}}26}27 28const char test1_strings_overrun(int x) {29  const char *mystr = "mary had a little lamb";30  return mystr[1000];  // expected-warning{{Out of bound access to memory}}31}32 33const char test1_strings_ok(int x) {34  const char *mystr = "mary had a little lamb";35  return mystr[5]; // no-warning36}37 38// Tests doing an out-of-bounds access after the end of an array using:39// - indirect pointer to buffer40// - constant integer index41// - constant integer size for buffer42void test1_ptr(int x) {43  int buf[100];44  int *p = buf;45  p[101] = 1; // expected-warning{{Out of bound access to memory}}46}47 48void test1_ptr_ok(int x) {49  int buf[100];50  int *p = buf;51  p[99] = 1; // no-warning52}53 54// Tests doing an out-of-bounds access before the start of an array using:55// - indirect pointer to buffer, manipulated using simple pointer arithmetic56// - constant integer index57// - constant integer size for buffer58void test1_ptr_arith(int x) {59  int buf[100];60  int *p = buf;61  p = p + 100;62  p[0] = 1; // expected-warning{{Out of bound access to memory}}63}64 65void test1_ptr_arith_ok(int x) {66  int buf[100];67  int *p = buf;68  p = p + 99;69  p[0] = 1; // no-warning70}71 72void test1_ptr_arith_bad(int x) {73  int buf[100];74  int *p = buf;75  p = p + 99;76  p[1] = 1; // expected-warning{{Out of bound access to memory}}77}78 79void test1_ptr_arith_ok2(int x) {80  int buf[100];81  int *p = buf;82  p = p + 99;83  p[-1] = 1; // no-warning84}85 86// Tests doing an out-of-bounds access before the start of an array using:87// - constant integer index88// - constant integer size for buffer89void test2(int x) {90  int buf[100];91  buf[-1] = 1; // expected-warning{{Out of bound access to memory}}92}93 94// Tests doing an out-of-bounds access before the start of an array using:95// - indirect pointer to buffer96// - constant integer index97// - constant integer size for buffer98void test2_ptr(int x) {99  int buf[100];100  int *p = buf;101  p[-1] = 1; // expected-warning{{Out of bound access to memory}}102}103 104// Tests doing an out-of-bounds access before the start of an array using:105// - indirect pointer to buffer, manipulated using simple pointer arithmetic106// - constant integer index107// - constant integer size for buffer108void test2_ptr_arith(int x) {109  int buf[100];110  int *p = buf;111  --p;112  p[0] = 1; // expected-warning {{Out of bound access to memory preceding}}113}114 115// Tests doing an out-of-bounds access before the start of a multi-dimensional116// array using:117// - constant integer indices118// - constant integer sizes for the array119void test2_multi(int x) {120  int buf[100][100];121  buf[0][-1] = 1; // expected-warning{{Out of bound access to memory}}122}123 124// Tests doing an out-of-bounds access before the start of a multi-dimensional125// array using:126// - constant integer indices127// - constant integer sizes for the array128void test2_multi_b(int x) {129  int buf[100][100];130  buf[-1][0] = 1; // expected-warning{{Out of bound access to memory}}131}132 133void test2_multi_ok(int x) {134  int buf[100][100];135  buf[0][0] = 1; // no-warning136}137 138void test3(int x) {139  int buf[100];140  if (x < 0)141    buf[x] = 1; // expected-warning{{Out of bound access to memory}}142}143 144void test4(int x) {145  int buf[100];146  if (x > 99)147    buf[x] = 1; // expected-warning{{Out of bound access to memory}}148}149 150// Don't warn when indexing below the start of a symbolic region's whose151// base extent we don't know.152int *get_symbolic(void);153void test_underflow_symbolic(void) {154  int *buf = get_symbolic();155  buf[-1] = 0; // no-warning156}157 158// But warn if we understand the internal memory layout of a symbolic region.159typedef struct {160  int id;161  char name[256];162} user_t;163 164user_t *get_symbolic_user(void);165char test_underflow_symbolic_2() {166  user_t *user = get_symbolic_user();167  return user->name[-1]; // expected-warning{{Out of bound access to memory}}168}169 170void test_incomplete_struct(void) {171  extern struct incomplete incomplete;172  int *p = (int *)&incomplete;173  p[1] = 42; // no-warning174}175 176void test_extern_void(void) {177  extern void v;178  int *p = (int *)&v;179  p[1] = 42; // no-warning180}181 182struct incomplete;183char test_comparison_with_extent_symbol(struct incomplete *p) {184  // Previously this was reported as a (false positive) overflow error because185  // the extent symbol of the area pointed by `p` was an unsigned and the '-1'186  // was converted to its type by `evalBinOpNN`.187  return ((char *)p)[-1]; // no-warning188}189 190int table[256], small_table[128];191int test_cast_to_unsigned(signed char x) {192  unsigned char y = x;193  if (x >= 0)194    return x;195  // FIXME: Here the analyzer ignores the signed -> unsigned cast, and manages to196  // load a negative value from an unsigned variable.197  // The underlying issue is tracked by Github ticket #39492.198  clang_analyzer_value(y); // expected-warning {{8s:{ [-128, -1] } }}199  // However, a hack in the ArrayBound checker suppresses the false positive200  // underflow report that would be generated here.201  return table[y]; // no-warning202}203 204int test_cast_to_unsigned_overflow(signed char x) {205  unsigned char y = x;206  if (x >= 0)207    return x;208  // FIXME: As in 'test_cast_to_unsigned', the analyzer thinks that this209  // unsigned variable contains a negative value.210  clang_analyzer_value(y); // expected-warning {{8s:{ [-128, -1] } }}211  // FIXME: The following subscript expression should produce an overflow212  // report (because negative signed char corresponds to unsigned char >= 128);213  // but the hack in ArrayBound just silences reports and cannot "restore" the214  // real execution paths.215  return small_table[y]; // no-warning216}217 218int test_negative_offset_with_unsigned_idx(void) {219  // An example where the subscript operator uses an unsigned index, but the220  // underflow report is still justified.221  int *p = table - 10;222  unsigned idx = 2u;223  return p[idx]; // expected-warning {{Out of bound access to memory preceding}}224}225 226struct three_words { int c[3]; };227struct seven_words { int c[7]; };228void partially_in_bounds(void) {229  struct seven_words c;230  struct three_words a, *p = (struct three_words *)&c;231  p[0] = a; // no-warning232  p[1] = a; // no-warning233  p[2] = a; // should warn234  // FIXME: This is an overflow, but currently security.ArrayBound only checks235  // that the _beginning_ of the accessed element is within bounds.236}237 238void vla(int a) {239  if (a == 5) {240    int x[a];241    x[4] = 4; // no-warning242    x[5] = 5; // expected-warning{{Out of bound access}}243  }244}245 246void sizeof_vla(int a) {247  // FIXME: VLA modeling is not good enough to cover this case.248  if (a == 5) {249    char x[a];250    int y[sizeof(x)];251    y[4] = 4; // no-warning252    y[5] = 5; // should be {{Out of bounds access}}253  }254}255 256void sizeof_vla_2(int a) {257  // FIXME: VLA modeling is not good enough to cover this case.258  if (a == 5) {259    char x[a];260    int y[sizeof(x) / sizeof(char)];261    y[4] = 4; // no-warning262    y[5] = 5; // should be {{Out of bounds access}}263  }264}265 266void sizeof_vla_3(int a) {267  // FIXME: VLA modeling is not good enough to cover this case.268  if (a == 5) {269    char x[a];270    int y[sizeof(*&*&*&x)];271    y[4] = 4; // no-warning272    y[5] = 5; // should be {{Out of bounds access}}273  }274}275