Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 Sep 2007 21:20:48 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        =?utf-8?Q?Dag-Erling_Sm=C3=B8rgrav?= <des@des.no>
Cc:        cvs-src@FreeBSD.org, src-committers@FreeBSD.org, cvs-all@FreeBSD.org, Sean Farley <scf@FreeBSD.org>
Subject:   Re: cvs commit: src/lib/libc/stdlib getenv.c
Message-ID:  <20070922202914.B90809@besplex.bde.org>
In-Reply-To: <86r6krqbrd.fsf@ds4.des.no>
References:  <200709220230.l8M2UiRK020609@repoman.freebsd.org> <86r6krqbrd.fsf@ds4.des.no>

next in thread | previous in thread | raw e-mail | index | archive | help
  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

--0-1574293470-1190460048=:90809
Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

On Sat, 22 Sep 2007, [utf-8] Dag-Erling Sm=C3=B8rgrav wrote:

> Sean Farley <scf@FreeBSD.org> writes:
>>   Log:
>>   The precision for a string argument in a call to warnx() needs to be c=
ast
>>   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 behaviou=
r
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.

Bruce
--0-1574293470-1190460048=:90809--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070922202914.B90809>