Re: strstr.c:105:3: error: ‘for’ loop initial declarations are only allowed in C99 or C11 mode
Giacomo Tesio
giacomo@tesio.it
Tue Aug 13 10:53:00 GMT 2019
Orlando, I have no issue if newlib decide to require -std=c99 but I
think the build scripts should impose it, without affecting each
single port. Otherwise the shared code should not require C99: using
C99 would be an option, but not mandatory.
As for the UB, I didn't think about it, I just fixed the compilation
error preserving everything else unchanged.
Giacomo
On 13/08/2019, Corinna Vinschen <vinschen@redhat.com> wrote:
> On Aug 12 20:18, Orlando Arias wrote:
>> On 8/12/19 8:05 PM, Howland, Craig D. - US via newlib wrote:
>> [snip]
>> >> for (int i = 0; i < ne_len; i++)
>> >> ^
>> [snip]
>> >
>> >
>> > A quick fix for you is to do what the error message suggests: add
>> > -std=gnu99 to CFLAGS before you configure Newlib, to have that as a
>> > default compiler flag when it is built.
>> > This is probably also the best solution for the real fix in Newlib.
>> > There are other cases of C99 constructs being used, anyway. (It has
>> > been 20 years. Seems totally reasonable to require it.)
>> > Craig
>> >
>>
>> Greetings,
>>
>> There is still a lingering bug in the code above, and the proposed patch
>> in [1]. It will trigger undefined behavior due to the comparison of a
>> signed type and an unsigned type. If the value of ne_len or similar is
>> over INT_MAX, the comparison will always fail and cause an integer
>> overflow, resulting in undefined behavior [signed overflow is UB per C
>> standard]. The datatype that should be used in these iterations is
>> size_t. I do agree however that requiring C99 or newer to compile newlib
>> should be a thing.
>>
>> Cheers,
>> Orlando.
>>
>> [1] https://sourceware.org/ml/newlib/2019/msg00469.html
>>
>
> I don't see any such patch in there fixing the undefined behaviour
> you're talking about:
>
> @@ -142,6 +145,7 @@ strstr (const char *haystack, const char *needle)
> {
> const unsigned char *hs = (const unsigned char *) haystack;
> const unsigned char *ne = (const unsigned char *) needle;
> + int i;
>
> /* Handle short needle special cases first. */
> if (ne[0] == '\0')
> @@ -170,7 +174,7 @@ strstr (const char *haystack, const char *needle)
>
> /* Initialize bad character shift hash table. */
> memset (shift, ne_len + 1, sizeof (shift));
> - for (int i = 0; i < ne_len; i++)
> + for (i = 0; i < ne_len; i++)
> shift[ne[i] % sizeof (shift)] = ne_len - i;
>
> do
>
> These two hunks are just the pre-C99 drop-in replacement.
> Also:
>
> if (__builtin_expect (ne_len < 255, 1))
> [...]
>
> So ne_len is guaranteed to be < 255 in this code snippet. Am I missing
> something?
>
>
> Corinna
>
> --
> Corinna Vinschen
> Cygwin Maintainer
> Red Hat
>
More information about the Newlib
mailing list