Subject: va_list pointers, bad(?) gcc code
To: None <tech-toolchain@netbsd.org>
From: Frank van der Linden <fvdl@netbsd.org>
List: tech-toolchain
Date: 11/11/2003 10:42:03
Recently, it was reported that compiling the glib2 package (glib 2.2.3)
causes a bus error somewhere along the line on amd64, to be more specific:
when the build process generates a file using an internal tool.

I looked at the problem, and noticed that the problem appeared in code
that passes pointers to varargs lists (va_list *). The code is in
glib/trio/trio.c in the distribution. This is a simple C file
to reproduce the problem (no include files used to make it OS
independent):

==================================

#define va_list __builtin_va_list
#define va_start __builtin_va_start
#define va_arg __builtin_va_arg
#define va_end __builtin_va_end

int printf(const char *, ...);
void vfoo0(const char *, ...);
void vfoo1(const char *, va_list);
void vfoo2(const char *, va_list *);

void
vfoo0(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vfoo1(fmt, ap);
	va_end(ap);
}

void
vfoo1(const char *a, va_list l)
{
	vfoo2(a, &l);
}

void
vfoo2(const char *a, va_list *lp)
{
	int argc;
	char *argv0;

	argc = va_arg(*lp, int);
	argv0 = va_arg(*lp, char *);
	printf(a, argc, argv0);
}

int
main(int argc, char **argv)
{
	vfoo0("%d %s\n", argc, argv[0]);
	return 0;
}

==============================

This works fine on i386. va_list is a simple pointer type there. However,
on amd64, it produces this warning in the call too vfoo2():

va2.c: In function `vfoo1':
va2.c:24: warning: passing arg 2 of `vfoo2' from incompatible pointer type

This is strange, because &l is va_list *, which is the specified type
in the prototype. The code it produces seems bad; it doesn't take the
address of l for the call to vfoo2(), it just passed the argument on
directly. The result is that printf() crashes, because it's passed
bad arguments.

It looks like this is an issue on all platforms on which gcc defines
va_list as an array pointer. I haven't verified this, but on powerpc,
gcc gives the same warning, at least.

What to do? Sure, the code isn't exactly pretty, but it's 3rd party code,
and looks to be legal C. And gcc seems to be messing it up.

- Frank

-- 
Frank van der Linden                                            fvdl@netbsd.org
===============================================================================
NetBSD. Free, Unix-like OS. > 45 different platforms.    http://www.netbsd.org/