cvs commit: src/lib/libc/stdlib getenv.c

Bruce Evans brde at
Sat Sep 22 04:21:02 PDT 2007

On Sat, 22 Sep 2007, [utf-8] Dag-Erling Smørgrav wrote:

> Sean Farley <scf at> writes:
>>   Log:
>>   The precision for a string argument in a call to warnx() needs to be cast
>>   to an int to remove the warning from using a size_t variable on 64-bit
>>   platforms.
> s/to remove the warning/to actually work/

Please be precise :-).

s/to remove the warning ... on 64-bit platforms/to avoid undefined behaviour
on platforms where size_t is not u_int, and to avoid having to make a
delicate analysis to show that the behaviour is defined and correct on
all other platforms/.

Delicate analysis:
- size_t is always an unsigned type, but the required type is int, so
   size_t is never compatible with the required type.
- on platforms where size_t is smaller than int, the arg type is
   nevertheless compatible with int, since warnx() is variadic and the
   arg is one of the variadic args; the default promotions thus apply
   and the arg is passed as an int whether or not you cast it explicitly
   to int (but casting it to a type larger than int would break it).
   FreeBSD doesn't support any platforms in this class.
- on platforms where size_t is u_int, the arg is passed as a u_int.
   The analysis for this case is too delicate to give in full here.
   Partial analysis:
   - the size_t variable must have a small value that is representable
     as an int (else casting it to int would be a bug and/or printing
     a line of that length would be a style bug).
   - the behaviour seems to have been undefined in C90, since va_arg()
     requires strict type compatibility in C90 and warnx() is implemented
     using va_arg(ap, int) which gave UB on u_int's.  Similarly for
     function calls, except the wording is less clear/strict.
   - UB in C90 was a bug in C90.  This is fixed in C99.  Now both va_arg()
     and function call args are specifically required to work if one type
     is a signed integer type, the [promotion of the] other type is the
     corresponding unsigned integer type, and the value is representable
     in both types.  Compatibility of the representation of integers and
     unsigned integers probably also requires this, but the specification
     of this in C90 is probably to fuzzy to override the parts that
     specify UB.  Everyone just knows that this case has to work.


More information about the cvs-src mailing list