"Gary E. Miller" <[email protected]> writes:

>> Yes, but you didn't quote enough.  It says:
>> 
>>   The c argument is a type int, the value of which the application
>> shall ensure is a character representable as an unsigned char or
>> equal to the value of the macro EOF. If the argument has any other
>> value, the behavior is undefined.
>
> GNU libc hhas no such caveat.  C99 also does not.

GNU libc might well do something else; that's within UB and no
violation.  But it's not an argument that the code is ok.

I don't have access to the released version of C99, but in draft
n1256, that text is in 7.4 "Character handling <ctype.h>" said to apply
to all of the ctype functions.
> C23 doe say:
>
> "In all cases the argument is an int, the value of which shall be
> representable as an unsigned char or shall equal the value of the macro
> EOF. If the argument has any other value, the behavior is undefined. "

Word for word same as C99 7.4

> Since gpsd only passed a char or unsigned char to isXXXX(), that is
> satisfied.  Those are simply promoted to int, so need no cast.

Not quite and that's why this is tricky.  When a (signed) char is
promoted to int, any negative values end up as negative ints, and those
are not representable as unsigned char.

>> This leads to the general rule that you can't use arguments of type
>> char for ctype functions.  If it's a char, it needs to be cast to
>> unsigned char.   There are a massive number of such constructions
>> already in the code.
>
> Id be happy to ensure gpsd is always using uchar for anything going
> to isXXXXX();  Old gpsd code is very sloppy about char vs uchar.

There is a tremendous amount of such code out there, not specific to
gpsd.  Basically when passing a variable of type char (or expression),
cast it to unsigned char, which moves the negative values to the 128-255
range.

>>   libgps/gpsutils.c:    if (isdigit((unsigned char)*p)) {
>
> Yeah, those are just wrong.  I did not expect to get them all
> on the first pass.  I'll rip those out today.

The code I pasted is right.  It's leaving it out tht's a bug.

Reply via email to