> On Apr 15, 2025, at 16:35, Kees Cook <k...@kernel.org> wrote: > > 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.
Yes, this is one of the benefit from this compromised approach -:) > > 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; > }; Yes, this is valid. Given a lone identifier, you will use “counted_by” attribute the same as the counted_by for FAM, and this identifier will be looked up inside the enclosing structure. (Even when the counted_by field is AFTER the pointer). The patch I sent a while ago on the counted_by for pointer filed of a structure: https://gcc.gnu.org/pipermail/gcc-patches/2025-January/673837.html Have supported this without issue. > > 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.) 1 would 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; > }; This could be: struct foo { struct bar *p __attribute__((counted_by (count))); int count; }; > ... > // defined after being referenced by counted_by_expr above > struct bar { > int a, b, c; > struct foo *p; > }; > > Is that correct? I think so. > > > 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...) This is a good idea. > > > 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? I guess that the hard error will be issued when the parser sees “unsigned long count” which Is conflict with the previous seen “int count” inside counted_by_expr. But I am not sure on this. Qing > 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