> On Aug 4, 2023, at 3:09 PM, Siddhesh Poyarekar <siddh...@gotplt.org> wrote: > > On 2023-08-04 15:06, Qing Zhao wrote: >>> Yes, that's what I'm thinking. >>> >>>>> so `q` must be pointing to a single element. So you could deduce: >>>>> >>>>> 1. the minimum size of the whole object that q points to. >>>> You mean that the TYPE will determine the minimum size of the whole >>>> object? (Does this include the size of the flexible array member, or only >>>> the other part of the structure except the flexible array member?) >>> >>> Only the constant sized part of the structure. >> Okay. I see. >> But if the “counted_by” info is available, then from p->array, we can deduce >> the minimum size too, as sizeof(struct A) + q->foo * sizeof(int), right? > > Yes. > >>> >>>>> Actually for minimum size we'd also need a guarantee that >>>>> `alloc_buf_more` returns a valid allocated object. >>>> Why? Please explain a little bit here. >>> >>> So `alloc_buf_more` could return NULL, a valid pointer or an invalid >>> pointer. So, we could end up returning a non-zero minimum size for an >>> invalid or NULL pointer, which is incorrect, we don't know that. >> I see what’ s you mean now. >> However, if we already see p->array, then the p is guaranteed a valid >> pointer and not a NULL, right? (We are discussing on >> __builtin_dynamic_object_size (q->array, 2), we see q->array already) > > Yes, you could argue that for p->array, I agree, but not for p.
Agreed. Yes, for p->array, observed access. -:) Looks like we can improve __builtin_dynamic_object_size for the following case: struct A { size_t foo; int array[] __attribute__((counted_by (foo))); }; extern struct fix * alloc_buf (); int main () { struct fix *p = alloc_buf (); __builtin_object_size(p->array, 0) == sizeof(struct A) + p->foo * sizeof(int); /* with the current algorithm, it’s UNKNOWN */ __builtin_object_size(p->array, 2) == sizeof(struct A) + p->foo * sizeof(int); /* with the current algorithm, it’s UNKNOWN */ } I will add this improvement to __builtin_dynamic_object_size for FAM with “counted_by” attribute in a later patch after the initial patch is committed. Thanks a lot for the help. Qing > >>> >>> We won't need the object validity guarantee for (2) beyond, e.g. guarding >>> against a new NULL pointer dereference because it's a *maximum* estimate; >>> an invalid or NULL pointer would have 0 size. So for such cases, __bos(q, >>> 0) could return >>> >>> sizeof(*q) + (q ? q->foo:0) >>> >>> and __bos(q->array, 0) could be >>> >>> sizeof(*q) + q->foo - offsetof(q, array) >>> >>> There's no need to guard against a dereference in the second case because >>> the q->array dereference already assumes that q is valid. >> q->array should also guarantee that q is a valid pointer for minimum size, >> right? Or do I miss anything here? > > Yes. > > Thanks, > Sid