`counted_by` attribute
Could we start annotating buffers in unions, structs, and function signatures with __counted_by to indicate what field or parameter indicates the buffer's minimum guaranteed size/capacity/count?
https://people.kernel.org/gustavoars/how-to-use-the-new-counted_by-attribute-in-c-and-linux
TL;DR: Clang 18, GCC 15, backwards-source-compatible via macro, see below.
// C
void fill_array_with_indices(uint8_t* __counted_by(count) buffer, size_t count) {
for (size_t i = 0; i < count; ++i) {
buffer[i] = i;
}
}
// __counted_by tells compiler: "buffer has at least count bytes"
struct aspa_record {
// ...
size_t provider_count;
uint32_t provider_asns[] __counted_by(provider_count);
// __counted_by tells compiler: "provider_asns has at provider_count elements"
};
fallback:
#ifndef __counted_by
# if __has_attribute(__counted_by__)
# define __counted_by(member) __attribute__((__counted_by__(member)))
# else
# define __counted_by(member)
# endif
#endif
The counted_by attribute is also used throughout the linux kernel.
Benefits:
- Improved compiler diagnostics: safer code,
- optional runtime checks on flexible array members
- increased compatibility with higher-level languages when importing C
e.g., Swift imports the function above as
f(buffer: Span<UInt8>)(nonescapability, memory safety, exclusivity checks) instead off(buffer: UnsafePointer<UInt8>, capacity: CInt)(unsafe). Maybe someone really familiar with Rust knows a similar technique for Rust's C interface? - future documentation generators may use this information for slightly better output
This sounds like a good proposal. Are there any drawbacks or downsides you could think of?
We talked about this in the Maintainer Coordination Call and you can go adhead and introduce this feature. It would be nice if you could add some documentation to the wiki or the Doxygen docs about it too, so it won't be overlooked when new code is added.
Do you have specific plans where to use it?
We talked about this in the Maintainer Coordination Call and you can go ahead and introduce this feature.
Great.
This sounds like a good proposal. Are there any drawbacks or downsides you could think of?
If you introduce this retroactively, you may need to rearrange initialization logic so that the count/size/length properties are initialized before the respective member. (btw, the naming of count vs size vs len vs length vs num is completely off in RIOT.)
It would be nice if you could add some documentation to the wiki or the Doxygen docs about it too, so it won't be overlooked when new code is added.
I am going to add a note to the coding convention. How strict do you think we should be? Should new code generally use __counted_by everywhere? I am asking because it feels quite strict for a feature with no immediate impact, but adoption is going to suffer if it's optional. So in RFC lingo SHOULD?
Do you have specific plans where to use it?
unicoap. And a little sEcReT sIdE pRoJeCt (Embedded Swift application, RIOT underneath), which I am very, very likely not going to have the time for.
I don't think it should be made mandatory, more like "(strongly) recommended to use, but no reason for rejection if not used".
This would probably also be a good task for a student project. Combining this with a number of other modern compiler features and an evaluation how effective those tools where to find bugs it might even be enough meat for a BSc thesis?
I think @OlegHahm, @mguetschow, @crasbe, and @jmgraeffe are working with students in RIOT 😉
Yeah that would help a lot, actually. I currently have to deal with a lot of logistic and organizational overhead.