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