1 // RUN: %clang_cc1 -std=c++20 -Wno-everything -Wunsafe-buffer-usage \ 2 // RUN: -fsafe-buffer-usage-suggestions \ 3 // RUN: -verify %s 4 5 // CHECK-NOT: [-Wunsafe-buffer-usage] 6 7 8 void foo(unsigned idx) { 9 int buffer[10]; // expected-warning{{'buffer' is an unsafe buffer that does not perform bounds checks}} 10 // expected-note@-1{{change type of 'buffer' to 'std::array' to label it for hardening}} 11 buffer[idx] = 0; // expected-note{{used in buffer access here}} 12 } 13 14 int global_buffer[10]; // expected-warning{{'global_buffer' is an unsafe buffer that does not perform bounds checks}} 15 void foo2(unsigned idx) { 16 global_buffer[idx] = 0; // expected-note{{used in buffer access here}} 17 } 18 19 struct Foo { 20 int member_buffer[10]; 21 }; 22 void foo2(Foo& f, unsigned idx) { 23 f.member_buffer[idx] = 0; // expected-warning{{unsafe buffer access}} 24 } 25 26 void constant_idx_safe(unsigned idx) { 27 int buffer[10]; 28 buffer[9] = 0; 29 } 30 31 void constant_idx_safe0(unsigned idx) { 32 int buffer[10]; 33 buffer[0] = 0; 34 } 35 36 void constant_idx_unsafe(unsigned idx) { 37 int buffer[10]; // expected-warning{{'buffer' is an unsafe buffer that does not perform bounds checks}} 38 // expected-note@-1{{change type of 'buffer' to 'std::array' to label it for hardening}} 39 buffer[10] = 0; // expected-note{{used in buffer access here}} 40 } 41 42 void constant_id_string(unsigned idx) { 43 char safe_char = "abc"[1]; // no-warning 44 safe_char = ""[0]; 45 safe_char = "\0"[0]; 46 47 char abcd[5] = "abc"; 48 abcd[2]; // no-warning 49 50 char unsafe_char = "abc"[3]; 51 unsafe_char = "abc"[-1]; //expected-warning{{unsafe buffer access}} 52 unsafe_char = ""[1]; //expected-warning{{unsafe buffer access}} 53 unsafe_char = ""[idx]; //expected-warning{{unsafe buffer access}} 54 } 55 56 typedef float Float4x4[4][4]; 57 58 // expected-warning@+1 {{'matrix' is an unsafe buffer that does not perform bounds checks}} 59 float two_dimension_array(Float4x4& matrix, unsigned idx) { 60 // expected-warning@+1{{unsafe buffer access}} 61 float a = matrix[0][4]; 62 63 a = matrix[0][3]; 64 65 // expected-note@+1{{used in buffer access here}} 66 a = matrix[4][0]; 67 68 a = matrix[idx][0]; // expected-note{{used in buffer access here}} 69 70 a = matrix[0][idx]; //expected-warning{{unsafe buffer access}} 71 72 a = matrix[idx][idx]; //expected-warning{{unsafe buffer access}} // expected-note{{used in buffer access here}} 73 74 return matrix[1][1]; 75 } 76 77 typedef float Float2x3x4[2][3][4]; 78 float multi_dimension_array(Float2x3x4& matrix) { 79 float *f = matrix[0][2]; 80 return matrix[1][2][3]; 81 } 82 83 char array_strings[][11] = { 84 "Apple", "Banana", "Cherry", "Date", "Elderberry" 85 }; 86 87 char array_string[] = "123456"; 88 89 char access_strings() { 90 char c = array_strings[0][4]; 91 c = array_strings[3][10]; 92 c = array_string[5]; 93 return c; 94 } 95 96 struct T { 97 int array[10]; 98 }; 99 100 const int index = 1; 101 102 constexpr int get_const(int x) { 103 if(x < 3) 104 return ++x; 105 else 106 return x + 5; 107 }; 108 109 void array_indexed_const_expr(unsigned idx) { 110 // expected-note@+2 {{change type of 'arr' to 'std::array' to label it for hardening}} 111 // expected-warning@+1{{'arr' is an unsafe buffer that does not perform bounds checks}} 112 int arr[10]; 113 arr[sizeof(int)] = 5; 114 115 int array[sizeof(T)]; 116 array[sizeof(int)] = 5; 117 array[sizeof(T) -1 ] = 3; 118 119 int k = arr[6 & 5]; 120 k = arr[2 << index]; 121 k = arr[8 << index]; // expected-note {{used in buffer access here}} 122 k = arr[16 >> 1]; 123 k = arr[get_const(index)]; 124 k = arr[get_const(5)]; // expected-note {{used in buffer access here}} 125 k = arr[get_const(4)]; 126 } 127