svn commit: r278589 - head/usr.sbin/flowctl

Bruce Evans brde at optusnet.com.au
Thu Feb 12 11:06:37 UTC 2015


On Wed, 11 Feb 2015, Pedro F. Giffuni wrote:

> Log:
>  flowctl: Replace alloca() with an array.
>
>  Reviewed by:	glebius
>
> Modified:
>  head/usr.sbin/flowctl/flowctl.c
>
> Modified: head/usr.sbin/flowctl/flowctl.c
> ==============================================================================
> --- head/usr.sbin/flowctl/flowctl.c	Wed Feb 11 17:41:23 2015	(r278588)
> +++ head/usr.sbin/flowctl/flowctl.c	Wed Feb 11 17:46:35 2015	(r278589)
> @@ -222,12 +222,10 @@ ctl_show(int argc, char **argv)
> static void
> do_show(int version, void (*func)(struct ngnf_show_header *))
> {
> -	struct ng_mesg *ng_mesg;
> +	struct ng_mesg ng_mesg[SORCVBUF_SIZE];
> 	struct ngnf_show_header req, *resp;
> 	int token, nread;
>
> -	ng_mesg = alloca(SORCVBUF_SIZE);
> -
> 	req.version = version;
> 	req.hash_id = req.list_id = 0;

It is surprising that this even compiles.  It replaces the allocation
of 1 (variable-size, using a perhaps-standard form of the struct hack)
struct of size SORCVBUF_SIZE with that of SORCVBUF_SIZE (fixed-size)
structs, each of too-small size.  This accidentally allocates enough
storage since 1 * SORCVBUF_SIZE < SORCVBUF_SIZE * sizeof(any).

It changes the variable type significantly, from a pointer to 1 struct to
the bogus array.

In 1 place, the array decays to a pointer to its first element without
too much magic.  (The magic is larger than usual since the struct hack
is used.  The first element is too small and is overrun.  This works
because the pointer isn't really a pointer to a struct.)

In 4 places, the array decays to a pointer to its first element more
magically.  It is surprising that ng_mesg->header means the same thing
as ng_mesg[0].header when ng_mesg is an array.

Using alloca() was ugly, but correctly reflected what was going on.
It is an optimization of mallocing the struct.  VLAs don't work as
well as alloca() for variable-sized structs.  I don't see how they
can be used at all.  Since we allocate the maximum size needed, we
don't even need a VLA, and could almost use

 	u_char buf[SORCVBUF_SIZE]
 	struct ng_mesg *ng_mesg;

 	ng_msg = (struct ng_mesg *)buf;

but this doesn't guarantee the necessary alignment like malloc() and
alloca() do.  It also takes more code than alloca().  To get the
necessary alignment, you would have to use some alignment hack,
e.g., put buf in a union with the struct (only works for fixed-size
allocation), or perhaps use an array not quite as in this commit:

 	struct ng_mesg buf[howmany(SORCVBUF_SIZE, sizeof(struct ng_mesg))];
 	struct ng_mesg *ng_mesg;

 	ng_msg = &buf[0];

This form works using VLAs (SORCVBUF_SIZE can be variable), but is much
uglier than using alloca().

Bruce


More information about the svn-src-all mailing list