> On Aug 4, 2023, at 12:36 PM, Siddhesh Poyarekar <siddh...@gotplt.org> wrote: > > On 2023-08-04 11:27, Qing Zhao wrote: >>> On Aug 4, 2023, at 10:40 AM, Siddhesh Poyarekar <siddh...@gotplt.org> wrote: >>> >>> On 2023-08-03 13:34, Qing Zhao wrote: >>>> One thing I need to point out first is, currently, even for regular fixed >>>> size array in the structure, >>>> We have this same issue, for example: >>>> #define LENGTH 10 >>>> struct fix { >>>> size_t foo; >>>> int array[LENGTH]; >>>> }; >>>> … >>>> int main () >>>> { >>>> struct fix *p; >>>> p = alloc_buf_more (); >>>> expect(__builtin_object_size(p->array, 1), LENGTH * sizeof(int)); >>>> expect(__builtin_object_size(p->array, 0), -1); >>>> } >>>> Currently, for __builtin_object_size(p->array, 0), GCC return UNKNOWN for >>>> it. >>>> This is not a special issue for flexible array member. >>> >>> That's fine for fixed arrays at the end of a struct because the "whole >>> object" size could be anything; `p` could be pointing to the beginning of >>> an array for all we know. If however `array` is strictly a flex array, >>> i.e.: >>> >>> ``` >>> struct A >>> { >>> size_t foo; >>> int array[]; >>> }; >>> ``` >>> >>> then there's no way in valid C to have an array of `struct fix`, >> Yes!! this is exactly the place that makes difference between structures >> with fixed arrays and the ones with flexible arrays. >> With such difference, I guess that using the type of the structure with >> flexible array member for p->array to get the size of the whole object p >> point to might be reasonable? > > 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? > >>> 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) > > 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? thanks. Qing > >>> >>> and >>> >>> 2. if you're able to determine the size of the flex array (through >>> __element_count__(foo) for example), you could even determine the maximum >>> size of the whole object. >>> >>> For (2) though, you'd break applications that overallocate and then expect >>> to be able to use that overallocation despite the space not being reflected >>> in the __element_count__. I think it's a bug in the application and I >>> can't see a way for an application to be able to do this in a valid way so >>> I'm inclined towards breaking it. >> Currently, we allow the situation when the allocation size for the whole >> object is larger than the value reflected in the “counted_by” attribute (the >> old name is __element_count__). But don’t allow the other way around (i.e, >> when the allocation size for the whole object is smaller than the value >> reflected in the “counted_by” attribute. > > Right, that's going to be the "break". For underallocation __bos will only > end up overestimating the space available, which is not ideal, but won't end > up breaking compatibility. > >>> >>> Of course, the fact that gcc allows flex arrays to be in the middle of >>> structs breaks the base assumption but that's something we need to get rid >>> of anyway since there's no way for valid C programs to use that safely. >> Since GCC14, we started to deprecate this extension (allow flex array to be >> in the middle of structs). >> https://gcc.gnu.org/pipermail/gcc-cvs/2023-June/385730.html > > Yes, that's what I'm banking on. > > Thanks, > Sid