On Mon, Nov 14, 2011, Steffen Daode Nurpmeso wrote:
> Hi,
>
> my dhclient.c patch was very wrong.
> And it (falsely) removed a runtime check of some struct member
> size. But this very hunk (while wrong) led me to a question.
> Since saving even some bytes in shell scripts counts so much,
> i wonder why compile-time assertions are not used at all (AFAIK).
> I.e., the simple change in that POC patch below saves 76 bytes on
> a i386. (And that is only on-disk.)
>
> Is there a reason not to use CTASSERT (and some kind of
> member_sizeof())? I couldn't find just any discussion on that in
> marc and gmane.
Seems like a good idea, but your patch is wrong. Off by one because
strlen != sizeof.
>
> --steffen
>
> Index: sys/sys/cdefs.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/cdefs.h,v
> retrieving revision 1.31
> diff -a -p -u -r1.31 cdefs.h
> --- sys/sys/cdefs.h 1 Oct 2010 04:51:49 -0000 1.31
> +++ sys/sys/cdefs.h 14 Nov 2011 17:21:49 -0000
> @@ -86,6 +86,18 @@
> #define __CONCAT(x,y) x/**/y
> #define __STRING(x) "x"
>
> +/*
> + * Compile time assertion
> + */
> +#define __CTASSERT(X) __CTASSERT1((X), __LINE__)
> +#define __CTASSERT1(X,L) __CTASSERT2((X), L)
> +#define __CTASSERT2(X,L) typedef char __CTASSERT_bail_ ## L[(X) ? 1 : -1]
> +
> +/*
> + * __member_sizeof(T,M) - 0x8 to avoid cc warnings and too aggr.
> optimization
> + */
> +#define __member_sizeof(T,M) sizeof(((T *)0x8)->M)
> +
> #if !defined(__GNUC__) && !defined(lint)
> #define __const /* delete pseudo-ANSI C
> keywords */
> #define __inline
> Index: sbin/dhclient/dhcpd.h
> ===================================================================
> RCS file: /cvs/src/sbin/dhclient/dhcpd.h,v
> retrieving revision 1.73
> diff -a -p -u -r1.73 dhcpd.h
> --- sbin/dhclient/dhcpd.h 11 May 2011 14:38:36 -0000 1.73
> +++ sbin/dhclient/dhcpd.h 14 Nov 2011 17:21:49 -0000
> @@ -189,6 +189,8 @@ struct interface_info {
> int rdomain;
> };
>
> +__CTASSERT(__member_sizeof(struct interface_info, name) >= IFNAMSIZ);
> +
> struct timeout {
> struct timeout *next;
> time_t when;
> Index: sbin/dhclient/dhclient.c
> ===================================================================
> RCS file: /cvs/src/sbin/dhclient/dhclient.c,v
> retrieving revision 1.141
> diff -a -p -u -r1.141 dhclient.c
> --- sbin/dhclient/dhclient.c 11 May 2011 14:38:36 -0000 1.141
> +++ sbin/dhclient/dhclient.c 14 Nov 2011 17:21:49 -0000
> @@ -2103,8 +2103,7 @@ get_ifname(char *ifname, char *arg)
> arg = ifg->ifgrq_member;
> }
>
> - if (strlcpy(ifi->name, arg, IFNAMSIZ) >= IFNAMSIZ)
> - error("Interface name too long: %m");
> + (void)strlcpy(ifi->name, arg, IFNAMSIZ);
>
> free(ifgr.ifgr_groups);
> close(s);