This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: ToT glibc build problem with ToT GCC
On 8/29/19 1:53 PM, Martin Sebor wrote:
> On 8/29/19 1:17 PM, Carlos O'Donell wrote:
>> On 8/29/19 2:36 PM, Martin Sebor wrote:
>>> On 8/29/19 11:54 AM, Carlos O'Donell wrote:
>>>> On 8/29/19 1:28 PM, Martin Sebor wrote:
>>>>> A longer term solution is to replace the array with a suitably
>>>>> aligned char buffer and write the data into it, e.g., like this:
>>>>>
>>>>> union {
>>>>> struct charseq replace[2];
>>>>> char buf[sizeof (struct charseq) * 2];
>>>>> } u;
>>>>>
>>>>> u.replace[0].nbytes = 1;
>>>>> const char s[] = "?";
>>>>> memcpy (u.buf + offsetof (struct charseq, bytes), "?", 2);
>>>>>
>>>>> This is still iffy but it won't trigger an out-of-bounds warning.
>>>>> This code should still be flagged for the declaration of an object
>>>>> with an internal zero-length array, so that will need to be dealt
>>>>> with when such a warning is introduced (e.g., by suppressing
>>>>> the warning).
>>>>
>>>> Why is this iffy? This is the kind of solution I was thinking of using.
>>>>
>>>> The alternative is an entirely new type that has a non-zero-length
>>>> array that can be used for static object allocation like this, but then
>>>> you need to cast between them in a safe way?
>>>
>>> It's iffy because of the interior zero-length array.
>>>
>>> GCC accepts zero-length array members anywhere but it doesn't
>>> always avoid assuming their elements don't overlap other members.
>>> Some other compilers don't allow zero-length arrays in definitions
>>> where they're followed by another member or element of a larger
>>> array. I'd like to see GCC warn for such uses because of
>>> the overlapping problem.
>>>
>>> Martin
>>>
>>> PS For example, GCC folds the test below to false. Clang does
>>> the same with slightly different test cases.
>>>
>>> struct charseq replace[2];
>>>
>>> void f (int i)
>>> {
>>> int x = *replace[1].name;
>>>
>>> replace[0].bytes[i] = 0;
>>>
>>> if (x != *replace[1].name)
>>> __builtin_abort ();
>>> }
>>
>> This static allocation is rare, it's the only one.
>>
>> Is there a viable solution for a static allocation of a structure
>> that ends in a VLA?
>
> The static allocation isn't necessarily a problem. Defining arrays
> or members of structures with flexible array members (or zero-length
> arrays) in a way that allows overlapping is.
>
> The only viable alternative I can think of is to define replace as
> a char buffer:
>
> static _Alignas (struct charseq)
> unsigned char replace[sizeof (struct charseq[2])];
>
> memcpy (replace + offsetof (struct charseq, nbytes),
> (int[]){ 1 }, sizeof (int));
>
> memcpy (replace + offsetof (struct charseq, bytes), "?", 2);
>
> This isn't pretty but it's close to strictly conforming. The only
> non-conforming part other than the zero-length member is that (if)
> the char array is later accessed as struct charseq. But that's so
> pervasive that it might as well be in the standard.
Couldn't we just drop the whole static initialization and do something like
static struct charseq *replace = NULL;
if (!replace)
replace = malloc (sizeof (struct charseq) + 2);
It leaks the chunk of memory though.
jeff
>
> Martin