================ @@ -0,0 +1,180 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \ +// RUN: -fsafe-buffer-usage-suggestions -verify %s + +using size_t = __typeof(sizeof(int)); + +namespace std { + class type_info; + class bad_cast; + class bad_typeid; + + template <typename T> class span { + + private: + T *elements; + size_t size_; + + public: + span(T *, size_t){} + + constexpr T* data() const noexcept { + return elements; + } + + constexpr size_t size() const noexcept { + return size_; + } + + }; +} + +struct A { + [[clang::unsafe_buffer_usage]] + int *ptr; + + size_t sz; +}; + +struct B { + A a; + + [[clang::unsafe_buffer_usage]] + int buf[]; +}; + +struct D { + [[clang::unsafe_buffer_usage]] + int *ptr, *ptr2; + + [[clang::unsafe_buffer_usage]] + int buf[10]; + + size_t sz; + +}; + +void foo(int *ptr); + +void foo_safe(std::span<int> sp); + +int* test_atribute_struct(A a) { + int b = *(a.ptr); //expected-warning{{field 'ptr' prone to unsafe buffer manipulation}} + a.sz++; + // expected-warning@+1{{unsafe pointer arithmetic}} + return a.ptr++; //expected-warning{{field 'ptr' prone to unsafe buffer manipulation}} +} + +void test_attribute_field_deref_chain(B b) { + int *ptr = b.a.ptr;//expected-warning{{field 'ptr' prone to unsafe buffer manipulation}} + foo(b.buf); //expected-warning{{field 'buf' prone to unsafe buffer manipulation}} +} + +void test_safe_writes(std::span<int> sp) { + A a; + // TODO: We should not warn for safe assignments from hardened types + a.ptr = sp.data(); //expected-warning{{field 'ptr' prone to unsafe buffer manipulation}} + a.sz = sp.size(); + + a.ptr = nullptr; // expected-warning{{field 'ptr' prone to unsafe buffer manipulation}} +} + +void test_safe_reads(A a, A b) { + //expected-warning@+1{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} + std::span<int> sp {a.ptr, a.sz}; //expected-warning{{field 'ptr' prone to unsafe buffer manipulation}} + + // expected-warning@+1 3{{field 'ptr' prone to unsafe buffer manipulation}} + if(a.ptr != nullptr && a.ptr != b.ptr) { + foo_safe(sp); + } + +} + +void test_attribute_multiple_fields (D d) { + int *p =d.ptr; //expected-warning{{field 'ptr' prone to unsafe buffer manipulation}} + p = d.ptr2; //expected-warning{{field 'ptr2' prone to unsafe buffer manipulation}} + + p = d.buf; //expected-warning{{field 'buf' prone to unsafe buffer manipulation}} + + int v = d.buf[0]; //expected-warning{{field 'buf' prone to unsafe buffer manipulation}} + + //expected-warning@+1{{unsafe buffer access}} + v = d.buf[5]; //expected-warning{{field 'buf' prone to unsafe buffer manipulation}} +} + +template <typename T> +struct TemplateArray { + [[clang::unsafe_buffer_usage]] + T *buf; + + [[clang::unsafe_buffer_usage]] + size_t sz; +}; + + +void test_struct_template (TemplateArray<int> t) { + int *p = t.buf; //expected-warning{{field 'buf' prone to unsafe buffer manipulation}} + size_t s = t.sz; //expected-warning{{field 'sz' prone to unsafe buffer manipulation}} +} + +class R { + [[clang::unsafe_buffer_usage]] + int *array; + + public: + int* getArray() { + return array; //expected-warning{{field 'array' prone to unsafe buffer manipulation}} + } + + void setArray(int *arr) { + array = arr; //expected-warning{{field 'array' prone to unsafe buffer manipulation}} + } +}; + +template<class P> +class Q { + [[clang::unsafe_buffer_usage]] + P *array; + + public: + P* getArray() { + return array; //expected-warning{{field 'array' prone to unsafe buffer manipulation}} + } + + void setArray(P *arr) { + array = arr; //expected-warning{{field 'array' prone to unsafe buffer manipulation}} + } +}; + +void test_class_template(Q<R> q) { + q.getArray(); + q.setArray(nullptr); +} + +struct AnonFields { + struct { + [[clang::unsafe_buffer_usage]] + int a; + }; +}; + +void test_anon_fields(AnonFields anon) { + int val = anon.a; //expected-warning{{field 'a' prone to unsafe buffer manipulation}} ---------------- malavikasamak wrote:
I will add this to the tests. Clang allows adding the attribute for the anonymous struct in your example. Looks like it treats inner structs as a member as well. However, because the attribute is not explicitly attached to the field 'a', it doesn't issue any warning. https://github.com/llvm/llvm-project/pull/101585 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits