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>
index | next in thread | raw e-mail
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
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.SUN.3.91.970912095226.28107G-100000>
