[clang] Specify taking address of a variable referred to by '__counted_by' is forbidden (PR #106147)
Yeoul Na via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 26 14:39:53 PDT 2024
https://github.com/rapidsna created https://github.com/llvm/llvm-project/pull/106147
`-fbounds-safety` doesn't allow taking address of a variable referred to by `__counted_by`, in order to prevent code from using the pointer to update the variable without necessary checks to keep the invariant of `__counted_by`.
As shown in the example below, with -fbounds-safety the compiler ensures that the `__counted_by` pointer/or array has at least as many as elements that the attribute indicates, by requiring the count and the buf are always updated side by side and emitting run-time checks to ensure the new values are valid.
```
struct counted_buf {
sized_t count;
int *__counted_by(count) buf;
};
// BEFORE FIX
void foo(struct counted_buf *p) {
p->count = 10; // error: assignment to 'count' requires corresponding assignment to 'int *__counted_by(count) buf')
}
// FIXED by adding assignment to `p->buf`
void foo(struct counted_buf *p) {
// The compiler is now happy because
p->buf = (int *)malloc(sizeof(int) *5); // run-time checks are emitted to make sure new buf has at least `10` elements.
p->count = 10;
}
```
Consequently, `-fbounds-safety` prevents taking address of a variable referred to by `__counted_by`, because otherwise, the compiler cannot check the updates through the pointer pointing to the count:
```
void foo(struct counted_buf *p) {
int *count_p = &p->count; // error: variable referred to by '__counted_by' cannot be pointed to by any other variable
*count_p = 10; // without the above error, `count_p` is a normal `int *` so the compiler cannot check the value it updates against `__counted_by`
}
```
This PR is to explicitly specify this restriction and avoid future conflicts.
>From 8ed704c9e85b917d526df1e468e325a302f5a4d2 Mon Sep 17 00:00:00 2001
From: Yeoul Na <yeoul_na at apple.com>
Date: Mon, 26 Aug 2024 14:17:59 -0700
Subject: [PATCH] Specify taking address of a variable referred to by
'__counted_by' is forbidden
---
clang/docs/BoundsSafety.rst | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/clang/docs/BoundsSafety.rst b/clang/docs/BoundsSafety.rst
index 8fd655663edb00..e4ddd3c62db65d 100644
--- a/clang/docs/BoundsSafety.rst
+++ b/clang/docs/BoundsSafety.rst
@@ -759,7 +759,24 @@ relationship must hold even after any of these related variables are updated. To
this end, the model requires that assignments to ``buf`` and ``count`` must be
side by side, with no side effects between them. This prevents ``buf`` and
``count`` from temporarily falling out of sync due to updates happening at a
-distance.
+distance. In addition, taking address of ``count`` is not allowed in order to
+prevent the programmers from updating the ``count`` through the pointer, which
+will evade the necessary checks to make ``count`` and ``buf`` in sync.
+
+.. code-block:: c
+
+ struct counted_buf {
+ int *__counted_by(count) buf;
+ size_t count;
+ };
+
+ void foo(struct counted_buf *p) {
+ int *pointer_to_count = &p->count; // error: variable referred to by
+ // '__counted_by' cannot be pointed to by any other variable; exception is
+ // when the pointer is passed as a compatible argument to a function.
+ *pointer_to_count = SIZE_MAX; // Without reporting the error above, the
+ // compiler cannot prevent count from getting an invalid value.
+ }
The example below shows a function ``alloc_buf`` that initializes a struct that
members that use the ``__counted_by`` annotation. The compiler allows these
More information about the cfe-commits
mailing list