190 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \2// RUN: -fsafe-buffer-usage-suggestions -verify %s3 4using size_t = __typeof(sizeof(int));5 6namespace std {7 class type_info;8 class bad_cast;9 class bad_typeid;10 11 template <typename T> class span {12 13 private:14 T *elements;15 size_t size_;16 17 public:18 span(T *, size_t){}19 20 constexpr T* data() const noexcept {21 return elements;22 }23 24 constexpr size_t size() const noexcept {25 return size_;26 }27 28 };29}30 31struct A {32 [[clang::unsafe_buffer_usage]]33 int *ptr;34 35 size_t sz;36};37 38struct B {39 A a;40 41 [[clang::unsafe_buffer_usage]]42 int buf[];43};44 45struct D { 46 [[clang::unsafe_buffer_usage]]47 int *ptr, *ptr2;48 49 [[clang::unsafe_buffer_usage]]50 int buf[10];51 52 size_t sz;53 54};55 56void foo(int *ptr);57 58void foo_safe(std::span<int> sp);59 60int* test_atribute_struct(A a) {61 int b = *(a.ptr); //expected-warning{{field 'ptr' prone to unsafe buffer manipulation}}62 a.sz++;63 // expected-warning@+1{{unsafe pointer arithmetic}}64 return a.ptr++; //expected-warning{{field 'ptr' prone to unsafe buffer manipulation}}65}66 67void test_attribute_field_deref_chain(B b) {68 int *ptr = b.a.ptr;//expected-warning{{field 'ptr' prone to unsafe buffer manipulation}}69 foo(b.buf); //expected-warning{{field 'buf' prone to unsafe buffer manipulation}}70}71 72void test_writes_from_span(std::span<int> sp) {73 A a;74 a.ptr = sp.data(); //expected-warning{{field 'ptr' prone to unsafe buffer manipulation}}75 a.sz = sp.size();76 77 a.ptr = nullptr; // expected-warning{{field 'ptr' prone to unsafe buffer manipulation}}78}79 80void test_reads_to_span(A a, A b) {81 //expected-warning@+1{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}}82 std::span<int> sp {a.ptr, a.sz}; //expected-warning{{field 'ptr' prone to unsafe buffer manipulation}}83 84 // expected-warning@+1 3{{field 'ptr' prone to unsafe buffer manipulation}}85 if(a.ptr != nullptr && a.ptr != b.ptr) {86 foo_safe(sp);87 }88 89}90 91void test_attribute_multiple_fields (D d) {92 int *p =d.ptr; //expected-warning{{field 'ptr' prone to unsafe buffer manipulation}}93 p = d.ptr2; //expected-warning{{field 'ptr2' prone to unsafe buffer manipulation}}94 95 p = d.buf; //expected-warning{{field 'buf' prone to unsafe buffer manipulation}}96 97 int v = d.buf[0]; //expected-warning{{field 'buf' prone to unsafe buffer manipulation}}98 99 v = d.buf[5]; //expected-warning{{field 'buf' prone to unsafe buffer manipulation}}100}101 102template <typename T>103struct TemplateArray {104 [[clang::unsafe_buffer_usage]]105 T *buf;106 107 [[clang::unsafe_buffer_usage]]108 size_t sz;109};110 111 112void test_struct_template (TemplateArray<int> t) {113 int *p = t.buf; //expected-warning{{field 'buf' prone to unsafe buffer manipulation}}114 size_t s = t.sz; //expected-warning{{field 'sz' prone to unsafe buffer manipulation}}115}116 117class R {118 [[clang::unsafe_buffer_usage]]119 int *array;120 121 public:122 int* getArray() {123 return array; //expected-warning{{field 'array' prone to unsafe buffer manipulation}}124 }125 126 void setArray(int *arr) {127 array = arr; //expected-warning{{field 'array' prone to unsafe buffer manipulation}}128 }129};130 131template<class P>132class Q {133 [[clang::unsafe_buffer_usage]]134 P *array;135 136 public:137 P* getArray() {138 return array; //expected-warning{{field 'array' prone to unsafe buffer manipulation}}139 }140 141 void setArray(P *arr) {142 array = arr; //expected-warning{{field 'array' prone to unsafe buffer manipulation}}143 }144};145 146void test_class_template(Q<R> q) {147 q.getArray();148 q.setArray(nullptr);149}150 151struct AnonSFields {152 struct {153 [[clang::unsafe_buffer_usage]]154 int a;155 };156};157 158void test_anon_struct_fields(AnonSFields anon) {159 int val = anon.a; //expected-warning{{field 'a' prone to unsafe buffer manipulation}}160}161 162union Union {163 [[clang::unsafe_buffer_usage]]164 int *ptr1;165 166 int ptr2;167};168 169struct C {170 Union ptr;171};172 173void test_attribute_union(C c) {174 int *p = c.ptr.ptr1; //expected-warning{{field 'ptr1' prone to unsafe buffer manipulation}}175 176 int address = c.ptr.ptr2;177}178 179struct AnonFields2 { 180 [[clang::unsafe_buffer_usage]] 181 struct { 182 int a; 183 }; 184};185 186void test_anon_struct(AnonFields2 af) {187 int val = af.a; // No warning here, as the attribute is not explicitly attached to field 'a'188 val++;189}190