On Tue, Apr 15, 2025 at 09:07:44PM +0200, Martin Uecker wrote:
> Am Dienstag, dem 15.04.2025 um 14:50 +0200 schrieb Michael Matz:
> > Hello,
> ...
> 
> > > struct A {
> > >   int *buf __counted_by(len); // 'len' *must* be in the struct.
> > >   int len;
> > > };
> > 
> > ... means that we would have to implement general delayed parsing for 
> > expressions in C parsers. 
> 
> I have to agree with Michael.  This was the main reason
> we rejected the original approach.  
> 
> I also think consistency with general syntax for arrays in structs
> is far more important for C than consistency for the special case of
> having only one identifier in counted_by.

Okay, so I think the generally recognized way forward is with two
attributes:

        counted_by(struct_member)

and

        counted_by_expr(type struct_member; ...; expression)

This leaves flexible array members with counted_by unchanged from
current behavior.

Questions I am left with:

1) When applying counted_by to pointer members, are out-of-order member
declarations expected to be handled? As in, is this expected to be valid?

        struct foo {
                struct bar *p __attribute__((counted_by(count)));
                int count;
        };

1.A) If it is _not_ valid, is it valid to use it when the member has
been declared earlier? Such as:

        struct foo {
                int count;
                struct bar *p __attribute__((counted_by(count)));
        };

1.B) If "1" isn't valid, but "1.A" is valid, I would expect that way to
allow the member ordering in "1" is through counted_by_expr? For example:

        struct foo {
                struct bar *p __attribute__((counted_by_expr(int count; 
count)));
                int count;
        };

1.C) If "1" isn't valid, and "1.A" isn't valid, then counted_by of
pointer members must always use counted_by_expr. Is that expected?
(I ask because it seems like a potentially weird case there member order
forces choosing between two differently named attributes. It'd be really
nice if "1" could be valid.)


2) For all counted_by of pointer members, I understand this to only be
about the parsing step, not further analysis where the full sizes of
all objects will need to be known. Which means that this is valid:

        struct bar; // empty declaration

        struct foo {
                struct bar *p __attribute__((counted_by_expr(int count; 
count)));
                int count;
        };
        ...
        // defined after being referenced by counted_by_expr above
        struct bar {
                int a, b, c;
                struct foo *p;
        };

Is that correct?


3) It seems it will be possible to provide a "singleton" alias to
indicate that a given pointer member is not an array of objects, but
rather a pointer to a single object instance:

        struct bar {
                int a, b, c;
                struct foo *p __attribute__((counted_by_expr(1)));
        };

Is that correct? (This will be useful once we can apply counted_by to
function arguments...)


4) If there are type mismatches between the counted_by_expr struct
member declaration and the later actual struct member declaration, I
assume that will be a hard error. For example, this would fail to compile:

        struct foo {
                struct bar *p __attribute__((counted_by_expr(int count; 
count)));
                unsigned long count;
        };

Is that correct? It feels like if we're already able to do this analysis,
then "1" should be possible also. Perhaps I'm misunderstanding something
about the parser.


Thanks!

-Kees

-- 
Kees Cook

Reply via email to