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