brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.3 KiB · bffd5d9 Raw
216 lines · c
1// RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-output=text        \2// RUN:     -analyzer-checker=core,security.ArrayBound,unix.Malloc,optin.taint -verify %s3 4// When the checker security.ArrayBound encounters an array subscript operation5// that _may be_ in bounds, it assumes that indexing _is_ in bound. These6// assumptions will be reported to the user if the execution path leads to a7// bug report (made by any checker) and the symbol which was constrainted by8// the assumption is marked as interesting (with `markInteresting` or9// indirectly via `trackExpressionValue`) in that bug report.10//11// This test file validates the content of these note tags which describe the12// assumptions for the user.13 14int TenElements[10];15 16int irrelevantAssumptions(int arg) {17  int a = TenElements[arg];18  // Here the analyzer assumes that `arg` is in bounds, but doesn't report this19  // because `arg` is not interesting for the bug.20  int b = TenElements[13];21  // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}22  // expected-note@-2 {{Access of 'TenElements' at index 13, while it holds only 10 'int' elements}}23  return a + b;24}25 26 27int assumingBoth(int arg) {28  int a = TenElements[arg];29  // expected-note@-1 {{Assuming index is non-negative and less than 10, the number of 'int' elements in 'TenElements'}}30  int b = TenElements[arg]; // no additional note, we already assumed that 'arg' is in bounds31  int c = TenElements[arg + 10];32  // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}33  // expected-note@-2 {{Access of 'TenElements' at an overflowing index, while it holds only 10 'int' elements}}34  return a + b + c;35}36 37int assumingBothPointerToMiddle(int arg) {38  // If we're accessing an TenElements through a pointer pointing to its middle, the checker39  // will speak about the "byte offset" measured from the beginning of the TenElements.40  int *p = TenElements + 2;41  int a = p[arg];42  // expected-note@-1 {{Assuming byte offset is non-negative and less than 40, the extent of 'TenElements'}}43 44  int b = TenElements[arg]; // This is normal access, and only the lower bound is new.45  int c = TenElements[arg + 10];46  // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}47  // expected-note@-2 {{Access of 'TenElements' at an overflowing index, while it holds only 10 'int' elements}}48  return a + b + c;49}50 51int assumingLower(int arg) {52  // expected-note@+2 {{Assuming 'arg' is < 10}}53  // expected-note@+1 {{Taking false branch}}54  if (arg >= 10)55    return 0;56  int a = TenElements[arg];57  // expected-note@-1 {{Assuming index is non-negative}}58  int b = TenElements[arg + 10];59  // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}60  // expected-note@-2 {{Access of 'TenElements' at an overflowing index, while it holds only 10 'int' elements}}61  return a + b;62}63 64int assumingUpper(int arg) {65  // expected-note@+2 {{Assuming 'arg' is >= 0}}66  // expected-note@+1 {{Taking false branch}}67  if (arg < 0)68    return 0;69  int a = TenElements[arg];70  // expected-note@-1 {{Assuming index is less than 10, the number of 'int' elements in 'TenElements'}}71  int b = TenElements[arg - 10];72  // expected-warning@-1 {{Out of bound access to memory preceding 'TenElements'}}73  // expected-note@-2 {{Access of 'TenElements' at a negative index}}74  return a + b;75}76 77int assumingUpperIrrelevant(int arg) {78  // FIXME: The assumption "assuming index is less than 10" is printed because79  // it's assuming something about the interesting variable `arg`; however,80  // it's irrelevant because in this testcase the out of bound access is81  // deduced from the _lower_ bound on `arg`. Currently the analyzer cannot82  // filter out assumptions that are logically irrelevant but "touch"83  // interesting symbols; eventually it would be good to add support for this.84 85  // expected-note@+2 {{Assuming 'arg' is >= 0}}86  // expected-note@+1 {{Taking false branch}}87  if (arg < 0)88    return 0;89  int a = TenElements[arg];90  // expected-note@-1 {{Assuming index is less than 10, the number of 'int' elements in 'TenElements'}}91  int b = TenElements[arg + 10];92  // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}93  // expected-note@-2 {{Access of 'TenElements' at an overflowing index, while it holds only 10 'int' elements}}94  return a + b;95}96 97int assumingUpperUnsigned(unsigned arg) {98  int a = TenElements[arg];99  // expected-note@-1 {{Assuming index is less than 10, the number of 'int' elements in 'TenElements'}}100  int b = TenElements[(int)arg - 10];101  // expected-warning@-1 {{Out of bound access to memory preceding 'TenElements'}}102  // expected-note@-2 {{Access of 'TenElements' at a negative index}}103  return a + b;104}105 106int assumingNothing(unsigned arg) {107  // expected-note@+2 {{Assuming 'arg' is < 10}}108  // expected-note@+1 {{Taking false branch}}109  if (arg >= 10)110    return 0;111  int a = TenElements[arg]; // no note here, we already know that 'arg' is in bounds112  int b = TenElements[(int)arg - 10];113  // expected-warning@-1 {{Out of bound access to memory preceding 'TenElements'}}114  // expected-note@-2 {{Access of 'TenElements' at a negative index}}115  return a + b;116}117 118short assumingConvertedToCharP(int arg) {119  // When indices are reported, the note will use the element type that's the120  // result type of the subscript operator.121  char *cp = (char*)TenElements;122  char a = cp[arg];123  // expected-note@-1 {{Assuming index is non-negative and less than 40, the number of 'char' elements in 'TenElements'}}124  char b = cp[arg]; // no additional note, we already assumed that 'arg' is in bounds125  char c = cp[arg + 40];126  // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}127  // expected-note@-2 {{Access of 'TenElements' at an overflowing index, while it holds only 40 'char' elements}}128  return a + b + c;129}130 131struct foo {132  int num;133  char a[8];134  char b[5];135};136 137int assumingConvertedToIntP(struct foo f, int arg) {138  // When indices are reported, the note will use the element type that's the139  // result type of the subscript operator.140  int a = ((int*)(f.a))[arg];141  // expected-note@-1 {{Assuming index is non-negative and less than 2, the number of 'int' elements in 'f.a'}}142  // However, if the extent of the memory region is not divisible by the143  // element size, the checker measures the offset and extent in bytes.144  int b = ((int*)(f.b))[arg];145  // expected-note@-1 {{Assuming byte offset is less than 5, the extent of 'f.b'}}146  int c = TenElements[arg-2];147  // expected-warning@-1 {{Out of bound access to memory preceding 'TenElements'}}148  // expected-note@-2 {{Access of 'TenElements' at a negative index}}149  return a + b + c;150}151 152int assumingPlainOffset(struct foo f, int arg) {153  // This TC is intended to check the corner case that the checker prints the154  // shorter "offset" instead of "byte offset" when it's irrelevant that the155  // offset is measured in bytes.156 157  // expected-note@+2 {{Assuming 'arg' is < 2}}158  // expected-note@+1 {{Taking false branch}}159  if (arg >= 2)160    return 0;161 162  int b = ((int*)(f.b))[arg];163  // expected-note@-1 {{Assuming byte offset is non-negative and less than 5, the extent of 'f.b'}}164  // FIXME: this should be {{Assuming offset is non-negative}}165  // but the current simplification algorithm doesn't realize that arg <= 1166  // implies that the byte offset arg*4 will be less than 5.167 168  int c = TenElements[arg+10];169  // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}170  // expected-note@-2 {{Access of 'TenElements' at an overflowing index, while it holds only 10 'int' elements}}171  return b + c;172}173 174typedef __typeof(sizeof(int)) size_t;175void *malloc(size_t size);176void free(void *ptr);177 178int assumingExtent(int arg) {179  // Verify that the assumption note is printed when the extent is interesting180  // (even if the index isn't interesting).181  int *mem = (int*)malloc(arg);182 183  mem[12] = 123;184  // expected-note@-1 {{Assuming index '12' is less than the number of 'int' elements in the heap area}}185 186  free(mem);187 188  return TenElements[arg];189  // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}190  // expected-note@-2 {{Access of 'TenElements' at an overflowing index, while it holds only 10 'int' elements}}191}192 193int *extentInterestingness(int arg) {194  // Verify that in an out-of-bounds access issue the extent is marked as195  // interesting (so assumptions about its value are printed).196  int *mem = (int*)malloc(arg);197 198  TenElements[arg] = 123;199  // expected-note@-1 {{Assuming index is non-negative and less than 10, the number of 'int' elements in 'TenElements'}}200 201  return &mem[12];202  // expected-warning@-1 {{Out of bound access to memory after the end of the heap area}}203  // expected-note@-2 {{Access of 'int' element in the heap area at index 12}}204}205 206int triggeredByAnyReport(int arg) {207  // Verify that note tags explaining the assumptions made by ArrayBound are208  // not limited to ArrayBound reports but will appear on any bug report (that209  // marks the relevant symbol as interesting).210  TenElements[arg + 10] = 8;211  // expected-note@-1 {{Assuming index is non-negative and less than 10, the number of 'int' elements in 'TenElements'}}212  return 1024 >> arg;213  // expected-warning@-1 {{Right operand is negative in right shift}}214  // expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}215}216