Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 4 Mar 2016 23:32:31 +0100
From:      Jilles Tjoelker <jilles@stack.nl>
To:        "Pedro F. Giffuni" <pfg@FreeBSD.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r296386 - head/lib/libc/rpc
Message-ID:  <20160304223231.GA47504@stack.nl>
In-Reply-To: <201603041530.u24FUfu5021609@repo.freebsd.org>
References:  <201603041530.u24FUfu5021609@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Mar 04, 2016 at 03:30:41PM +0000, Pedro F. Giffuni wrote:
> Author: pfg
> Date: Fri Mar  4 15:30:41 2016
> New Revision: 296386
> URL: https://svnweb.freebsd.org/changeset/base/296386

> Log:
>   Work around aliasing issues detected in modern GCC.

>   Avoid casting gymnastics that lead to pointer aliasing by introducing an
>   inline function as done in NetBSD (but without #if0'd WIP code).

>   Obtained from:	NetBSD (CVS Rev. 1.24, 1.25)

> Modified:
>   head/lib/libc/rpc/clnt_vc.c

> Modified: head/lib/libc/rpc/clnt_vc.c
> ==============================================================================
> --- head/lib/libc/rpc/clnt_vc.c	Fri Mar  4 14:23:34 2016	(r296385)
> +++ head/lib/libc/rpc/clnt_vc.c	Fri Mar  4 15:30:41 2016	(r296386)
> @@ -502,6 +502,20 @@ clnt_vc_abort(CLIENT *cl)
>  {
>  }
>  
> +static __inline void
> +htonlp(void *dst, const void *src, uint32_t incr)
> +{
> +	/* We are aligned, so we think */
> +	*(uint32_t *)dst = htonl(*(const uint32_t *)src + incr);
> +}
> +
> +static __inline void
> +ntohlp(void *dst, const void *src)
> +{
> +	/* We are aligned, so we think */
> +	*(uint32_t *)dst = htonl(*(const uint32_t *)src);
> +}
> +
>  static bool_t
>  clnt_vc_control(CLIENT *cl, u_int request, void *info)
>  {
> @@ -576,14 +590,12 @@ clnt_vc_control(CLIENT *cl, u_int reques
>  		 * first element in the call structure
>  		 * This will get the xid of the PREVIOUS call
>  		 */
> -		*(u_int32_t *)info =
> -		    ntohl(*(u_int32_t *)(void *)&ct->ct_u.ct_mcalli);
> +		ntohlp(info, &ct->ct_u.ct_mcalli);
>  		break;
>  	case CLSET_XID:
>  		/* This will set the xid of the NEXT call */
> -		*(u_int32_t *)(void *)&ct->ct_u.ct_mcalli =
> -		    htonl(*((u_int32_t *)info) + 1);
>  		/* increment by 1 as clnt_vc_call() decrements once */
> +		htonlp(&ct->ct_u.ct_mcalli, info, 1);
>  		break;
>  	case CLGET_VERS:
>  		/*
> @@ -592,15 +604,11 @@ clnt_vc_control(CLIENT *cl, u_int reques
>  		 * begining of the RPC header. MUST be changed if the
>  		 * call_struct is changed
>  		 */
> -		*(u_int32_t *)info =
> -		    ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
> -		    4 * BYTES_PER_XDR_UNIT));
> +		ntohlp(info, ct->ct_u.ct_mcallc + 4 * BYTES_PER_XDR_UNIT);
>  		break;
>  
>  	case CLSET_VERS:
> -		*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
> -		    4 * BYTES_PER_XDR_UNIT) =
> -		    htonl(*(u_int32_t *)info);
> +		htonlp(ct->ct_u.ct_mcallc + 4 * BYTES_PER_XDR_UNIT, info, 0);
>  		break;
>  
>  	case CLGET_PROG:
> @@ -610,15 +618,11 @@ clnt_vc_control(CLIENT *cl, u_int reques
>  		 * begining of the RPC header. MUST be changed if the
>  		 * call_struct is changed
>  		 */
> -		*(u_int32_t *)info =
> -		    ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
> -		    3 * BYTES_PER_XDR_UNIT));
> +		ntohlp(info, ct->ct_u.ct_mcallc + 3 * BYTES_PER_XDR_UNIT);
>  		break;
>  
>  	case CLSET_PROG:
> -		*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
> -		    3 * BYTES_PER_XDR_UNIT) =
> -		    htonl(*(u_int32_t *)info);
> +		htonlp(ct->ct_u.ct_mcallc + 3 * BYTES_PER_XDR_UNIT, info, 0);
>  		break;
>  
>  	default:

This change just deceives GCC's warning logic without changing whether
there is an aliasing violation or not (I don't think there is any when
clnt_vc.c is compiled separately, since *ct does not have an effective
type in that case).

To avoid casts, ct_mcalli could be changed to an array (of
MCALL_MSG_SIZE / 4 elements) and used. This also avoids depending on the
unspecified value of the elements 4 to 23 of ct_mcallc after storing to
ct_mcalli.

Note that C89 did not permit type punning via a union. NetBSD might care
but we do not. C89 compilers are unlikely to be cunning enough for this
to be a problem anyway.

It may be that this code is too old for this kind of change.

-- 
Jilles Tjoelker



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