This is the mail archive of the
libc-hacker@cygnus.com
mailing list for the glibc project.
64bit fix for SunRPC
- To: libc-hacker@cygnus.com
- Subject: 64bit fix for SunRPC
- From: Thorsten Kukuk <kukuk@suse.de>
- Date: Fri, 5 Mar 1999 13:51:11 +0100
Hi,
I had some problems with seg.faults in the SunRPC code on 64bit
platforms the last days. The problem is, that under some rare
conditions the RPC code gives a pointer to a int32 to a function
which expects a pointer to a long. We casts all access to this
variables to 32 bit integers, but the upper bits will be zero'd,
and we never had allocated this memory.
I have implemented the solution Sun uses for 64bit Solaris 7.
It works fine here on the alphas, and solves my problems.
I hope it breaks nothing else.
Thorsten
--
Thorsten Kukuk http://www.suse.de/~kukuk/ kukuk@suse.de
SuSE GmbH Schanzaeckerstr. 10 90443 Nuernberg
Linux is like a Vorlon. It is incredibly powerful, gives terse,
cryptic answers and has a lot of things going on in the background.
1999-03-05 Thorsten Kukuk <kukuk@suse.de>
* sunrpc/rpc/xdr.h: Add x_getint32/x_putint32 to xdr_ops,
change XDR_GETINT32/XDR_PUTINT32 to sue new functions.
* sunrpc/xdr_mem.c: Add xdrmem_getint32, xdrmem_putint32.
* sunrpc/xdr_rec.c: Add xdrrec_getint32, xdrrec_putint32.
* sunrpc/xdr_sizeof.c: Add x_putint32, add dummy function
for x_getint32.
* sunrpc/xdr_stdio.c: Add xdrstdio_getint32, xdrstdio_putint32.
* nis/nis_print.c: Fix ctime argument for platforms where
sizeof (time_t) != sizeof (int).
diff -u -r --new-file glibc-current/sunrpc/rpc/xdr.h work-2.1/sunrpc/rpc/xdr.h
--- glibc-current/sunrpc/rpc/xdr.h Thu Dec 17 20:35:45 1998
+++ work-2.1/sunrpc/rpc/xdr.h Thu Mar 4 21:40:52 1999
@@ -82,12 +82,11 @@
* XDR_FREE can be used to release the space allocated by an XDR_DECODE
* request.
*/
-enum xdr_op
- {
- XDR_ENCODE = 0,
- XDR_DECODE = 1,
- XDR_FREE = 2
- };
+enum xdr_op {
+ XDR_ENCODE = 0,
+ XDR_DECODE = 1,
+ XDR_FREE = 2
+};
/*
* This is the number of bytes per unit of external data.
@@ -135,6 +134,10 @@
/* buf quick ptr to buffered data */
void (*x_destroy) __PMT ((XDR *__xdrs));
/* free privates of this xdr_stream */
+ bool_t (*x_getint32) __PMT ((XDR *__xdrs, int32_t *__ip));
+ /* get a int from underlying stream */
+ bool_t (*x_putint32) __PMT ((XDR *__xdrs, __const int32_t *__ip));
+ /* put a int to " */
}
*x_ops;
caddr_t x_public; /* users' data */
@@ -165,14 +168,14 @@
* u_int pos;
*/
#define XDR_GETINT32(xdrs, int32p) \
- (*(xdrs)->x_ops->x_getlong)(xdrs, (long *)int32p)
+ (*(xdrs)->x_ops->x_getint32)(xdrs, int32p)
#define xdr_getint32(xdrs, int32p) \
- (*(xdrs)->x_ops->x_getlong)(xdrs, (long *)int32p)
+ (*(xdrs)->x_ops->x_getint32)(xdrs, int32p)
#define XDR_PUTINT32(xdrs, int32p) \
- (*(xdrs)->x_ops->x_putlong)(xdrs, (long *)int32p)
+ (*(xdrs)->x_ops->x_putint32)(xdrs, int32p)
#define xdr_putint32(xdrs, int32p) \
- (*(xdrs)->x_ops->x_putlong)(xdrs, (long *)int32p)
+ (*(xdrs)->x_ops->x_putint32)(xdrs, int32p)
#define XDR_GETLONG(xdrs, longp) \
(*(xdrs)->x_ops->x_getlong)(xdrs, longp)
diff -u -r --new-file glibc-current/sunrpc/xdr_mem.c work-2.1/sunrpc/xdr_mem.c
--- glibc-current/sunrpc/xdr_mem.c Mon Jun 8 14:12:25 1998
+++ work-2.1/sunrpc/xdr_mem.c Thu Mar 4 22:07:16 1999
@@ -54,6 +54,8 @@
static bool_t xdrmem_setpos (XDR *, u_int);
static long *xdrmem_inline (XDR *, int);
static void xdrmem_destroy (XDR *);
+static bool_t xdrmem_getint32 (XDR *, int32_t *);
+static bool_t xdrmem_putint32 (XDR *, const int32_t *);
static const struct xdr_ops xdrmem_ops =
{
@@ -64,7 +66,9 @@
xdrmem_getpos,
xdrmem_setpos,
xdrmem_inline,
- xdrmem_destroy
+ xdrmem_destroy,
+ xdrmem_getint32,
+ xdrmem_putint32
};
/*
@@ -218,4 +222,36 @@
xdrs->x_private += len;
}
return buf;
+}
+
+/*
+ * Gets the next word from the memory referenced by xdrs and places it
+ * in the int pointed to by ip. It then increments the private word to
+ * point at the next element. Neither object pointed to is const
+ */
+static bool_t
+xdrmem_getint32 (XDR *xdrs, int32_t *ip)
+{
+
+ if ((xdrs->x_handy -= 4) < 0)
+ return FALSE;
+ *ip = ntohl ((*((int32_t *) (xdrs->x_private))));
+ xdrs->x_private += 4;
+ return TRUE;
+}
+
+/*
+ * Puts the int pointed to by ip in the memory referenced by xdrs. It
+ * then increments the private word to point at the next element. The
+ * int pointed at is const
+ */
+static bool_t
+xdrmem_putint32 (XDR *xdrs, const int32_t *ip)
+{
+
+ if ((xdrs->x_handy -= 4) < 0)
+ return FALSE;
+ *(int32_t *) xdrs->x_private = htonl (*ip);
+ xdrs->x_private += 4;
+ return TRUE;
}
diff -u -r --new-file glibc-current/sunrpc/xdr_rec.c work-2.1/sunrpc/xdr_rec.c
--- glibc-current/sunrpc/xdr_rec.c Fri Jul 17 23:40:55 1998
+++ work-2.1/sunrpc/xdr_rec.c Thu Mar 4 21:51:20 1999
@@ -66,6 +66,8 @@
static bool_t xdrrec_setpos (XDR *, u_int);
static long *xdrrec_inline (XDR *, int);
static void xdrrec_destroy (XDR *);
+static bool_t xdrrec_getint32 (XDR *, int32_t *);
+static bool_t xdrrec_putint32 (XDR *, const int32_t *);
static const struct xdr_ops xdrrec_ops =
{
@@ -76,7 +78,9 @@
xdrrec_getpos,
xdrrec_setpos,
xdrrec_inline,
- xdrrec_destroy
+ xdrrec_destroy,
+ xdrrec_getint32,
+ xdrrec_putint32
};
/*
@@ -251,11 +255,8 @@
return TRUE;
}
-static bool_t /* must manage buffers, fragments, and records */
-xdrrec_getbytes (xdrs, addr, len)
- XDR *xdrs;
- caddr_t addr;
- u_int len;
+static bool_t /* must manage buffers, fragments, and records */
+xdrrec_getbytes (XDR *xdrs, caddr_t addr, u_int len)
{
RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
u_int current;
@@ -420,6 +421,53 @@
mem_free ((caddr_t) rstrm, sizeof (RECSTREAM));
}
+static bool_t
+xdrrec_getint32 (XDR *xdrs, int32_t *ip)
+{
+ RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+ int32_t *bufip = (int32_t *) rstrm->in_finger;
+ int32_t mylong;
+
+ /* first try the inline, fast case */
+ if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT &&
+ rstrm->in_boundry - (char *) bufip >= BYTES_PER_XDR_UNIT)
+ {
+ *ip = ntohl (*bufip);
+ rstrm->fbtbc -= BYTES_PER_XDR_UNIT;
+ rstrm->in_finger += BYTES_PER_XDR_UNIT;
+ }
+ else
+ {
+ if (!xdrrec_getbytes (xdrs, (caddr_t) &mylong,
+ BYTES_PER_XDR_UNIT))
+ return FALSE;
+ *ip = ntohl (mylong);
+ }
+ return TRUE;
+}
+
+static bool_t
+xdrrec_putint32 (XDR *xdrs, const int32_t *ip)
+{
+ RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private;
+ int32_t *dest_ip = (int32_t *) rstrm->out_finger;
+
+ if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry)
+ {
+ /*
+ * this case should almost never happen so the code is
+ * inefficient
+ */
+ rstrm->out_finger -= BYTES_PER_XDR_UNIT;
+ rstrm->frag_sent = TRUE;
+ if (!flush_out (rstrm, FALSE))
+ return FALSE;
+ dest_ip = (int32_t *) rstrm->out_finger;
+ rstrm->out_finger += BYTES_PER_XDR_UNIT;
+ }
+ *dest_ip = htonl (*ip);
+ return TRUE;
+}
/*
* Exported routines to manage xdr records
diff -u -r --new-file glibc-current/sunrpc/xdr_sizeof.c work-2.1/sunrpc/xdr_sizeof.c
--- glibc-current/sunrpc/xdr_sizeof.c Tue Apr 21 00:19:46 1998
+++ work-2.1/sunrpc/xdr_sizeof.c Thu Mar 4 21:57:07 1999
@@ -123,6 +123,13 @@
return;
}
+static bool_t
+x_putint32 (XDR *xdrs, const int32_t *int32p)
+{
+ xdrs->x_handy += BYTES_PER_XDR_UNIT;
+ return TRUE;
+}
+
unsigned long
xdr_sizeof (xdrproc_t func, void *data)
{
@@ -132,6 +139,7 @@
/* to stop ANSI-C compiler from complaining */
typedef bool_t (*dummyfunc1) (XDR *, long *);
typedef bool_t (*dummyfunc2) (XDR *, caddr_t, u_int);
+ typedef bool_t (*dummyfunc3) (XDR *, int32_t *);
ops.x_putlong = x_putlong;
ops.x_putbytes = x_putbytes;
@@ -139,10 +147,12 @@
ops.x_getpostn = x_getpostn;
ops.x_setpostn = x_setpostn;
ops.x_destroy = x_destroy;
+ ops.x_putint32 = x_putint32;
/* the other harmless ones */
ops.x_getlong = (dummyfunc1) harmless;
ops.x_getbytes = (dummyfunc2) harmless;
+ ops.x_getint32 = (dummyfunc3) harmless;
x.x_op = XDR_ENCODE;
x.x_ops = &ops;
diff -u -r --new-file glibc-current/sunrpc/xdr_stdio.c work-2.1/sunrpc/xdr_stdio.c
--- glibc-current/sunrpc/xdr_stdio.c Fri Jul 17 23:40:55 1998
+++ work-2.1/sunrpc/xdr_stdio.c Thu Mar 4 22:14:22 1999
@@ -61,6 +61,8 @@
static bool_t xdrstdio_setpos (XDR *, u_int);
static long *xdrstdio_inline (XDR *, int);
static void xdrstdio_destroy (XDR *);
+static bool_t xdrstdio_getint32 (XDR *, int32_t *);
+static bool_t xdrstdio_putint32 (XDR *, const int32_t *);
/*
* Ops vector for stdio type XDR
@@ -74,7 +76,9 @@
xdrstdio_getpos, /* get offset in the stream */
xdrstdio_setpos, /* set offset in the stream */
xdrstdio_inline, /* prime stream for inline macros */
- xdrstdio_destroy /* destroy stream */
+ xdrstdio_destroy, /* destroy stream */
+ xdrstdio_getint32, /* deserialize a int */
+ xdrstdio_putint32 /* serialize a int */
};
/*
@@ -180,4 +184,26 @@
* management on this buffer, so we don't do this.
*/
return NULL;
+}
+
+static bool_t
+xdrstdio_getint32 (XDR *xdrs, int32_t *ip)
+{
+ int32_t mycopy;
+
+ if (fread ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1)
+ return FALSE;
+ *ip = ntohl (mycopy);
+ return TRUE;
+}
+
+static bool_t
+xdrstdio_putint32 (XDR *xdrs, const int32_t *ip)
+{
+ int32_t mycopy = htonl (*ip);
+
+ ip = &mycopy;
+ if (fwrite ((caddr_t) ip, 4, 1, (FILE *) xdrs->x_private) != 1)
+ return FALSE;
+ return TRUE;
}
diff -u -r --new-file glibc-current/nis/nis_print.c work-2.1/nis/nis_print.c
--- glibc-current/nis/nis_print.c Wed Jan 20 20:43:17 1999
+++ work-2.1/nis/nis_print.c Thu Mar 4 22:20:10 1999
@@ -1,4 +1,4 @@
-/* Copyright (c) 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (c) 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
@@ -311,6 +311,8 @@
void
nis_print_object (const nis_object * obj)
{
+ time_t buf;
+
printf (_("Object Name : %s\n"), obj->zo_name);
printf (_("Directory : %s\n"), obj->zo_domain);
printf (_("Owner : %s\n"), obj->zo_owner);
@@ -319,8 +321,10 @@
nis_print_rights (obj->zo_access);
printf (_("\nTime to Live : "));
print_ttl (obj->zo_ttl);
- printf (_("Creation Time : %s"), ctime ((time_t *)&obj->zo_oid.ctime));
- printf (_("Mod. Time : %s"), ctime ((time_t *)&obj->zo_oid.mtime));
+ buf = obj->zo_oid.ctime;
+ printf (_("Creation Time : %s"), ctime (&buf));
+ buf = obj->zo_oid.mtime;
+ printf (_("Mod. Time : %s"), ctime (&buf));
fputs (_("Object Type : "), stdout);
nis_print_objtype (obj->zo_data.zo_type);
switch (obj->zo_data.zo_type)