Skip to content

Commit 7710eea

Browse files
committed
Add detailed description of GCC access attributes to Compiler Annotations Guide
Signed-off-by: Thomas Nyman <[email protected]>
1 parent 74ae5dd commit 7710eea

File tree

1 file changed

+66
-14
lines changed

1 file changed

+66
-14
lines changed

docs/Compiler-Hardening-Guides/Compiler-Annotations-for-C-and-C++.md

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,20 @@ Some function attributes can accept parameters that have specific meanings. Par
2626

2727
Table 1: Recommended attributes
2828

29-
| Attribute | Supported since | Type | Description |
30-
|:-------------------------------------------------------------------------------------- |:---------------------------:|:----------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
31-
| `malloc` | GCC 2.95.3<br/>Clang 13.0.0 | Function | Mark custom allocation functions that return non-aliased (possibly NULL) pointers. |
32-
| `malloc (`_`deallocator`_`)` | GCC 11.0.0<br/>Clang 21.0.0 | Function | Associates _`deallocator`_ as the valid deallocator for the storage allocated by marked function. |
33-
| `ownership_returns(`_`allocation-type`_`)` | Clang 20.1.0 | Function | Associate pointers returned by custom allocation function with _`allocation-type`_ . |
34-
| `ownership_takes(`_`allocation-type`_`,` _`ptr-index`_`)` | Clang 20.1.0 | Function | Mark function as valid deallocator for _`allocation-type`_. |
35-
| `ownership_holds(`_`allocation-type`_`,` _`ptr-index`_`)` | Clang 20.1.0 | Function | Mark function taking responsibility of deallocation for _`allocation-type`_. |
36-
| `alloc_size(`_`size-index`_`)`<br/>`alloc_size(`_`size-index-1`_`,`_`size-index-2`_`)` | GCC 2.95.3<br/>Clang 4.0.0 | Function | Mark positional arguments holding the allocation size that the returned pointer points to. |
37-
| `access(mode, ref-pos)`<br/>`access(mode, ref-pos, size-pos)` | GCC 10 | Function | Indicate how the function uses argument at `ref-pos`. `mode` could be `read_only`, `read_write`, `write_only` or `none`. `size-pos`, if mentioned, is the argument indicating the size of object at `ref-pos`. |
38-
| `fd_arg(N)` | GCC 13 | Function | Argument N is an open file descriptor. |
39-
| `fd_arg_read(N)` | GCC 13 | Function | Argument N is an open file descriptor that can be read from. |
40-
| `fd_arg_write(N)` | GCC 13 | Function | Argument N is an open file descriptor that can be written to. |
41-
| `noreturn` | GCC 2.95.3<br/>Clang 4.0.0 | Function | The function does not return. |
42-
| `tainted_args` | GCC 12 | Function or function pointer | Function needs sanitization of its arguments. Used by `-fanalyzer=taint` |
29+
| Attribute | Supported since | Type | Description |
30+
|:------------------------------------------------------------------------------------------ |:---------------------------:|:----------------------------:|:------------------------------------------------------------------------------------------------- |
31+
| `malloc` | GCC 2.95.3<br/>Clang 13.0.0 | Function | Mark custom allocation functions that return non-aliased (possibly NULL) pointers. |
32+
| `malloc (`_`deallocator`_`)` | GCC 11.0.0<br/>Clang 21.0.0 | Function | Associates _`deallocator`_ as the valid deallocator for the storage allocated by marked function. |
33+
| `ownership_returns(`_`allocation-type`_`)` | Clang 20.1.0 | Function | Associate pointers returned by custom allocation function with _`allocation-type`_ . |
34+
| `ownership_takes(`_`allocation-type`_`,` _`ptr-index`_`)` | Clang 20.1.0 | Function | Mark function as valid deallocator for _`allocation-type`_. |
35+
| `ownership_holds(`_`allocation-type`_`,` _`ptr-index`_`)` | Clang 20.1.0 | Function | Mark function taking responsibility of deallocation for _`allocation-type`_. |
36+
| `alloc_size(`_`size-index`_`)`<br/>`alloc_size(`_`size-index-1`_`,`_`size-index-2`_`)` | GCC 2.95.3<br/>Clang 4.0.0 | Function | Mark positional arguments holding the allocation size that the returned pointer points to. |
37+
| `access(`_`mode`_`,`_`ref-pos`_`)`<br/>`access(`_`mode`_`,` _`ref-pos`_`,` _`size-pos`_`)` | GCC 10.0.0 | Function | Mark access restrictions for positional argument. |
38+
| `fd_arg(N)` | GCC 13 | Function | Argument N is an open file descriptor. |
39+
| `fd_arg_read(N)` | GCC 13 | Function | Argument N is an open file descriptor that can be read from. |
40+
| `fd_arg_write(N)` | GCC 13 | Function | Argument N is an open file descriptor that can be written to. |
41+
| `noreturn` | GCC 2.95.3<br/>Clang 4.0.0 | Function | The function does not return. |
42+
| `tainted_args` | GCC 12 | Function or function pointer | Function needs sanitization of its arguments. Used by `-fanalyzer=taint` |
4343

4444
## Performance considerations
4545

@@ -173,3 +173,55 @@ assert(__builtin_object_size(s, 0) == 100);
173173
[^clang-alloc_size]: LLVM team, [Attributes in Clang: alloc_size](https://clang.llvm.org/docs/AttributeReference.html#alloc-size), Clang Compiler User's Manual, 2025-03-04.
174174
175175
---
176+
177+
### Mark access restrictions for positional arguments
178+
179+
| Attribute | Supported since | Type | Description |
180+
|:-----------------------------------------------------------------------------------------------|:---------------------------:|:----------------------------:|:------------------------------------------------------------------------------------------------- |
181+
| `access(`_`mode`_`,`_`ref-index`_`)`<br/>`access(`_`mode`_`,`_`ref-index`_`,`_`size-index`_`)` | GCC 11.0.0 | Function | Mark access restrictions for positional argument. |
182+
183+
The `access` attribute in GCC[^gcc-acess] indicates the intended mode in which the annotated function operates on the specified positional argument. GCC uses this information to detect non-confirming accesses by the annotated function or their callers, as well as write-only accesses to objects that are never read from. Diagnostics of such non-conforming accesses are reported through the `-Wstringop-overread`, `-Wstringop-overflow`, `-Wuninitialized`, `-Wmaybe-uninitialized`, and `-Wunused` warnings.
184+
185+
The `access(`_`mode`_`,`_`ref-index`_`)` form indicates to GCC that the annotated function accesses the object passed to the function by-reference denoted the by the positional argument at _`ref-index`_ (using one-based indexing) according to _`mode`_, where _`mode`_ is one of the following access modes:
186+
187+
- `read_only`: the pointer or C++ reference corresponding to the specified positional argument may be used to read the referenced object but not write to it.
188+
- `write_only`: the pointer or C++ reference corresponding to the specified positional argument may be used to write the referenced object but not to read from it.
189+
- `read_write`: the pointer or C++ reference corresponding to the specified positional argument may be used to both read and write to the referenced object.
190+
- `none`: the pointer or C++ reference corresponding to the specified positional argument may not be used to access the referenced object at all.
191+
192+
The `access(`_`mode`_`,`_`ref-index`_`,`_`size-index`_`)` form behaves as the `access(`_`mode`_`,`_`ref-index`_`)` form but additionally hints to the compiler that the maximum size of the object (for the purposes of accesses) referenced by the pointer (or C++ reference) corresponding to the _`ref-index`_ positional argument is is denoted by the positional argument at _`size-index`_. The size is expected to the expressed as number of bytes if the pointer type denoted by _`ref-index`_ is `void*`. Otherwise, the size of expressed as number of elements of the type being referenced by the pointer denoted by _`ref-index`_. The actual bounds of the accesses carried out the function may be less than the size denoted the positional argument at _`size-index`_ but they must not exceed the denoted size.
193+
194+
The `write_only` and `read_write` access modes are applicable only to non-`const` pointer types. The `read_only` access mode implies a stronger guarantee than the `const` qualifier which may be cast away from a pointer.
195+
196+
In the `read_only`and `read_write` access modes the object referenced by the pointer corresponding to the _`ref-index`_ must be initialized unless the argument specifying the size of the access denoted by _`size-index`_ is zero. In the `write_only` access mode the object referenced by the pointer need not be initialized.
197+
198+
### Example usage
199+
200+
~~~c
201+
// Denotes that puts will perform read-only access on the memory pointer to by ptr.
202+
int puts (const char* ptr) __attribute__ ((access (read_only, 1)));
203+
204+
// Denotes that strcat will perform read-write access on the memory pointer to by destination and read-only access on the memory pointed to by source.
205+
char* strcat (char* destination, const char* source) __attribute__ ((access (read_write, 1), access (read_only, 2)));
206+
207+
// Denotes that strcpy will perform write-only access on the memory pointer to by destination and read-only access on the memory pointed to by source.
208+
char* strcpy (char* destination, const char* source) __attribute__ ((access (write_only, 1), access (read_only, 2)));
209+
210+
// Denotes that fgets will perform write-only access up n character on the memory pointed to by destination and read-write access on the memory pointed to by stream.
211+
int fgets (char* buff, int n, FILE* stream) __attribute__ ((access (write_only, 1, 2), access (read_write, 3)));
212+
213+
// Denotes that print_buffer will perform read-only access up to size characters on memory pointed to by buffer.
214+
void print_buffer(const char *buffer, size_t size) __attribute__((access(read_only, 1, 2)));
215+
216+
// Denotes that fill_buffer will perform write-only access up to size characters on memory pointed to by buffer.
217+
void fill_buffer(char *buffer, size_t size) __attribute__((access(write_only, 1, 2)));
218+
219+
// Denotes that to_uppercase will perform read-write access up to size characters on memory pointed to by buffer.
220+
void to_uppercase(char *buffer, size_t size) __attribute__((access(read_write, 1, 2)));
221+
~~~
222+
223+
[[Extended example at Compiler Explorer](https://godbolt.org/z/K44d89YM7)]
224+
225+
[^gcc-acess]: GCC team, [Using the GNU Compiler Collection (GCC): 6.35.1 Common Function Attributes: access](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-access-function-attribute), GCC Manual, 2024-08-01.
226+
227+
---

0 commit comments

Comments
 (0)