Date: Fri, 12 Sep 1997 10:03:05 -0400 (EDT) From: "Ron G. Minnich" <rminnich@Sarnoff.COM> To: hackers@freebsd.org Subject: amusing problem with varargs Message-ID: <Pine.SUN.3.91.970912095226.28107G-100000@terra>
next in thread | raw e-mail | index | archive | help
try the following program: #include <stdio.h> #include <sys/types.h> #include <stdarg.h> int ope9(const char *name, int flags, ...) { mode_t mode; va_list ap; va_start(ap, flags); mode = va_arg(ap, mode_t); va_end(ap); return 1; } main() { int f = ope9("/etc/passwd", 1, 1); } it will on FreeBSD 2.1.0-RELEASE (CLUSTER) #4: Mon Jul 29 11:10:24 EDT 1996 p0 3% ./tv IOT trap (core dumped) p0 4% And on FreeBSD tres.sarnoff.com 2.2.1-RELEASE FreeBSD 2.2.1-RELEASE #0: Tue Apr 1 11:51:00 GMT 1997 jkh@whisker.cdrom.com:/usr/src/sys/compile/GENERIC i386 bash$ ./tv Abort trap (core dumped) bash$ (note different traps ...) It works on: Linux ntan.sarnoff.com 2.1.24 #54 Fri Jun 6 12:54:56 EST 1997 ppc unknown (note: power pc) Linux india.sarnoff.com 2.0.30 #1 Wed Aug 13 14:03:28 EDT 1997 i486 unknown (cyrix) will it fail on other freebsd's, esp. 3.x? The problem is in the following assertion (from stdarg.h) #define va_arg(ap, type) \ ((type *)(ap += sizeof(type) < sizeof(int) ? \ (abort(), 0) : sizeof(type)))[-1] It fails because mode_t is 16 bits. So, I wonder, why did linux work? They appear to use a more sophisticated technique, from gnu cc. from /usr/lib/gcc-lib/powerpc-unknown-linux/2.7.2.1-ppclinux/include/stdarg.h ... /* We cast to void * and then to TYPE * because this avoids a warning about increasing the alignment requirement. */ #if defined (__arm__) || defined (__i386__) || defined (__i860__) || defined (__ns32000__) || defined (__vax__) /* This is for little-endian machines; small args are padded upward. */ #define va_arg(AP, TYPE) \ (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE)))) #else /* big-endian */ /* This is for big-endian machines; small args are padded downward. */ #define va_arg(AP, TYPE) \ (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ *((TYPE *) (void *) ((char *) (AP) \ - ((sizeof (TYPE) < __va_rounded_size (char) \ ? sizeof (TYPE) : __va_rounded_size (TYPE)))))) #endif /* big-endian */ #endif /* _STDARG_H */ FYI -- ron
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.SUN.3.91.970912095226.28107G-100000>