svn commit: r203777 - in user/eri/pf45/head: contrib/pf/pfctl sys/contrib/pf/net

Bruce Evans brde at optusnet.com.au
Fri Feb 12 13:07:59 UTC 2010


On Thu, 11 Feb 2010, Ermal Luçi wrote:

> Log:
>  Cast to proper type.
>
>  Requested-by: Jilles Tjoelker

Isn't the proper type [u]intmax_t (provided the format is also proper)?

> Modified: user/eri/pf45/head/contrib/pf/pfctl/parse.y
> ==============================================================================
> --- user/eri/pf45/head/contrib/pf/pfctl/parse.y	Thu Feb 11 08:50:21 2010	(r203776)
> +++ user/eri/pf45/head/contrib/pf/pfctl/parse.y	Thu Feb 11 09:55:45 2010	(r203777)
> @@ -709,7 +709,7 @@ varstring	: numberstring varstring 		{
>
> numberstring	: NUMBER				{
> 			char	*s;
> -			if (asprintf(&s, "%lld", (int64_t)$1) == -1) {
> +			if (asprintf(&s, "%lld", (long long)$1) == -1) {

The long long type is always improper, as is the %lld format that goes
with it.

> @@ -2859,7 +2859,7 @@ host		: STRING			{
>
> 			/* ie. for 10/8 parsing */
> #ifdef __FreeBSD__
> -			if (asprintf(&buf, "%lld/%lld", (int64_t)$1, (int64_t)$3) == -1)
> +			if (asprintf(&buf, "%lld/%lld", (long long)$1, (long long)$3) == -1)
> #else
> 			if (asprintf(&buf, "%lld/%lld", $1, $3) == -1)
> #endif

Why messy ifdefs to keep using the improper type typeof($1) for non-FreeBSD?

Why these messy ifdefs in all places except the first one above?

> Modified: user/eri/pf45/head/contrib/pf/pfctl/pfctl_parser.c
> ==============================================================================
> --- user/eri/pf45/head/contrib/pf/pfctl/pfctl_parser.c	Thu Feb 11 08:50:21 2010	(r203776)
> +++ user/eri/pf45/head/contrib/pf/pfctl/pfctl_parser.c	Thu Feb 11 09:55:45 2010	(r203777)
> @@ -576,7 +576,7 @@ print_status(struct pf_status *s, int op
> 		for (i = 0; i < SCNT_MAX; i++) {
> 			printf("  %-25s %14lld ", pf_scounters[i],
> #ifdef __FreeBSD__
> -				    (int64_t)s->scounters[i]);
> +				    (long long)s->scounters[i]);
> #else
> 				    s->scounters[i]);
> #endif

The type s->scounters is easier to see than the type of $[13] in the
above.  It is certainly not signed long long, at least in the public
version.  It is u_int64_t.  This type should be printed by converting
it to uintmax_t and printing it using format %ju.  The above depends
on the following assumptions:

very old FreeBSD case (the public version):
     The cast seems to have been almost correct.  It was to unsigned long
     long.  That would work, but is ugly, provided the format is unbroken
     too.  The format %lld is only suitable for printing signed values,
     but the value was unsigned long long.  This gave undefined behaviour
     if the value was > LONGLONG_MAX (which is possible though unlikely).
old version (in above):
     Casting to int64_t gives undefined behaviour if sizeof(int64_t) !=
     sizeof(long long).  It happens that sizeof(int64_t) == sizeof(long
     long) for all machines curently supported by FreeBSD, so there is
     no runtime error, but int64_t is carefully chosen so that the
     compiler can detect this type mismatch anyway on 64-bit arches,
     so that printf format errors don't need to be "fixed" for every
     generation of word sizes.  There is still a sign mismatch between
     the variable type and the printf format.  Now the cast is bug-for-
     bug compatible with the format, so there is no undefined behaviour
     for values > INT64_MAX.  Such values are just corrupted by the
     cast in an implementation-defined way, probably to negative values.
new version (in above):
     Since LONG_LONG_MAX >= INT64_MAX, values up to and including
     INT64_MAX can be printed correctly by converting them to long long
     and using %lld format.  There is still a sign mismatch between the
     variable type and the printf format, as above.  This could be fixed
     by converting to unsigned long long and %llu format.  Then there
     would only be style bugs (use of the long long abomination).
non-FreeBSD version:
     This remains plain broken.  It depends on
     sizeof(uint64_t) == sizeof(long long), which is true today on some
     machines, but will break someday (except I fear the people who
     broke long by requiring it to be 32-bits forever for binary
     compatibility will break long long similarly, requiring it to be
     64 bits forever).  It also depends on uint64_t being signed, which
     it isn't, or on the value never exceeding INT64_MAX.

> Modified: user/eri/pf45/head/sys/contrib/pf/net/if_pfsync.c
> ==============================================================================
> --- user/eri/pf45/head/sys/contrib/pf/net/if_pfsync.c	Thu Feb 11 08:50:21 2010	(r203776)
> +++ user/eri/pf45/head/sys/contrib/pf/net/if_pfsync.c	Thu Feb 11 09:55:45 2010	(r203777)
> @@ -2805,7 +2805,7 @@ pfsync_q_ins(struct pf_state *st, int q)
> #if 1 || defined(PFSYNC_DEBUG)
> 	if (sc->sc_len < PFSYNC_MINPKT)
> #ifdef __FreeBSD__
> -		panic("pfsync pkt len is too low %ld", sc->sc_len);
> +		panic("pfsync pkt len is too low %zu", sc->sc_len);
> #else
> 		panic("pfsync pkt len is too low %d", sc->sc_len);
> #endif
>

This is correct iff sc_len has type size_t in FreeBSD and int in non-FreeBSD.
Its type shouldn't be so different.

Bruce


More information about the svn-src-user mailing list