> On Apr 15, 2025, at 16:35, Kees Cook <[email protected]> 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