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

Reply via email to