Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Dec 2011 20:08:16 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Dimitry Andric <dim@freebsd.org>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org
Subject:   Re: svn commit: r228678 - head/usr.sbin/rpc.ypupdated
Message-ID:  <20111218194714.W1622@besplex.bde.org>
In-Reply-To: <201112180040.pBI0eVKi084246@svn.freebsd.org>
References:  <201112180040.pBI0eVKi084246@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 18 Dec 2011, Dimitry Andric wrote:

> Log:
>  In usr.sbin/rpc.ypupdated/yp_dbupdate.c, use the appropriate printf
>  length modifier for time_t (after casting it to intmax_t).
>
>  MFC after:	1 week
>
> Modified:
>  head/usr.sbin/rpc.ypupdated/yp_dbupdate.c
>
> Modified: head/usr.sbin/rpc.ypupdated/yp_dbupdate.c
> ==============================================================================
> --- head/usr.sbin/rpc.ypupdated/yp_dbupdate.c	Sun Dec 18 00:34:42 2011	(r228677)
> +++ head/usr.sbin/rpc.ypupdated/yp_dbupdate.c	Sun Dec 18 00:40:30 2011	(r228678)
> @@ -130,7 +130,7 @@ ypmap_update(char *netname, char *map, u
> 		return(rval);
> 	}
>
> -	snprintf(yplastbuf, sizeof(yplastbuf), "%lu", time(NULL));
> +	snprintf(yplastbuf, sizeof(yplastbuf), "%ju", (intmax_t)time(NULL));
> 	key.data = yp_last;
> 	key.size = strlen(yp_last);
> 	data.data = (char *)&yplastbuf;

It still has a sign mismatch.  time_t can be unsigned, but in practice
isn't.  Now a sign mismatch is certain, since intmax_t is signed but
the format is still unsigned.  If time() somehow failed, it would
return -1 and this is printed as an inscrutable huge number (1844mumble
with 64-bit intmax_t).  If time_t were unsigned, then there would be
another sign error converting it to intmax_t.

Casting to intmax_t is silly for time_t, at least for current times.
Many places cast to long.  This is guaranteed to work until 2038 even
on i386.  It will keep working past then provided long is enlarged
before then.  I think long is already 64 bits on all arches that have
64-bit time_t.

Determining the appropriate printf modifier for time_t is especially
difficult, even in POSIX, since POSIX still allows it to be a floating
point type (it now says "integer or real floating type" where it used
to say "arithmetic type".  C still says "arithmetic type", and that
now seems to allow it to be a complex floating point type too).  In
C, there might be no appropriate modifier, since the encoding is
unspecified but code like the above wants seconds [since the Epoch].
Apart from that, determination of the appropriate modifier requires
either:
A. first determine if it is floating point.  If so, cast to long double,
    etc.
    else determine if it is signed.  If so, cast to intmax_t, etc.
    else cast to uintmax_t.
B. just assume that it is signed integer and cast to the simplest type
    that works.  I prefer plain long.

Bruce



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