Skip to content

Commit 86f8e18

Browse files
committed
Update wording on __attribute__((malloc))
- Clang doesn't support the two-argument version. This is llvm/llvm-project#53152 . - Clang 21 isn't a thing yet. - Emphasize the "optimization" we're talking about (noalias); I believe that's the only optimization we're talking about here (and if not, we should be even more explicit, because it's fooled me). Add an example of the optimization to the relevant Godbolt, since it was missing any example before. - Fix two trivial "cplusplis" typos. Addresses my comments in #201.
1 parent 23bde78 commit 86f8e18

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

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

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Table 1: Recommended attributes
2929
| Attribute | Supported since | Type | Description |
3030
|:------------------------------------------------------------------------------------------ |:---------------------------:|:----------------------------:|:------------------------------------------------------------------------------------------------- |
3131
| `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. |
32+
| `malloc (`_`deallocator`_`)` | GCC 11.0.0 | Function | Associates _`deallocator`_ as the valid deallocator for the storage allocated by marked function. |
3333
| `ownership_returns(`_`allocation-type`_`)` | Clang 20.1.0 | Function | Associate pointers returned by custom allocation function with _`allocation-type`_ . |
3434
| `ownership_takes(`_`allocation-type`_`,` _`ptr-index`_`)` | Clang 20.1.0 | Function | Mark function as valid deallocator for _`allocation-type`_. |
3535
| `ownership_holds(`_`allocation-type`_`,` _`ptr-index`_`)` | Clang 20.1.0 | Function | Mark function taking responsibility of deallocation for _`allocation-type`_. |
@@ -56,7 +56,7 @@ Attributes influence not only diagnostics generated by the compiler but also the
5656
| Attribute | Supported since | Type | Description |
5757
|:--------------------------------------------------------------------------------------------|:---------------------------:|:----------------------------:|:------------------------------------------------------------------------------------------------- |
5858
| <span id="malloc">`malloc`</span> | GCC 2.95.3<br/>Clang 13.0.0 | Function | Mark custom allocation functions that return non-aliased (possibly NULL) pointers. |
59-
| <span id="malloc (dealloc)">`malloc (`_`deallocator`_`)`</span> | GCC 11.0.0<br/>Clang 21.0.0 | Function | Associates _`deallocator`_ as the valid deallocator for the storage allocated by marked function. |
59+
| <span id="malloc (dealloc)">`malloc (`_`deallocator`_`)`</span> | GCC 11.0.0 | Function | Associates _`deallocator`_ as the valid deallocator for the storage allocated by marked function. |
6060
| <span id="malloc (dealloc, ptr-index)">`malloc (`_`deallocator`_`,` _`ptr-index`_`)`</span> | GCC 11.0.0 | Function | Same as above but also denotes the positional argument here the pointer must be passed. |
6161
| <span id="ownership_returns">`ownership_returns(`_`allocation-type`_`)`</span> | Clang 20.1.0 | Function | Associate pointers returned by custom allocation function with _`allocation-type`_ . |
6262
| <span id="ownership_takes">`ownership_takes(`_`allocation-type`_`,` _`ptr-index`_`)`</span> | Clang 20.1.0 | Function | Mark function as valid deallocator for _`allocation-type`_. |
@@ -75,7 +75,8 @@ In GCC, the `malloc (`_`deallocator`_`)` and `malloc (`_`deallocator`_`,` _`ptr-
7575
- **Memory leaks** (`-Wanalyzer-malloc-leak`) if if there is an execution path in which the result of an allocation call goes out of scope without being passed to the deallocation function.
7676
- **Invalid free** (`-Wanalyzer-free-of-non-heap`) if a deallocation function is used on a global or on-stack variable.
7777

78-
Clang supports both forms of the `malloc` attribute but does not yet implement the `-Wmismatched-dealloc` and `-Wmismatched-new-delete` warnings. Instead, Clang provides the `ownership_returns`, `ownership_takes`, and `ownership_holds` attributes[^clang-ownership]: that interact with the Clang static analyzer[^clang-checkers].
78+
Clang's parser recognizes both forms of the `malloc` attribute, but Clang does not yet implement the `-Wuse-after-free`, `-Wmismatched-dealloc`, and `-Wmismatched-new-delete` warnings
79+
that would use that information. Instead, Clang provides the `ownership_returns`, `ownership_takes`, and `ownership_holds` attributes[^clang-ownership]: that interact with the Clang static analyzer[^clang-checkers].
7980

8081
In Clang, the `ownership_returns(`_`allocation-type`_`)` associates the pointer returned by the marked function with an _`allocation-type`_. Here, _`allocation-type`_ is any string which will subsequently be used to detect mismatched allocations in cases where the pointer is passed to a deallocator marked with another _`allocation-type`_. The _`allocation-type`_ `malloc` has a special meaning and causes the Clang static analyzer to treat the associated pointer as though the allocated storage would have been allocated using the standard `malloc()` function, and can subsequently be safely deallocated with the standard `free()` function.
8182

@@ -84,8 +85,8 @@ The Clang `ownership_takes(`_`allocation-type`_`,` _`ptr-index`_`)` attribute ma
8485
Using the the `ownership_returns`, `ownership_takes`, and `ownership_holds` attributes allows the Clang static analyzer to catch:
8586

8687
- **Mismatched deallocation** (`unix.MismatchedDeallocator`) if there is an execution path in which the result of an allocation call of type _`allocation-type`_ is passed to a function annotated with `ownership_takes` or `ownership_holds` with a different allocation type.
87-
- **Double free** (`unix.Malloc`, `cplusplis.NewDelete`) if there is an execution path in which a value is passed more than once to a function annotated with `ownership_takes` or `ownership_holds`.
88-
- **Use-after-free** (`unix.Malloc`, `cplusplis.NewDelete`) if there is an execution path in which the memory passed by pointer to a function annotated with `ownership_takes` is used after the call. Using memory passed to a function annotated with `ownership_holds` is considered valid.
88+
- **Double free** (`unix.Malloc`, `cplusplus.NewDelete`) if there is an execution path in which a value is passed more than once to a function annotated with `ownership_takes` or `ownership_holds`.
89+
- **Use-after-free** (`unix.Malloc`, `cplusplus.NewDelete`) if there is an execution path in which the memory passed by pointer to a function annotated with `ownership_takes` is used after the call. Using memory passed to a function annotated with `ownership_holds` is considered valid.
8990
- **Memory leaks** (`unix.Malloc`, `cplusplus.NewDeleteLeaks`) if if there is an execution path in which the result of an allocation call goes out of scope without being passed to a function annotated with `ownership_takes` or `ownership_holds`.
9091
- **Dubious `malloc()` arguments involving `sizeof`** (`unix.MallocSizeof`) if the size of the pointer type the returned pointer does not match the size indicated by `sizeof` expression passed as argument to the allocation function.
9192
- **Potentially attacker controlled `size` parameters to allocation functions** (`optin.taint.TaintedAlloc`) if the `size` parameter originates from a tainted source and the analyzer cannot prove that the size parameter is within reasonable bounds (`<= SIZE_MAX/4`).
@@ -101,12 +102,16 @@ void my_free(void *ptr);
101102
void *my_malloc(size_t size) __attribute__ ((malloc, malloc (my_free, 1)));
102103
~~~
103104
104-
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)]
105+
Note that to benefit from both the associated `noalias` optimization and the improved detection of memory errors,
106+
functions should be marked with _both_ the zero-argument `malloc` attribute and the form of the attribute with one
107+
or two arguments. Note that an allocation function whose return value may alias another object (for example as a non-null
108+
"flag" or "sentinel" value) must not be marked with the zero-argument `malloc` attribute, but can still safely be
109+
marked with the one- or two-argument form. [[Extended example at Compiler Explorer](https://godbolt.org/z/PheGfrvdc)]
105110
106111
Clang `ownership_returns`, `ownership_takes`, and `ownership_holds`:
107112
108113
~~~c
109-
// Denotes that my_malloc will return with a pointer to storage of labeled as "my_allocation" .
114+
// Denotes that my_malloc will return a pointer to storage with the label "my_allocation" .
110115
void *my_malloc(size_t size) __attribute((malloc, ownership_returns(my_allocation)));
111116
112117
// Denotes that my_free will deallocate storage pointed to by ptr that has been labeled "my_allocation".

0 commit comments

Comments
 (0)