This is the mail archive of the libc-hacker@cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

64bit fix for SunRPC



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)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]