Skip to content

Commit 8894104

Browse files
committed
Add examples in C++11 and C23 attribute syntax to Compiler Annotations for C and C++
Signed-off-by: Thomas Nyman <[email protected]>
1 parent 3119641 commit 8894104

File tree

1 file changed

+106
-2
lines changed

1 file changed

+106
-2
lines changed

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

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,16 @@ Using the `ownership_returns`, `ownership_takes`, and `ownership_holds` attribut
9292

9393
#### Example usage
9494

95-
GCC `malloc`, `malloc (`_`deallocator`_`)`, and `malloc (`_`deallocator`_, _`ptr-index`_`)` :
95+
GCC `malloc`, `malloc (`_`deallocator`_`)`, and `malloc (`_`deallocator`_, _`ptr-index`_`)` in C++11 / C23 attribute syntax:
96+
97+
~~~c
98+
void my_free(void *ptr);
99+
100+
// Denotes that my_malloc will return with a dynamically allocated piece of memory which must be freed using my_free.
101+
void * my_malloc(size_t size) [[gnu::malloc]] [[gnu::malloc(my_free, 1)]];
102+
~~~
103+
104+
In `__attribute__` keyword syntax:
96105
97106
~~~c
98107
void my_free(void *ptr);
@@ -103,7 +112,20 @@ void *my_malloc(size_t size) __attribute__ ((malloc, malloc (my_free, 1)));
103112

104113
Note that to benefit both from the associated optimizations and improved detection of memory errors functions should be marked with _both_ the form of the attribute without arguments and the form of the attribute with one or two arguments. [[Extended example at Compiler Explorer](https://godbolt.org/z/bc97ahbnd)]
105114

106-
Clang `ownership_returns`, `ownership_takes`, and `ownership_holds`:
115+
Clang `ownership_returns`, `ownership_takes`, and `ownership_holds` in C++11 / C23 attribute syntax:
116+
117+
~~~c
118+
// Denotes that my_malloc will return with a pointer to storage labeled as "my_allocation".
119+
void * my_malloc(size_t size) [[gnu::malloc]] [[clang::ownership_returns(my_allocation)]];
120+
121+
// Denotes that my_free will deallocate storage pointed to by ptr that has been labeled "my_allocation".
122+
voidmy_free(void *ptr) [[clang::ownership_takes(my_allocation, 1)]] ;
123+
124+
// Denotes that my_hold will take over the ownership of storage pointed to by ptr that has been labeled "my_allocation".
125+
void my_hold(void *ptr) [[clang::ownership_holds(my_allocation, 1)]];
126+
~~~
127+
128+
In `__attribute__` keyword syntax:
107129
108130
~~~c
109131
// Denotes that my_malloc will return with a pointer to storage of labeled as "my_allocation" .
@@ -141,6 +163,21 @@ In Clang, the size information hints provided via `alloc_size` attribute only af
141163

142164
#### Example usage
143165

166+
In C++11 / C23 attribute syntax:
167+
168+
~~~c
169+
// Denotes that my_malloc will return with a pointer to storage capable of holding up to size bytes.
170+
void * my_malloc(size_t size) [[gnu::alloc_size(1)]];
171+
172+
// Denotes that my_realloc will return with a pointer to storage capable of holding up to size bytes.
173+
void * my_realloc(void* ptr, size_t size) [[gnu::alloc_size(2)]];
174+
175+
// Denotes that my_calloc will return with a pointer to storage capable of holding up to n * size bytes.
176+
void * my_calloc(size_t n, size_t size) [[gnu::alloc_size(1, 2)]];
177+
~~~
178+
179+
In `__attribute__` keyword syntax:
180+
144181
~~~c
145182
// Denotes that my_malloc will return with a pointer to storage capable of holding up to size bytes.
146183
void *my_malloc(size_t size) __attribute__((alloc_size(1)));
@@ -197,6 +234,33 @@ In the `read_only` and `read_write` access modes the object referenced by the po
197234

198235
### Example usage
199236

237+
In C++11 / C23 attribute syntax:
238+
239+
~~~c
240+
// Denotes that puts performs read-only access on the memory pointed to by ptr.
241+
int puts (const char* ptr) [[gnu::access(read_only, 1)]];
242+
243+
// Denotes that strcat performs read-write access on the memory pointed to by destination and read-only access on the memory pointed to by source.
244+
char* strcat (char* destination, const char* source) [[gnu::access(read_write, 1)]] [[gnu::access(read_only, 2)]];
245+
246+
// Denotes that strcpy performs write-only access on the memory pointed to by destination and read-only access on the memory pointed to by source.
247+
char* strcpy (char* destination, const char* source) [[gnu::access(write_only, 1)]] [[gnu::access(read_only, 2)]];
248+
249+
// Denotes that fgets performs write-only access up to n characters on the memory pointed to by buff and read-write access on the memory pointed to by stream.
250+
int] fgets (char* buff, int n, FILE* stream) [[gnu::access(write_only, 1, 2)]] [[gnu::access(read_write, 3)];
251+
252+
// Denotes that print_buffer performs read-only access up to size characters on memory pointed to by buffer.
253+
void print_buffer(const char *buffer, size_t size) [[gnu::access(read_only, 1, 2)]];
254+
255+
// Denotes that fill_buffer performs write-only access up to size characters on memory pointed to by buffer.
256+
void fill_buffer(char *buffer, size_t size) [[gnu::access(write_only, 1, 2)]];
257+
258+
// Denotes that to_uppercase performs read-write access up to size characters on memory pointed to by buffer.
259+
void to_uppercase(char *buffer, size_t size) [[gnu::access(read_write, 1, 2)]];
260+
~~~
261+
262+
In `__attribute__` keyword syntax:
263+
200264
~~~c
201265
// Denotes that puts performs read-only access on the memory pointed to by ptr.
202266
int puts (const char* ptr) __attribute__ ((access (read_only, 1)));
@@ -250,6 +314,21 @@ The `fd_arg_write(`_`fd-index`_`)` form is like `fd_arg` but also requires that
250314

251315
#### Example usage
252316

317+
In C++11 / C23 attribute syntax:
318+
319+
~~~c
320+
// Denotes that use_file expects fd to be a valid and open file descriptor
321+
void use_file (int fd) [[gnu::fd_arg(1)]] ;
322+
323+
// Denotes that write_to_file expects fd to be a valid, open, and writable file descriptor
324+
void write_to_file (int fd, void *src, size_t size) [[gnu::fd_arg_write(1)]];
325+
326+
// Denotes that read_from_file expects fd to be a valid, open, and readable file descriptor
327+
void read_from_file (int fd, void *dst, size_t size) [[gnu::fd_arg_read(1)]];
328+
~~~
329+
330+
In `__attribute__` keyword syntax:
331+
253332
~~~c
254333
// Denotes that use_file expects fd to be a valid and open file descriptor
255334
void use_file (int fd) __attribute__ ((fd_arg (1)));
@@ -281,6 +360,22 @@ Users should be careful not to assume that registers saved by the calling functi
281360

282361
#### Example usage
283362

363+
In C++11 / C23 attribute syntax:
364+
365+
~~~c
366+
// Denotes that fatal will never return
367+
void fatal () [[noreturn]];
368+
369+
void
370+
fatal (...)
371+
{
372+
... /* Print error message. */ ...
373+
exit (1);
374+
}
375+
~~~
376+
377+
In `__attribute__` keyword syntax:
378+
284379
~~~c
285380
// Denotes that fatal will never return
286381
void fatal () __attribute__ ((noreturn));
@@ -331,6 +426,15 @@ Prior to GCC 14.1.0 the GCC analyzer's _taint mode_ had to be explicitly enabled
331426

332427
### Example usage
333428

429+
In C++11 / C23 attribute syntax:
430+
431+
~~~c
432+
// Marks arguments to do_with_untrusted as requiring sanitization
433+
void do_with_untrusted_input(int untrusted_input) [[gnu::tainted_args]];
434+
~~~
435+
436+
In `__attribute__` keyword syntax:
437+
334438
~~~c
335439
// Marks arguments to do_with_untrusted as requiring sanitization
336440
void do_with_untrusted_input(int untrusted_input) __attribute__ ((tainted_args));

0 commit comments

Comments
 (0)