On Mon, Jul 15, 2024 at 07:20:31PM +0200, Martin Uecker wrote:
> No, there are still two many missing pieces. The following
> works already
>
> int h(int n, int buf[n])
> {
> return __builtin_dynamic_object_size(buf, 1);
> }
Yeah, this is nice.
There are some interesting things happening around this general
idea. Clang has the rather limited attributes "pass_object_size" and
"pass_dynamic_object_size" that will work on function prototypes that
will inform a _bos or _bdos internally, but you can only choose _one_
type to apply to a given function parameter:
size_t h(char * const __attribute__((pass_dynamic_object_size(1))) buf)
{
return __builtin_dynamic_object_size(buf, 1);
}
https://clang.llvm.org/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size
I have found it easier to just make wrapper macros, as that can allow
both size types:
size_t h(char *buf, const size_t p_max, const size_t p_min);
#define h(p) \
({ \
const size_t __p_max = __builtin_dynamic_object_size(p, 0); \
const size_t __p_min = __builtin_dynamic_object_size(p, 1); \
__h(p, __p_max, __p_min); \
})
But best is that it just gets handled automatically, which will be the
goals of the more generalized "counted_by" (and "sized_by") attributes
that will provide similar coverage as your example:
size_t h(int * __attribute__((sized_by(bytes))) buf, int bytes)
{
return __builtin_dynamic_object_size(buf, 1);
}
https://discourse.llvm.org/t/rfc-enforcing-bounds-safety-in-c-fbounds-safety/
Those attributes end up being similar to what you have only the explicit
predeclaration isn't needed. i.e. to put "int n" in your example after
"buf", it needs predeclaration:
int h(int n; int buf[n], int n)
{
...
}
(But Clang doesn't appear to support predeclarations.)
--
Kees Cook