================
@@ -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}}
----------------
haoNoQ wrote:

In this case the field isn't anonymous, only the parent field is anonymous.

I wonder if this works too:
```
 struct AnonFields {
  [[clang::unsafe_buffer_usage]]
  struct {
   int a;
  };
 };
```
But this would probably cause the attribute to try to get attached to the 
struct decl, not to the field decl? So I'm not really aware of a realistic way 
to trigger this kind of problem.

But in case of functions this is going to be way more common. Eg., every 
overloaded operator is basically an anonymous function. ObjC methods are named 
but their names aren't simple identifiers so this is another source of crashes. 
Blocks... exist.

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

Reply via email to