diff --git a/NEWS b/NEWS
index 038690480..6a20225b5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,34 @@
                        User-Visible OpenAFS Changes
 
+OpenAFS 1.6.25
+
+  All client platforms
+
+    * Fix OPENAFS-SA-2024-001: theft of credentials in Unix client PAGs
+      (CVE-2024-10394)
+      Local users can bypass the PAG throttling mechanism in Unix clients and
+      create a PAG using an existing id number and thereby gain access to any
+      credentials in that PAG.
+
+    * Fix OPENAFS-SA-2024-003: buffer overflows in XDR responses
+      (CVE-2024-10397)
+      A malicious server can return more data than the preallocated buffer
+      holds and cause a buffer overflow, which can crash the OpenAFS cache
+      manager and other client utilities, and possibly result in arbitrary
+      code execution.
+
+  All platforms
+
+    * Fix OPENAFS-SA-2024-002: unsafe memory access in ACL processing
+      (CVE-2024-10396)
+      Authenticated users can provide malformed ACLs to the fileserver's
+      StoreACL RPC, causing the fileserver to crash, possibly expose the
+      contents of uninitialized memory, and possibly store garbage data
+      in the audit log.
+      Malicious servers or network MITM can provide malformed ACLs to
+      clients, possibly causing the process to crash and possibly storing
+      the contents of uninitialized memory in ACLs stored on the server.
+
 OpenAFS 1.6.24
 
 All platforms
diff --git a/configure-libafs.ac b/configure-libafs.ac
index 62bcb33d3..66d76bb33 100644
--- a/configure-libafs.ac
+++ b/configure-libafs.ac
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR(src/libafs/Makefile.common.in)
 AM_INIT_AUTOMAKE
 
 AC_CONFIG_HEADER(src/config/afsconfig.h)
-MACOS_VERSION=1.6.24
+MACOS_VERSION=1.6.25
 
 AC_SUBST(MACOS_VERSION)
 
diff --git a/configure.ac b/configure.ac
index 80dca168d..982184ece 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,8 +5,8 @@ AC_CONFIG_SRCDIR([src/config/stds.h])
 AM_INIT_AUTOMAKE
 
 AC_CONFIG_HEADER(src/config/afsconfig.h)
-MACOS_VERSION=1.6.24
-LINUX_PKGVER=1.6.24
+MACOS_VERSION=1.6.25
+LINUX_PKGVER=1.6.25
 
 dnl Debian wants the release candidate version in the main upstream version,
 dnl and wants ~ before it.
diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c
index 172cbc082..b11d6cdf4 100644
--- a/src/WINNT/afsd/cm_ioctl.c
+++ b/src/WINNT/afsd/cm_ioctl.c
@@ -413,7 +413,7 @@ cm_IoctlGetACL(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t
         afid.Unique = scp->fid.unique;
         do {
             acl.AFSOpaque_val = ioctlp->outDatap;
-            acl.AFSOpaque_len = 0;
+	    acl.AFSOpaque_len = SMB_IOCTL_MAXDATA - (ioctlp->outDatap - ioctlp->outAllocp);
             code = cm_ConnFromFID(&scp->fid, userp, reqp, &connp);
             if (code)
                 continue;
@@ -427,6 +427,13 @@ cm_IoctlGetACL(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t
 
         if (code)
             return code;
+	/* Ensure the ACL is a string before trying to treat it like one. */
+	if (acl.AFSOpaque_len == 0 || memchr(acl.AFSOpaque_val, '\0',
+					     acl.AFSOpaque_len) == NULL)
+	    return CM_ERROR_INVAL;
+	/* Reject "strings" with trailing data after the NUL. */
+	if (strlen(acl.AFSOpaque_val) + 1 != acl.AFSOpaque_len)
+	    return CM_ERROR_INVAL;
     }
     /* skip over return data */
     tlen = (int)strlen(ioctlp->outDatap) + 1;
@@ -735,9 +742,6 @@ cm_IoctlGetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
     cm_conn_t *connp;
     AFSFetchVolumeStatus volStat;
     char *cp;
-    char *Name;
-    char *OfflineMsg;
-    char *MOTD;
     struct rx_connection * rxconnp;
 
 #ifdef AFS_FREELANCE_CLIENT
@@ -754,13 +758,18 @@ cm_IoctlGetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
     } else
 #endif
     {
-	Name = volName;
-	OfflineMsg = offLineMsg;
-	MOTD = motd;
+	char *Name = NULL;
+	char *OfflineMsg = NULL;
+	char *MOTD = NULL;
+
 	do {
 	    code = cm_ConnFromFID(&scp->fid, userp, reqp, &connp);
 	    if (code) continue;
 
+	    xdr_free((xdrproc_t) xdr_string, &Name);
+	    xdr_free((xdrproc_t) xdr_string, &OfflineMsg);
+	    xdr_free((xdrproc_t) xdr_string, &MOTD);
+
 	    rxconnp = cm_GetRxConn(connp);
 	    code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
 					 &volStat, &Name, &OfflineMsg, &MOTD);
@@ -768,6 +777,19 @@ cm_IoctlGetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
 
 	} while (cm_Analyze(connp, userp, reqp, &scp->fid, 0, NULL, NULL, NULL, code));
 	code = cm_MapRPCError(code, reqp);
+
+	strncpy(volName, Name, sizeof(volName));
+	volName[sizeof(volName) - 1] = '\0';
+
+	strncpy(offLineMsg, OfflineMsg, sizeof(offLineMsg));
+	offLineMsg[sizeof(offLineMsg) - 1] = '\0';
+
+	strncpy(motd, MOTD, sizeof(motd));
+	motd[sizeof(motd) - 1] = '\0';
+
+	xdr_free((xdrproc_t) xdr_string, &Name);
+	xdr_free((xdrproc_t) xdr_string, &OfflineMsg);
+	xdr_free((xdrproc_t) xdr_string, &MOTD);
     }
 
     if (code)
diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c
index c03dee583..2837184a7 100644
--- a/src/WINNT/afsd/cm_vnodeops.c
+++ b/src/WINNT/afsd/cm_vnodeops.c
@@ -2398,6 +2398,13 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
 	    }
             rx_PutConnection(rxconnp);
 
+	    if (code == 0) {
+		if (statStruct.AFSBulkStats_len != filesThisCall ||
+		    callbackStruct.AFSCBs_len != filesThisCall) {
+		    code = RXGEN_CC_UNMARSHAL;
+		}
+	    }
+
             /*
              * If InlineBulk RPC was called and it succeeded,
              * then pull out the return code from the status info
diff --git a/src/WINNT/afsd/cm_volume.c b/src/WINNT/afsd/cm_volume.c
index 62b30284e..f0cb4d564 100644
--- a/src/WINNT/afsd/cm_volume.c
+++ b/src/WINNT/afsd/cm_volume.c
@@ -442,6 +442,7 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
                         if (code)
                             continue;
 
+			xdr_free((xdrproc_t) xdr_bulkaddrs, &addrs);
                         rxconnp = cm_GetRxConn(connp);
                         code = VL_GetAddrsU(rxconnp, &attrs, &uuid, &unique, &nentries, &addrs);
                         rx_PutConnection(rxconnp);
@@ -455,6 +456,8 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
                     }
                     osi_Log1(afsd_logp, "CALL VL_GetAddrsU serverNumber %u SUCCESS", i);
 
+		    nentries = min(nentries, addrs.bulkaddrs_len);
+
                     addrp = addrs.bulkaddrs_val;
                     for (k = 0; k < nentries && j < NMAXNSERVERS; j++, k++) {
                         serverFlags[j] = uvldbEntry.serverFlags[i];
@@ -1228,22 +1231,12 @@ cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, afs_uint32
     cm_conn_t *connp;
     long code;
     AFSFetchVolumeStatus volStat;
-    char *Name;
-    char *OfflineMsg;
-    char *MOTD;
     cm_req_t req;
     struct rx_connection * rxconnp;
-    char volName[32];
-    char offLineMsg[256];
-    char motd[256];
     long alldown, alldeleted;
     cm_serverRef_t *serversp;
     cm_fid_t fid;
 
-    Name = volName;
-    OfflineMsg = offLineMsg;
-    MOTD = motd;
-
     if (statep->ID != 0 && (!volID || volID == statep->ID)) {
         /* create fid for volume root so that VNOVOL and VMOVED errors can be processed */
         cm_SetFid(&fid, volp->cellp->cellID, statep->ID, 1, 1);
@@ -1285,6 +1278,10 @@ cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, afs_uint32
 
                 lock_ReleaseWrite(&volp->rw);
                 do {
+		    char *Name = NULL;
+		    char *OfflineMsg = NULL;
+		    char *MOTD = NULL;
+
                     code = cm_ConnFromVolume(volp, statep->ID, cm_rootUserp, &req, &connp);
                     if (code)
                         continue;
@@ -1293,6 +1290,11 @@ cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, afs_uint32
                     code = RXAFS_GetVolumeStatus(rxconnp, statep->ID,
                                                  &volStat, &Name, &OfflineMsg, &MOTD);
                     rx_PutConnection(rxconnp);
+
+		    xdr_free((xdrproc_t) xdr_string, &Name);
+		    xdr_free((xdrproc_t) xdr_string, &OfflineMsg);
+		    xdr_free((xdrproc_t) xdr_string, &MOTD);
+
                 } while (cm_Analyze(connp, cm_rootUserp, &req, &fid, 0, NULL, NULL, NULL, code));
                 code = cm_MapRPCError(code, &req);
 
diff --git a/src/WINNT/afsd/fs.c b/src/WINNT/afsd/fs.c
index 5331b3072..704fa5639 100644
--- a/src/WINNT/afsd/fs.c
+++ b/src/WINNT/afsd/fs.c
@@ -547,9 +547,10 @@ PruneList (struct AclEntry **ae, int dfs)
 static char *
 SkipLine (char *astr)
 {
-    while (*astr !='\n')
+    while (*astr != '\0' && *astr !='\n')
+        astr++;
+    if (*astr == '\n')
         astr++;
-    astr++;
     return astr;
 }
 
@@ -566,7 +567,7 @@ EmptyAcl(char *astr)
     struct Acl *tp;
     int junk;
 
-    tp = (struct Acl *)malloc(sizeof (struct Acl));
+    tp = (struct Acl *)calloc(sizeof(*tp), 1);
     assert(tp);
     tp->nplus = tp->nminus = 0;
     tp->pluslist = tp->minuslist = 0;
@@ -588,9 +589,9 @@ EmptyAcl(char *astr)
 static struct Acl *
 ParseAcl (char *astr, int astr_size)
 {
-    int nplus, nminus, i, trights, ret;
+    int nplus, nminus, i, trights = 0, ret;
     size_t len;
-    char tname[MAXNAME];
+    char tname[MAXNAME + 1] = "";
     struct AclEntry *first, *next, *last, *tl;
     struct Acl *ta;
 
@@ -637,7 +638,7 @@ ParseAcl (char *astr, int astr_size)
         if (ret <= 0)
             goto nplus_err;
         astr = SkipLine(astr);
-        tl = (struct AclEntry *) malloc(sizeof (struct AclEntry));
+       tl = (struct AclEntry *) calloc(sizeof(*tl), 1);
         if (tl == NULL)
             goto nplus_err;
         if (!first)
@@ -665,7 +666,7 @@ ParseAcl (char *astr, int astr_size)
         if (ret <= 0)
             goto nminus_err;
         astr = SkipLine(astr);
-        tl = (struct AclEntry *) malloc(sizeof (struct AclEntry));
+       tl = (struct AclEntry *) calloc(sizeof(*tl), 1);
         if (tl == NULL)
             goto nminus_err;
         if (!first)
diff --git a/src/afs/AIX/osi_groups.c b/src/afs/AIX/osi_groups.c
index 2ef317f42..f7bfa9bb8 100644
--- a/src/afs/AIX/osi_groups.c
+++ b/src/afs/AIX/osi_groups.c
@@ -86,6 +86,14 @@ setpag(cred, pagvalue, newpag, change_parent)
     int j;
 
     AFS_STATCNT(setpag);
+
+    if (pagvalue == -1) {
+	code = afs_genpag(*cred, &pagvalue);
+	if (code != 0) {
+	    return (setuerror(code), code);
+	}
+    }
+
 #ifndef AFS_AIX51_ENV
     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
     if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
@@ -99,7 +107,7 @@ setpag(cred, pagvalue, newpag, change_parent)
 	ngroups += 2;
     }
 #endif
-    *newpag = (pagvalue == -1 ? genpag() : pagvalue);
+    *newpag = pagvalue;
 #ifdef AFS_AIX51_ENV
     if (change_parent) {
 	code = kcred_setpag(*cred, PAG_AFS, *newpag);
diff --git a/src/afs/DARWIN/osi_groups.c b/src/afs/DARWIN/osi_groups.c
index 11e65e378..2e3750f35 100644
--- a/src/afs/DARWIN/osi_groups.c
+++ b/src/afs/DARWIN/osi_groups.c
@@ -97,6 +97,14 @@ setpag(proc, cred, pagvalue, newpag, change_parent)
     int j;
 
     AFS_STATCNT(setpag);
+
+    if (pagvalue == -1) {
+	code = afs_genpag(*cred, &pagvalue);
+	if (code != 0) {
+	    return code;
+	}
+    }
+
     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
     if (afs_get_pag_from_groups(gidset[1], gidset[2]) == NOPAG) {
 	/* We will have to shift grouplist to make room for pag */
@@ -108,7 +116,7 @@ setpag(proc, cred, pagvalue, newpag, change_parent)
 	}
 	ngroups += 2;
     }
-    *newpag = (pagvalue == -1 ? genpag() : pagvalue);
+    *newpag = pagvalue;
     afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
     code = afs_setgroups(proc, cred, ngroups, gidset, change_parent);
     return code;
diff --git a/src/afs/FBSD/osi_groups.c b/src/afs/FBSD/osi_groups.c
index e897f4610..295027308 100644
--- a/src/afs/FBSD/osi_groups.c
+++ b/src/afs/FBSD/osi_groups.c
@@ -95,6 +95,14 @@ setpag(struct thread *td, struct ucred **cred, afs_uint32 pagvalue,
     int j;
 
     AFS_STATCNT(setpag);
+
+    if (pagvalue == -1) {
+	code = afs_genpag(*cred, &pagvalue);
+	if (code != 0) {
+	    return code;
+	}
+    }
+
 #ifdef AFS_FBSD80_ENV
     gidset = osi_Alloc(gidset_len * sizeof(gid_t));
 #endif
@@ -109,7 +117,7 @@ setpag(struct thread *td, struct ucred **cred, afs_uint32 pagvalue,
 	}
 	ngroups += 2;
     }
-    *newpag = (pagvalue == -1 ? genpag() : pagvalue);
+    *newpag = pagvalue;
     afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
     code = afs_setgroups(td, cred, ngroups, gidset, change_parent);
 #ifdef AFS_FBSD80_ENV
diff --git a/src/afs/HPUX/osi_groups.c b/src/afs/HPUX/osi_groups.c
index 8d6d9dbd7..87989f6bc 100644
--- a/src/afs/HPUX/osi_groups.c
+++ b/src/afs/HPUX/osi_groups.c
@@ -70,6 +70,14 @@ setpag(cred, pagvalue, newpag, change_parent)
     int j;
 
     AFS_STATCNT(setpag);
+
+    if (pagvalue == -1) {
+	code = afs_genpag(*cred, &pagvalue);
+	if (code != 0) {
+	    return (setuerror(code), code);
+	}
+    }
+
     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
     if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
 	/* We will have to shift grouplist to make room for pag */
@@ -81,7 +89,7 @@ setpag(cred, pagvalue, newpag, change_parent)
 	}
 	ngroups += 2;
     }
-    *newpag = (pagvalue == -1 ? genpag() : pagvalue);
+    *newpag = pagvalue;
     afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
 
     if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) {
diff --git a/src/afs/IRIX/osi_groups.c b/src/afs/IRIX/osi_groups.c
index d028c2026..9d1fc3374 100644
--- a/src/afs/IRIX/osi_groups.c
+++ b/src/afs/IRIX/osi_groups.c
@@ -276,6 +276,17 @@ setpag(cred, pagvalue, newpag, change_parent)
 
     AFS_STATCNT(setpag);
 
+    if (pagvalue == -1) {
+	code = afs_genpag(*cred, &pagvalue);
+	if (code != 0) {
+#if defined(KERNEL_HAVE_UERROR)
+	    return (setuerror(code), code);
+#else
+	    return code;
+#endif
+	}
+    }
+
     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
     if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
 	/* We will have to shift grouplist to make room for pag */
@@ -291,7 +302,7 @@ setpag(cred, pagvalue, newpag, change_parent)
 	}
 	ngroups += 2;
     }
-    *newpag = (pagvalue == -1 ? genpag() : pagvalue);
+    *newpag = pagvalue;
     afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
     if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) {
 #if defined(KERNEL_HAVE_UERROR)
diff --git a/src/afs/LINUX/osi_groups.c b/src/afs/LINUX/osi_groups.c
index de3671c3a..05ccb1ed7 100644
--- a/src/afs/LINUX/osi_groups.c
+++ b/src/afs/LINUX/osi_groups.c
@@ -144,11 +144,19 @@ __setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag,
 {
     struct group_info *group_info;
     struct group_info *tmp;
+    int code;
+
+    if (pagvalue == -1) {
+	code = afs_genpag((afs_ucred_t**)*cr, &pagvalue);
+	if (code != 0) {
+	    return code;
+	}
+    }
 
     get_group_info(afs_cr_group_info(*cr));
     group_info = afs_cr_group_info(*cr);
 
-    *newpag = (pagvalue == -1 ? genpag() : pagvalue);
+    *newpag = pagvalue;
     afs_linux_pag_to_groups(*newpag, group_info, &tmp);
 
     if (old_groups) {
diff --git a/src/afs/NBSD/osi_groups.c b/src/afs/NBSD/osi_groups.c
index 307973ae9..138a7b2d7 100644
--- a/src/afs/NBSD/osi_groups.c
+++ b/src/afs/NBSD/osi_groups.c
@@ -88,6 +88,13 @@ setpag(struct proc *proc, afs_ucred_t *cred, afs_uint32 pagvalue,
     int j;
 
     AFS_STATCNT(setpag);
+
+    if (pagvalue == -1) {
+	code = afs_genpag(*cred, &pagvalue);
+	if (code != 0) {
+	    return code;
+	}
+    }
     ngroups = osi_getgroups(*cred, NGROUPS, gidset);
     if (afs_get_pag_from_groups(gidset[1], gidset[2]) == NOPAG) {
 	/* We will have to shift grouplist to make room for pag */
@@ -99,7 +106,7 @@ setpag(struct proc *proc, afs_ucred_t *cred, afs_uint32 pagvalue,
 	}
 	ngroups += 2;
     }
-    *newpag = (pagvalue == -1 ? genpag() : pagvalue);
+    *newpag = pagvalue;
     afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
     code = osi_setgroups(proc, cred, ngroups, gidset, change_parent);
     return code;
diff --git a/src/afs/OBSD/osi_groups.c b/src/afs/OBSD/osi_groups.c
index e26088f19..2c0ada144 100644
--- a/src/afs/OBSD/osi_groups.c
+++ b/src/afs/OBSD/osi_groups.c
@@ -80,6 +80,14 @@ setpag(struct proc *proc, struct ucred **cred, afs_uint32 pagvalue,
     int j;
 
     AFS_STATCNT(setpag);
+
+    if (pagvalue == -1) {
+	code = afs_genpag(*cred, &pagvalue);
+	if (code != 0) {
+	    return code;
+	}
+    }
+
     ngroups = afs_getgroups(*cred, NGROUPS, gidset);
     /*
      * If the group list is empty, use the task's primary group as the group
@@ -101,7 +109,7 @@ setpag(struct proc *proc, struct ucred **cred, afs_uint32 pagvalue,
 	}
 	ngroups += 2;
     }
-    *newpag = (pagvalue == -1 ? genpag() : pagvalue);
+    *newpag = pagvalue;
     afs_get_groups_from_pag(*newpag, &gidset[1], &gidset[2]);
     code = afs_setgroups(proc, cred, ngroups, gidset, change_parent);
     return code;
diff --git a/src/afs/SOLARIS/osi_groups.c b/src/afs/SOLARIS/osi_groups.c
index 527964b9f..3b3074c9d 100644
--- a/src/afs/SOLARIS/osi_groups.c
+++ b/src/afs/SOLARIS/osi_groups.c
@@ -176,6 +176,13 @@ setpag(cred, pagvalue, newpag, change_parent)
 
     AFS_STATCNT(setpag);
 
+    if (pagvalue == -1) {
+	code = afs_genpag(*cred, &pagvalue);
+	if (code != 0) {
+	    return code;
+	}
+    }
+
     /* Derive gidset size from running kernel's ngroups_max;
      * default 16, but configurable up to 32 (Sol10) or
      * 1024 (Sol11).
@@ -185,8 +192,6 @@ setpag(cred, pagvalue, newpag, change_parent)
     /* must use osi_Alloc, osi_AllocSmallSpace may not be enough. */
     gidset = osi_Alloc(gidset_sz);
 
-    pagvalue = (pagvalue == -1 ? genpag() : pagvalue);
-
     mutex_enter(&curproc->p_crlock);
     ngroups = afs_getgroups(*cred, gidset);
 
diff --git a/src/afs/UKERNEL/osi_groups.c b/src/afs/UKERNEL/osi_groups.c
index f72fd61ac..3aee97f20 100644
--- a/src/afs/UKERNEL/osi_groups.c
+++ b/src/afs/UKERNEL/osi_groups.c
@@ -74,6 +74,13 @@ usr_setpag(struct usr_ucred **cred, afs_uint32 pagvalue, afs_uint32 * newpag,
 
     AFS_STATCNT(setpag);
 
+    if (pagvalue == -1) {
+	code = afs_genpag((afs_ucred_t**)*cred, &pagvalue);
+	if (code != 0) {
+	    return code;
+	}
+    }
+
     gidset = (gid_t *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
     ngroups = afs_getgroups(*cred, gidset);
 
@@ -88,7 +95,7 @@ usr_setpag(struct usr_ucred **cred, afs_uint32 pagvalue, afs_uint32 * newpag,
 	}
 	ngroups += 2;
     }
-    *newpag = (pagvalue == -1 ? genpag() : pagvalue);
+    *newpag = pagvalue;
     afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
     if ((code = afs_setgroups(cred, ngroups, gidset, change_parent))) {
 	osi_FreeSmallSpace((char *)gidset);
diff --git a/src/afs/afs_osi_pag.c b/src/afs/afs_osi_pag.c
index cdb199859..2744b51d6 100644
--- a/src/afs/afs_osi_pag.c
+++ b/src/afs/afs_osi_pag.c
@@ -9,7 +9,7 @@
 
 /*
  * Implements:
- * genpag
+ * genpagval
  * getpag
  * afs_setpag
  * AddPag
@@ -67,8 +67,8 @@ afs_uint32 pagCounter = 0;
  * secure (although of course not absolutely secure).
 */
 #if !defined(UKERNEL)
-afs_uint32
-genpag(void)
+static afs_uint32
+genpagval(void)
 {
     AFS_STATCNT(genpag);
 #ifdef AFS_LINUX20_ENV
@@ -96,8 +96,8 @@ getpag(void)
 /* Web enhancement: we don't need to restrict pags to 41XXXXXX since
  * we are not sharing the space with anyone.  So we use the full 32 bits. */
 
-afs_uint32
-genpag(void)
+static afs_uint32
+genpagval(void)
 {
     AFS_STATCNT(genpag);
 #ifdef AFS_LINUX20_ENV
@@ -181,6 +181,19 @@ afs_pag_wait(afs_ucred_t **acred)
     return 0;
 }
 
+/*
+ * Note that 'acred' is actually an 'afs_ucred_t*', not an 'afs_ucred_t**'. But
+ * various callers and callees expect an 'afs_ucred_t*' due to historical
+ * reasons.
+ */
+afs_int32
+afs_genpag(afs_ucred_t **acred, afs_uint32 *apag)
+{
+    afs_pag_wait(acred);
+    *apag = genpagval();
+    return 0;
+}
+
 int
 #if	defined(AFS_SUN5_ENV)
 afs_setpag(afs_ucred_t **credpp)
@@ -202,6 +215,7 @@ afs_setpag(void)
 #endif
 
     int code = 0;
+    afs_uint32 pag;
 
 #if defined(AFS_SGI53_ENV) && defined(MP)
     /* This is our first chance to get the global lock. */
@@ -210,18 +224,17 @@ afs_setpag(void)
 
     AFS_STATCNT(afs_setpag);
 
-    afs_pag_wait(acred);
-
+    afs_genpag(acred, &pag);
 
 #if	defined(AFS_SUN5_ENV)
-    code = AddPag(genpag(), credpp);
+    code = AddPag(pag, credpp);
 #elif	defined(AFS_FBSD_ENV)
-    code = AddPag(td, genpag(), &td->td_ucred);
+    code = AddPag(td, pag, &td->td_ucred);
 #elif   defined(AFS_NBSD40_ENV)
     /* XXXX won't work */
-    code = AddPag(p, genpag(), (afs_ucred_t **) osi_curcred());
+    code = AddPag(p, pag, (afs_ucred_t **) osi_curcred());
 #elif	defined(AFS_XBSD_ENV)
-    code = AddPag(p, genpag(), &p->p_rcred);
+    code = AddPag(p, pag, &p->p_rcred);
 #elif	defined(AFS_AIX41_ENV)
     {
 	struct ucred *credp;
@@ -229,7 +242,7 @@ afs_setpag(void)
 
 	credp = crref();
 	credp0 = credp;
-	code = AddPag(genpag(), &credp);
+	code = AddPag(pag, &credp);
 	/* If AddPag() didn't make a new cred, then free our cred ref */
 	if (credp == credp0) {
 	    crfree(credp);
@@ -238,36 +251,36 @@ afs_setpag(void)
 #elif	defined(AFS_HPUX110_ENV)
     {
 	struct ucred *credp = p_cred(u.u_procp);
-	code = AddPag(genpag(), &credp);
+	code = AddPag(pag, &credp);
     }
 #elif	defined(AFS_SGI_ENV)
     {
 	cred_t *credp;
 	credp = OSI_GET_CURRENT_CRED();
-	code = AddPag(genpag(), &credp);
+	code = AddPag(pag, &credp);
     }
 #elif	defined(AFS_LINUX20_ENV)
     {
 	afs_ucred_t *credp = crref();
-	code = AddPag(genpag(), &credp);
+	code = AddPag(pag, &credp);
 	crfree(credp);
     }
 #elif defined(AFS_DARWIN80_ENV)
     {
 	afs_ucred_t *credp = kauth_cred_proc_ref(p);
-	code = AddPag(p, genpag(), &credp);
+	code = AddPag(p, pag, &credp);
 	crfree(credp);
     }
 #elif defined(AFS_DARWIN_ENV)
     {
 	afs_ucred_t *credp = crdup(p->p_cred->pc_ucred);
-	code = AddPag(p, genpag(), &credp);
+	code = AddPag(p, pag, &credp);
 	crfree(credp);
     }
 #elif defined(UKERNEL)
-    code = AddPag(genpag(), &(get_user_struct()->u_cred));
+    code = AddPag(pag, &(get_user_struct()->u_cred));
 #else
-    code = AddPag(genpag(), &u.u_cred);
+    code = AddPag(pag, &u.u_cred);
 #endif
 
     afs_Trace1(afs_iclSetp, CM_TRACE_SETPAG, ICL_TYPE_INT32, code);
@@ -288,7 +301,7 @@ afs_setpag(void)
 /*
  * afs_setpag_val
  * This function is like setpag but sets the current thread's pag id to a
- * caller-provided value instead of calling genpag().  This implements a
+ * caller-provided value instead of calling afs_genpag().  This implements a
  * form of token caching since the caller can recall a particular pag value
  * for the thread to restore tokens, rather than reauthenticating.
  */
diff --git a/src/afs/afs_pag_call.c b/src/afs/afs_pag_call.c
index a1f40b580..edcc30109 100644
--- a/src/afs/afs_pag_call.c
+++ b/src/afs/afs_pag_call.c
@@ -493,6 +493,8 @@ afs_syscall_pioctl(path, com, cmarg, follow)
 	goto out_idata;
     }
 
+    memset(odata.rmtbulk_val, 0, out_size);
+
     AFS_GUNLOCK();
     code = RMTSYS_Pioctl(rmtsys_conn, &ccred, abspath, com, follow,
 			 &idata, &odata, &err);
diff --git a/src/afs/afs_pioctl.c b/src/afs/afs_pioctl.c
index d96d7b714..36d67f1d3 100644
--- a/src/afs/afs_pioctl.c
+++ b/src/afs/afs_pioctl.c
@@ -1590,13 +1590,13 @@ DECL_PIOCTL(PGetAcl)
 	    return ERANGE;
 	Fid.Vnode |= (ain->remaining << 30);
     }
-    acl.AFSOpaque_val = aout->ptr;
+    memset(&acl, 0, sizeof(acl));
     do {
 	tconn = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn);
 	if (tconn) {
-	    acl.AFSOpaque_val[0] = '\0';
 	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
 	    RX_AFS_GUNLOCK();
+	    xdr_free((xdrproc_t) xdr_AFSOpaque, &acl);
 	    code = RXAFS_FetchACL(rxconn, &Fid, &acl, &OutStatus, &tsync);
 	    RX_AFS_GLOCK();
 	    XSTATS_END_TIME;
@@ -1607,11 +1607,22 @@ DECL_PIOCTL(PGetAcl)
 	      SHARED_LOCK, NULL));
 
     if (code == 0) {
-	if (acl.AFSOpaque_len == 0)
-	    afs_pd_skip(aout, 1); /* leave the NULL */
-	else
-	    afs_pd_skip(aout, acl.AFSOpaque_len); /* Length of the ACL */
+	if (acl.AFSOpaque_len == 0) {
+	    code = afs_pd_putBytes(aout, "\0", 1); /* leave a single NUL byte */
+
+	} else if (memchr(acl.AFSOpaque_val, '\0', acl.AFSOpaque_len) == NULL) {
+	    /* Do not return an unterminated ACL string. */
+	    code = EINVAL;
+
+	} else if (strlen(acl.AFSOpaque_val) + 1 != acl.AFSOpaque_len) {
+	    /* Do not return an ACL string that has data beyond the trailing NUL. */
+	    code = EINVAL;
+
+	} else {
+	    code = afs_pd_putBytes(aout, acl.AFSOpaque_val, acl.AFSOpaque_len);
+	}
     }
+    xdr_free((xdrproc_t) xdr_AFSOpaque, &acl);
     return code;
 }
 
@@ -1961,32 +1972,31 @@ DECL_PIOCTL(PSetTokens)
  */
 DECL_PIOCTL(PGetVolumeStatus)
 {
-    char volName[32];
-    char *offLineMsg = afs_osi_Alloc(256);
-    char *motd = afs_osi_Alloc(256);
+    char *volName = NULL;
+    char *offLineMsg = NULL;
+    char *motd = NULL;
     struct afs_conn *tc;
     afs_int32 code = 0;
     struct AFSFetchVolumeStatus volstat;
-    char *Name;
     struct rx_connection *rxconn;
     XSTATS_DECLS;
 
-    osi_Assert(offLineMsg != NULL);
-    osi_Assert(motd != NULL);
     AFS_STATCNT(PGetVolumeStatus);
     if (!avc) {
 	code = EINVAL;
 	goto out;
     }
-    Name = volName;
     do {
 	tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn);
 	if (tc) {
 	    XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
 	    RX_AFS_GUNLOCK();
+	    xdr_free((xdrproc_t) xdr_string, &volName);
+	    xdr_free((xdrproc_t) xdr_string, &offLineMsg);
+	    xdr_free((xdrproc_t) xdr_string, &motd);
 	    code =
 		RXAFS_GetVolumeStatus(rxconn, avc->f.fid.Fid.Volume, &volstat,
-				      &Name, &offLineMsg, &motd);
+				      &volName, &offLineMsg, &motd);
 	    RX_AFS_GLOCK();
 	    XSTATS_END_TIME;
 	} else
@@ -2007,8 +2017,9 @@ DECL_PIOCTL(PGetVolumeStatus)
     if (afs_pd_putString(aout, motd) != 0)
 	return E2BIG;
   out:
-    afs_osi_Free(offLineMsg, 256);
-    afs_osi_Free(motd, 256);
+    xdr_free((xdrproc_t) xdr_string, &volName);
+    xdr_free((xdrproc_t) xdr_string, &offLineMsg);
+    xdr_free((xdrproc_t) xdr_string, &motd);
     return code;
 }
 
@@ -4615,7 +4626,13 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
     *acred = newcred;
     if (!code && *com == PSETPAG) {
 	/* Special case for 'setpag' */
-	afs_uint32 pagvalue = genpag();
+	afs_uint32 pagvalue;
+
+	code = afs_genpag(*acred, &pagvalue);
+	if (code != 0) {
+	    EXP_RELE(outexporter);
+	    return code;
+	}
 
 	au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
 	/*
diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h
index 238696359..7e8fa4403 100644
--- a/src/afs/afs_prototypes.h
+++ b/src/afs/afs_prototypes.h
@@ -589,7 +589,7 @@ extern int afs_setpag(afs_proc_t *p, void *args, int *retval);
 extern int afs_setpag(void);
 #endif
 
-extern afs_uint32 genpag(void);
+extern afs_int32 afs_genpag(afs_ucred_t **acred, afs_uint32 *apag);
 extern afs_uint32 getpag(void);
 #if defined(AFS_FBSD_ENV)
 extern int AddPag(struct thread *td, afs_int32 aval, afs_ucred_t **credpp);
diff --git a/src/afs/afs_stats.h b/src/afs/afs_stats.h
index 71e337e63..c24c7202a 100644
--- a/src/afs/afs_stats.h
+++ b/src/afs/afs_stats.h
@@ -545,7 +545,7 @@ struct afs_MeanStats {
     AFS_CS(afs_swapvp)		/* afs_vfsops.c */ \
     AFS_CS(afs_AddMarinerName)	/* afs_vnodeops.c */ \
     AFS_CS(afs_setpag)		/* afs_vnodeops.c */ \
-    AFS_CS(genpag)		/* afs_vnodeops.c */ \
+    AFS_CS(genpag)		/* afs_vnodeops.c, renamed to genpagval() */ \
     AFS_CS(getpag)		/* afs_vnodeops.c */ \
     AFS_CS(afs_GetMariner)	/* afs_vnodeops.c */ \
     AFS_CS(afs_badop)		/* afs_vnodeops.c */ \
diff --git a/src/afs/afs_volume.c b/src/afs/afs_volume.c
index eee883ad1..cb74bd09c 100644
--- a/src/afs/afs_volume.c
+++ b/src/afs/afs_volume.c
@@ -1138,6 +1138,7 @@ LockAndInstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
 					 0, &rxconn);
 		    if (tconn) {
 			RX_AFS_GUNLOCK();
+			xdr_free((xdrproc_t) xdr_bulkaddrs, &addrs);
 			code =
 			    VL_GetAddrsU(rxconn, &attrs, &uuid, &unique,
 					 &nentries, &addrs);
@@ -1158,6 +1159,10 @@ LockAndInstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell,
 		    return;
 		}
 
+		if (addrs.bulkaddrs_len < nentries) {
+		    nentries = addrs.bulkaddrs_len;
+		}
+
 		addrp = addrs.bulkaddrs_val;
 		for (k = 0; k < nentries; k++) {
 		    addrp[k] = htonl(addrp[k]);
diff --git a/src/bozo/bos.c b/src/bozo/bos.c
index 8d0cb6869..d0c90ed33 100644
--- a/src/bozo/bos.c
+++ b/src/bozo/bos.c
@@ -380,13 +380,12 @@ UnInstall(struct cmd_syndesc *as, void *arock)
 static afs_int32
 GetServerGoal(struct rx_connection *aconn, char *aname)
 {
-    char buffer[500];
-    char *tp;
+    char *itype = NULL;
     afs_int32 code;
     struct bozo_status istatus;
 
-    tp = buffer;
-    code = BOZO_GetInstanceInfo(aconn, aname, &tp, &istatus);
+    code = BOZO_GetInstanceInfo(aconn, aname, &itype, &istatus);
+    xdr_free((xdrproc_t)xdr_string, &itype);
     if (code) {
 	printf("bos: failed to get instance info for '%s' (%s)\n", aname,
 	       em(code));
@@ -730,28 +729,31 @@ ListHosts(struct cmd_syndesc *as, void *arock)
 {
     struct rx_connection *tconn;
     afs_int32 code;
-    char tbuffer[256];
-    char *tp;
+    char *cellname = NULL;
+    char *hostname = NULL;
     afs_int32 i;
 
-    tp = tbuffer;
     tconn = GetConn(as, 0);
-    code = BOZO_GetCellName(tconn, &tp);
+    code = BOZO_GetCellName(tconn, &cellname);
     if (code) {
 	printf("bos: failed to get cell name (%s)\n", em(code));
 	exit(1);
     }
-    printf("Cell name is %s\n", tbuffer);
+    printf("Cell name is %s\n", cellname);
     for (i = 0;; i++) {
-	code = BOZO_GetCellHost(tconn, i, &tp);
+	xdr_free((xdrproc_t)xdr_string, &hostname);
+	code = BOZO_GetCellHost(tconn, i, &hostname);
 	if (code == BZDOM)
 	    break;
 	if (code != 0) {
 	    printf("bos: failed to get cell host %d (%s)\n", i, em(code));
 	    exit(1);
 	}
-	printf("    Host %d is %s\n", i + 1, tbuffer);
+	printf("    Host %d is %s\n", i + 1, hostname);
     }
+
+    xdr_free((xdrproc_t)xdr_string, &cellname);
+    xdr_free((xdrproc_t)xdr_string, &hostname);
     return 0;
 }
 
@@ -943,23 +945,22 @@ ListSUsers(struct cmd_syndesc *as, void *arock)
     struct rx_connection *tconn;
     int i;
     afs_int32 code;
-    char tbuffer[256];
-    char *tp;
+    char *name = NULL;
     int lastNL, printGreeting;
 
     tconn = GetConn(as, 0);
     lastNL = 0;
     printGreeting = 1;
     for (i = 0;; i++) {
-	tp = tbuffer;
-	code = BOZO_ListSUsers(tconn, i, &tp);
+	xdr_free((xdrproc_t)xdr_string, &name);
+	code = BOZO_ListSUsers(tconn, i, &name);
 	if (code)
 	    break;
 	if (printGreeting) {
 	    printGreeting = 0;	/* delay until after first call succeeds */
 	    printf("SUsers are: ");
 	}
-	printf("%s ", tbuffer);
+	printf("%s ", name);
 	if ((i % NPERLINE) == NPERLINE - 1) {
 	    printf("\n");
 	    lastNL = 1;
@@ -969,11 +970,15 @@ ListSUsers(struct cmd_syndesc *as, void *arock)
     if (code != 1) {
 	/* a real error code, instead of scanned past end */
 	printf("bos: failed to retrieve super-user list (%s)\n", em(code));
-	return code;
+	goto done;
     }
     if (lastNL == 0)
 	printf("\n");
-    return 0;
+    code = 0;
+
+  done:
+    xdr_free((xdrproc_t)xdr_string, &name);
+    return code;
 }
 
 static int
@@ -982,8 +987,7 @@ StatServer(struct cmd_syndesc *as, void *arock)
     struct rx_connection *tconn;
     afs_int32 code;
     int i;
-    char ibuffer[BOZO_BSSIZE];
-    char *tp;
+    char *iname = NULL;
     int int32p;
 
     /* int32p==1 is obsolete, smaller, printout */
@@ -996,8 +1000,8 @@ StatServer(struct cmd_syndesc *as, void *arock)
     tconn = GetConn(as, 0);
     for (i = 0;; i++) {
 	/* for each instance */
-	tp = ibuffer;
-	code = BOZO_EnumerateInstance(tconn, i, &tp);
+	xdr_free((xdrproc_t)xdr_string, &iname);
+	code = BOZO_EnumerateInstance(tconn, i, &iname);
 	if (code == BZDOM)
 	    break;
 	if (code) {
@@ -1005,8 +1009,10 @@ StatServer(struct cmd_syndesc *as, void *arock)
 		   em(code));
 	    break;
 	}
-	DoStat(ibuffer, tconn, int32p, (i == 0));	/* print status line */
+	DoStat(iname, tconn, int32p, (i == 0));	/* print status line */
     }
+
+    xdr_free((xdrproc_t)xdr_string, &iname);
     return 0;
 }
 
@@ -1300,9 +1306,10 @@ DoSalvage(struct rx_connection * aconn, char * aparm1, char * aparm2,
     /* now wait for bnode to disappear */
     count = 0;
     while (1) {
+	char *itype = NULL;
 	IOMGR_Sleep(1);
-	tp = tbuffer;
-	code = BOZO_GetInstanceInfo(aconn, "salvage-tmp", &tp, &istatus);
+	code = BOZO_GetInstanceInfo(aconn, "salvage-tmp", &itype, &istatus);
+	xdr_free((xdrproc_t)xdr_string, &itype);
 	if (code)
 	    break;
 	if ((count++ % 5) == 0)
@@ -1386,14 +1393,12 @@ GetLogCmd(struct cmd_syndesc *as, void *arock)
 static int
 IsDAFS(struct rx_connection *aconn)
 {
-    char buffer[BOZO_BSSIZE];
-    char *tp;
+    char *itype = NULL;
     struct bozo_status istatus;
     afs_int32 code;
 
-    tp = &buffer[0];
-
-    code = BOZO_GetInstanceInfo(aconn, "dafs", &tp, &istatus);
+    code = BOZO_GetInstanceInfo(aconn, "dafs", &itype, &istatus);
+    xdr_free((xdrproc_t)xdr_string, &itype);
     if (code) {
 	/* no dafs bnode; cannot be dafs */
 	return 0;
@@ -1724,26 +1729,30 @@ DoStat(IN char *aname,
        IN int firstTime) 	/* true iff first instance in cmd */
 {
     afs_int32 temp;
-    char buffer[500];
     afs_int32 code;
     afs_int32 i;
     struct bozo_status istatus;
-    char *tp;
-    char *is1, *is2, *is3, *is4;	/* instance strings */
-
-    tp = buffer;
-    code = BOZO_GetInstanceInfo(aconn, aname, &tp, &istatus);
+    char *itype = NULL;
+    char *is1 = NULL;
+    char *is2 = NULL;
+    char *is3 = NULL;
+    char *is4 = NULL;
+    char *desc = NULL;
+    char *parm = NULL;
+    char *notifier_parm = NULL;
+
+    code = BOZO_GetInstanceInfo(aconn, aname, &itype, &istatus);
     if (code) {
 	printf("bos: failed to get instance info for '%s' (%s)\n", aname,
 	       em(code));
-	return -1;
+	goto done;
     }
     if (firstTime && aint32p && (istatus.flags & BOZO_BADDIRACCESS))
 	printf
 	    ("Bosserver reports inappropriate access on server directories\n");
     printf("Instance %s, ", aname);
     if (aint32p)
-	printf("(type is %s) ", buffer);
+	printf("(type is %s) ", itype);
     if (istatus.fileGoal == istatus.goal) {
 	if (!istatus.goal)
 	    printf("disabled, ");
@@ -1759,8 +1768,7 @@ DoStat(IN char *aname,
     if (istatus.flags & BOZO_HASCORE)
 	printf("has core file, ");
 
-    tp = buffer;
-    code = BOZO_GetStatus(aconn, aname, &temp, &tp);
+    code = BOZO_GetStatus(aconn, aname, &temp, &desc);
     if (code)
 	printf("bos: failed to get status for instance '%s' (%s)\n", aname,
 	       em(code));
@@ -1774,14 +1782,16 @@ DoStat(IN char *aname,
 	    printf("starting up.\n");
 	else if (temp == BSTAT_SHUTTINGDOWN)
 	    printf("shutting down.\n");
-	if (buffer[0] != 0) {
-	    printf("    Auxiliary status is: %s.\n", buffer);
+	if (desc[0] != '\0') {
+	    printf("    Auxiliary status is: %s.\n", desc);
 	}
     }
 
     /* are we done yet? */
-    if (!aint32p)
-	return 0;
+    if (!aint32p) {
+	code = 0;
+	goto done;
+    }
 
     if (istatus.procStartTime)
 	printf("    Process last started at %s (%d proc starts)\n",
@@ -1790,7 +1800,6 @@ DoStat(IN char *aname,
 	printf("    Last exit at %s\n", DateOf(istatus.lastAnyExit));
     }
     if (istatus.lastErrorExit) {
-	is1 = is2 = is3 = is4 = NULL;
 	printf("    Last error exit at %s, ", DateOf(istatus.lastErrorExit));
 	code = BOZO_GetInstanceStrings(aconn, aname, &is1, &is2, &is3, &is4);
 	/* don't complain about failing call, since could simply mean
@@ -1801,10 +1810,6 @@ DoStat(IN char *aname,
 		/* non-null instance string */
 		printf("by %s, ", is1);
 	    }
-	    free(is1);
-	    free(is2);
-	    free(is3);
-	    free(is4);
 	}
 	if (istatus.errorSignal) {
 	    if (istatus.errorSignal == SIGTERM)
@@ -1818,21 +1823,31 @@ DoStat(IN char *aname,
     if (aint32p > 1) {
 	/* try to display all the parms */
 	for (i = 0;; i++) {
-	    tp = buffer;
-	    code = BOZO_GetInstanceParm(aconn, aname, i, &tp);
+	    xdr_free((xdrproc_t)xdr_string, &parm);
+	    code = BOZO_GetInstanceParm(aconn, aname, i, &parm);
 	    if (code)
 		break;
-	    printf("    Command %d is '%s'\n", i + 1, buffer);
+	    printf("    Command %d is '%s'\n", i + 1, parm);
 	}
-	tp = buffer;
-	code = BOZO_GetInstanceParm(aconn, aname, 999, &tp);
+	code = BOZO_GetInstanceParm(aconn, aname, 999, &notifier_parm);
 	if (!code) {
 	    /* Any type of failure is treated as not having a notifier program */
-	    printf("    Notifier  is '%s'\n", buffer);
+	    printf("    Notifier  is '%s'\n", notifier_parm);
 	}
 	printf("\n");
     }
-    return 0;
+    code = 0;
+
+  done:
+    xdr_free((xdrproc_t)xdr_string, &itype);
+    xdr_free((xdrproc_t)xdr_string, &is1);
+    xdr_free((xdrproc_t)xdr_string, &is2);
+    xdr_free((xdrproc_t)xdr_string, &is3);
+    xdr_free((xdrproc_t)xdr_string, &is4);
+    xdr_free((xdrproc_t)xdr_string, &desc);
+    xdr_free((xdrproc_t)xdr_string, &parm);
+    xdr_free((xdrproc_t)xdr_string, &notifier_parm);
+    return code;
 }
 
 static int
diff --git a/src/bucoord/commands.c b/src/bucoord/commands.c
index 54a978ce6..9d2a7d071 100644
--- a/src/bucoord/commands.c
+++ b/src/bucoord/commands.c
@@ -2754,6 +2754,8 @@ DBLookupByVolume(char *volumeName)
     char vname[BU_MAXNAMELEN];
     char ds[50];
 
+    memset(volumeEntry, 0, sizeof(volumeEntry));
+
     for (pass = 0; pass < 2; pass++) {
 	/*p */
 	/* On second pass, search for backup volume */
diff --git a/src/bucoord/restore.c b/src/bucoord/restore.c
index 69bfba294..6eac5b7b5 100644
--- a/src/bucoord/restore.c
+++ b/src/bucoord/restore.c
@@ -199,7 +199,7 @@ bc_Restorer(afs_int32 aindex)
     partitionAll = dumpTaskPtr->destPartition;
 
     volumeEntries = (struct budb_volumeEntry *)
-	malloc(MAXTAPESATONCE * sizeof(struct budb_volumeEntry));
+	calloc(MAXTAPESATONCE, sizeof(struct budb_volumeEntry));
     if (!volumeEntries) {
 	afs_com_err(whoami, BC_NOMEM, NULL);
 	ERROR(BC_NOMEM);
diff --git a/src/bucoord/ubik_db_if.c b/src/bucoord/ubik_db_if.c
index 9be620312..62fb81108 100644
--- a/src/bucoord/ubik_db_if.c
+++ b/src/bucoord/ubik_db_if.c
@@ -126,6 +126,12 @@ afs_int32 bcdb_listDumps (afs_int32 sflags, afs_int32 groupId,
 	free(dumpsList.budb_dumpsList_val);
     if (flagsList.budb_dumpsList_val)
 	free(flagsList.budb_dumpsList_val);
+
+    if (code == 0 &&
+	dumpsPtr->budb_dumpsList_len != flagsPtr->budb_dumpsList_len) {
+	code = BUDB_INTERNALERROR;
+    }
+
     return (code);
 }
 
diff --git a/src/butc/dump.c b/src/butc/dump.c
index 8fcc61a05..6a4cff19a 100644
--- a/src/butc/dump.c
+++ b/src/butc/dump.c
@@ -201,6 +201,18 @@ Bind(afs_uint32 server)
     return (curr_fromconn);
 }
 
+static int
+ListOneVolume(struct rx_connection *aconn, afs_int32 apart, afs_uint32 avolid,
+	      volEntries *entries)
+{
+    afs_int32 code;
+    code = AFSVolListOneVolume(aconn, apart, avolid, entries);
+    if (code == 0 && entries->volEntries_len != 1) {
+	code = VOLSERFAILEDOP;
+    }
+    return code;
+}
+
 /* notes
  * 1) save the chunksize or otherwise ensure tape space remaining is
  *	check frequently enough
@@ -245,8 +257,7 @@ dumpVolume(struct tc_dumpDesc * curDump, struct dumpRock * dparamsPtr)
     /* Determine when the volume was last cloned and updated */
     volumeInfo.volEntries_val = (volintInfo *) 0;
     volumeInfo.volEntries_len = 0;
-    rc = AFSVolListOneVolume(fromconn, curDump->partition, curDump->vid,
-			     &volumeInfo);
+    rc = ListOneVolume(fromconn, curDump->partition, curDump->vid, &volumeInfo);
     if (rc)
 	ERROR_EXIT(rc);
     updatedate = volumeInfo.volEntries_val[0].updateDate;
@@ -574,8 +585,7 @@ xbsaDumpVolume(struct tc_dumpDesc * curDump, struct dumpRock * dparamsPtr)
     /* Determine when the volume was last cloned and updated */
     volumeInfo.volEntries_val = (volintInfo *) 0;
     volumeInfo.volEntries_len = 0;
-    rc = AFSVolListOneVolume(fromconn, curDump->partition, curDump->vid,
-			     &volumeInfo);
+    rc = ListOneVolume(fromconn, curDump->partition, curDump->vid, &volumeInfo);
     if (rc)
 	ERROR_EXIT(rc);
     updatedate = volumeInfo.volEntries_val[0].updateDate;
diff --git a/src/config/NTMakefile.amd64_w2k b/src/config/NTMakefile.amd64_w2k
index 24cd10a48..6077eb9a1 100644
--- a/src/config/NTMakefile.amd64_w2k
+++ b/src/config/NTMakefile.amd64_w2k
@@ -90,7 +90,7 @@ AFSPRODUCT_VER_MAJOR=1
 AFSPRODUCT_VER_MINOR=6
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_PATCH)
-AFSPRODUCT_VER_PATCH=2400
+AFSPRODUCT_VER_PATCH=2500
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_BUILD)
 AFSPRODUCT_VER_BUILD=0
diff --git a/src/config/NTMakefile.i386_nt40 b/src/config/NTMakefile.i386_nt40
index 627a54752..cf8f5274f 100644
--- a/src/config/NTMakefile.i386_nt40
+++ b/src/config/NTMakefile.i386_nt40
@@ -90,7 +90,7 @@ AFSPRODUCT_VER_MAJOR=1
 AFSPRODUCT_VER_MINOR=6
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_PATCH)
-AFSPRODUCT_VER_PATCH=2400
+AFSPRODUCT_VER_PATCH=2500
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_BUILD)
 AFSPRODUCT_VER_BUILD=0
diff --git a/src/config/NTMakefile.i386_w2k b/src/config/NTMakefile.i386_w2k
index 4c20879d0..655838afd 100644
--- a/src/config/NTMakefile.i386_w2k
+++ b/src/config/NTMakefile.i386_w2k
@@ -94,7 +94,7 @@ AFSPRODUCT_VER_MAJOR=1
 AFSPRODUCT_VER_MINOR=6
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_PATCH)
-AFSPRODUCT_VER_PATCH=2400
+AFSPRODUCT_VER_PATCH=2500
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_BUILD)
 AFSPRODUCT_VER_BUILD=0
diff --git a/src/fsprobe/fsprobe.c b/src/fsprobe/fsprobe.c
index f5008ac5b..88a47532e 100644
--- a/src/fsprobe/fsprobe.c
+++ b/src/fsprobe/fsprobe.c
@@ -225,6 +225,7 @@ fsprobe_LWP(void *unused)
     struct ProbeViceStatistics *curr_stats;	/*Current stats region */
     int *curr_probeOK;		/*Current probeOK field */
     ViceStatistics64 stats64;      /*Current stats region */
+    stats64.ViceStatistics64_len = STATS64_VERSION;
     stats64.ViceStatistics64_val = (afs_uint64 *)malloc(STATS64_VERSION *
 							sizeof(afs_uint64));
     while (1) {			/*Service loop */
diff --git a/src/kauth/authclient.c b/src/kauth/authclient.c
index 0d577714e..300f9ddf5 100644
--- a/src/kauth/authclient.c
+++ b/src/kauth/authclient.c
@@ -540,12 +540,15 @@ ka_Authenticate(char *name, char *instance, char *cell, struct ubik_client * con
     oanswer.MaxSeqLen = sizeof(answer);
     oanswer.SeqLen = 0;
     oanswer.SeqBody = (char *)&answer;
+    memset(&answer, 0, sizeof(answer));
+    memset(&answer_old, 0, sizeof(answer_old));
 
     version = 2;
     code =
 	kawrap_ubik_Call(KAA_AuthenticateV2, conn, 0, name, instance,
 			 (void*)(uintptr_t)start, (void*)(uintptr_t)end, &arequest, &oanswer, 0, 0);
     if (code == RXGEN_OPCODE) {
+	oanswer.SeqLen = 0;
 	oanswer.MaxSeqLen = sizeof(answer);
 	oanswer.SeqBody = (char *)&answer;
 	version = 1;
@@ -553,6 +556,7 @@ ka_Authenticate(char *name, char *instance, char *cell, struct ubik_client * con
 	    ubik_KAA_Authenticate(conn, 0, name, instance, start, end,
 				  &arequest, &oanswer);
 	if (code == RXGEN_OPCODE) {
+	    oanswer.SeqLen = 0;
 	    oanswer.MaxSeqLen = sizeof(answer_old);
 	    oanswer.SeqBody = (char *)&answer_old;
 	    version = 0;
diff --git a/src/kauth/kaaux.c b/src/kauth/kaaux.c
index e6f013d7b..cc42d93a7 100644
--- a/src/kauth/kaaux.c
+++ b/src/kauth/kaaux.c
@@ -33,7 +33,17 @@ xdr_ka_CBS(XDR * x, struct ka_CBS *abbs)
 	xdr_afs_int32(x, &len);
 	if (len < 0 || len > MAXBS)
 	    return FALSE;
-	if (!abbs->SeqBody)
+	if (abbs->SeqBody != NULL) {
+	    if (len > abbs->SeqLen) {
+		/*
+		 * We've been given a preallocated buffer to decode into, but
+		 * we're decoding 'len' bytes, which is larger than the
+		 * provided buffer (only abbs->SeqLen bytes large). This won't
+		 * work.
+		 */
+		return FALSE;
+	    }
+	} else
 	    abbs->SeqBody = (char *)malloc(len);
 	abbs->SeqLen = len;
 	xdr_opaque(x, abbs->SeqBody, len);
@@ -60,7 +70,26 @@ xdr_ka_BBS(XDR * x, struct ka_BBS *abbs)
 	if (!xdr_afs_int32(x, &maxLen) || !xdr_afs_int32(x, &len) || (len < 0)
 	    || (len > MAXBS) || (len > maxLen))
 	    return FALSE;
-	if (!abbs->SeqBody)
+	if (abbs->SeqBody != NULL) {
+	    if (len > abbs->MaxSeqLen) {
+		/*
+		 * We've been given a preallocated buffer to decode into, but
+		 * we're decoding 'len' bytes, which is larger than the
+		 * provided buffer (only abbs->MaxSeqLen bytes large). This
+		 * won't work.
+		 */
+		return FALSE;
+	    }
+	    if (maxLen > abbs->MaxSeqLen) {
+		/*
+		 * Our preallocated buffer only has space for MaxSeqLen bytes.
+		 * Don't let the peer change 'abbs' so that it looks like we
+		 * have space for more bytes than that; that could cause us to
+		 * access memory beyond what we've actually allocated.
+		 */
+		return FALSE;
+	    }
+	} else
 	    abbs->SeqBody = (char *)malloc(maxLen);
 	abbs->MaxSeqLen = maxLen;
 	abbs->SeqLen = len;
diff --git a/src/kauth/kkids.c b/src/kauth/kkids.c
index f54dc5408..2ebc56b7b 100644
--- a/src/kauth/kkids.c
+++ b/src/kauth/kkids.c
@@ -198,7 +198,7 @@ find_me(char *arg, char *parent_dir)
     return 1;			/* found it */
 }
 
-#define SkipLine(str) { while (*str !='\n') str++; str++; }
+#define SkipLine(str) do { while (*str != '\0' && *str !='\n') str++; if (*str == '\n') str++; } while(0)
 
 /* this function returns TRUE (1) if the file is in AFS, otherwise false (0) */
 static int
@@ -236,8 +236,8 @@ struct AclEntry {
 static struct Acl *
 ParseAcl(char *astr)
 {
-    int nplus, nminus, i, trights;
-    char tname[MAXNAME];
+    int nplus = 0, nminus = 0, i, trights = 0;
+    char tname[MAXNAME + 1] = "";
     struct AclEntry *first, *last, *tl;
     struct Acl *ta;
     sscanf(astr, "%d", &nplus);
@@ -245,7 +245,7 @@ ParseAcl(char *astr)
     sscanf(astr, "%d", &nminus);
     SkipLine(astr);
 
-    ta = (struct Acl *)malloc(sizeof(struct Acl));
+    ta = calloc(sizeof(*ta), 1);
     ta->nplus = nplus;
 
     last = 0;
diff --git a/src/kauth/test/test_interim_ktc.c b/src/kauth/test/test_interim_ktc.c
index bd3f4cb4a..20463bf03 100644
--- a/src/kauth/test/test_interim_ktc.c
+++ b/src/kauth/test/test_interim_ktc.c
@@ -386,9 +386,10 @@ char *
 SkipLine(astr)
      char *astr;
 {
-    while (*astr != '\n')
+    while (*astr != '\0' && *astr != '\n')
+	astr++;
+    if (*astr == '\n')
 	astr++;
-    astr++;
     return astr;
 }
 
@@ -396,8 +397,8 @@ struct Acl *
 ParseAcl(astr)
      char *astr;
 {
-    int nplus, nminus, i, trights;
-    char tname[MAXNAME];
+    int nplus = 0, nminus = 0, i, trights = 0;
+    char tname[MAXNAME + 1] = "";
     struct AclEntry *first, *last, *tl;
     struct Acl *ta;
     sscanf(astr, "%d", &nplus);
@@ -405,7 +406,7 @@ ParseAcl(astr)
     sscanf(astr, "%d", &nminus);
     astr = SkipLine(astr);
 
-    ta = (struct Acl *)malloc(sizeof(struct Acl));
+    ta = calloc(sizeof(*ta), 1);
     ta->nplus = nplus;
     ta->nminus = nminus;
 
@@ -414,7 +415,7 @@ ParseAcl(astr)
     for (i = 0; i < nplus; i++) {
 	sscanf(astr, "%100s %d", tname, &trights);
 	astr = SkipLine(astr);
-	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	if (!first)
 	    first = tl;
 	strcpy(tl->name, tname);
@@ -431,7 +432,7 @@ ParseAcl(astr)
     for (i = 0; i < nminus; i++) {
 	sscanf(astr, "%100s %d", tname, &trights);
 	astr = SkipLine(astr);
-	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	if (!first)
 	    first = tl;
 	strcpy(tl->name, tname);
diff --git a/src/libacl/aclprocs.c b/src/libacl/aclprocs.c
index 72bf8aebc..2b5c38e9c 100644
--- a/src/libacl/aclprocs.c
+++ b/src/libacl/aclprocs.c
@@ -122,6 +122,10 @@ acl_FreeACL(struct acl_accessList **acl)
     /* Releases the access list defined by acl.  Returns 0 always. */
     struct freeListEntry *x;
 
+    if (*acl == NULL) {
+	return 0;
+    }
+
     x = (struct freeListEntry *)
 	((char *)*acl - sizeof(struct freeListEntry *) - sizeof(int));
     *acl = NULL;
@@ -270,10 +274,12 @@ acl_Internalize_pr(int (*func)(namelist *names, idlist *ids), char *elist, struc
     nextc = elist;
     while (*nextc && *nextc != '\n')
 	nextc++;
-    nextc++;
+    if (*nextc != '\0')
+	nextc++;
     while (*nextc && *nextc != '\n')
 	nextc++;
-    nextc++;			/* now at the beginning of the entry list */
+    if (*nextc != '\0')
+	nextc++;			/* now at the beginning of the entry list */
     for (i = 0; i < (*acl)->positive; i++) {
 	int k;
 	if (sscanf(nextc, "%63s\t%d\n", lnames.namelist_val[i], &k) != 2) {
@@ -282,6 +288,10 @@ acl_Internalize_pr(int (*func)(namelist *names, idlist *ids), char *elist, struc
 	}
 	(*acl)->entries[i].rights = k;
 	nextc = strchr(nextc, '\n');
+	if (nextc == NULL) {
+	    free(lnames.namelist_val);
+	    return (-1);
+	}
 	nextc++;		/* 1 + index can cast ptr to integer */
     }
     j = i;
@@ -294,6 +304,10 @@ acl_Internalize_pr(int (*func)(namelist *names, idlist *ids), char *elist, struc
 	    return (-1);
 	}
 	nextc = strchr(nextc, '\n');
+	if (nextc == NULL) {
+	    free(lnames.namelist_val);
+	    return (-1);
+	}
 	nextc++;
     }
     lids.idlist_len = 0;
diff --git a/src/libadmin/adminutil/afs_AdminUtilErrors.et b/src/libadmin/adminutil/afs_AdminUtilErrors.et
index e60c2e5ea..d03163811 100644
--- a/src/libadmin/adminutil/afs_AdminUtilErrors.et
+++ b/src/libadmin/adminutil/afs_AdminUtilErrors.et
@@ -22,4 +22,5 @@ error_table AU
     ec ADMRXDEBUGHANDLENULL, "the rxdebug handle parameter cannot be null"
     ec ADMRXDEBUGVERSIONNULL, "the rxdebug version parameter cannot be null"
     ec ADMRXDEBUGSTATSNULL, "the rxdebug stats parameter cannot be null"
+    ec ADMRPCTOOBIG, "the rpc output data exceeds buffer size."
 end
diff --git a/src/libadmin/adminutil/afs_utilAdmin.c b/src/libadmin/adminutil/afs_utilAdmin.c
index c4f2f5412..04a1dcac7 100644
--- a/src/libadmin/adminutil/afs_utilAdmin.c
+++ b/src/libadmin/adminutil/afs_utilAdmin.c
@@ -42,6 +42,58 @@
 #endif
 #include "afs_utilAdmin.h"
 
+/*
+ * The 'admin_strlcpy' function is copied from heimdal, under the following
+ * license:
+ *
+ * Copyright (c) 1995-2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+static size_t
+admin_strlcpy(char *dst, const char *src, size_t dst_sz)
+{
+    size_t n;
+
+    for (n = 0; n < dst_sz; n++) {
+	if ((*dst++ = *src++) == '\0')
+	    break;
+    }
+
+    if (n < dst_sz)
+	return n;
+    if (n > 0)
+	*(dst - 1) = '\0';
+    return n + strlen (src);
+}
+
 /*
  * AIX 4.2 has PTHREAD_CREATE_UNDETACHED and not PTHREAD_CREATE_JOINABLE
  *
@@ -2007,14 +2059,14 @@ ListCellsRPC(void *rpc_specific, int slot, int *last_item,
     int rc = 0;
     afs_status_t tst = 0;
     cm_list_cell_get_p t = (cm_list_cell_get_p) rpc_specific;
-    char *name;
+    char *name = NULL;
+    size_t len;
     serverList sl;
     unsigned int n;
 
     /*
      * Get the next entry in the CellServDB.
      */
-    name = t->cell[slot].cellname;
     sl.serverList_len = 0;
     sl.serverList_val = NULL;
     memset(t->cell[slot].serverAddr, 0, sizeof(afs_int32)*UTIL_MAX_CELL_HOSTS);
@@ -2023,7 +2075,11 @@ ListCellsRPC(void *rpc_specific, int slot, int *last_item,
     if (tst) {
 	goto fail_ListCellsRPC;
     }
-    strcpy(t->cell[slot].cellname, name);
+    len = admin_strlcpy(t->cell[slot].cellname, name, sizeof(t->cell[slot].cellname));
+    if (len >= sizeof(t->cell[slot].cellname)) {
+	tst = ADMRPCTOOBIG;
+	goto fail_ListCellsRPC;
+    }
     if (sl.serverList_val) {
         for (n=0; n<sl.serverList_len && n<UTIL_MAX_CELL_HOSTS; n++) {
             t->cell[slot].serverAddr[n] = sl.serverList_val[n];
@@ -2043,6 +2099,7 @@ ListCellsRPC(void *rpc_specific, int slot, int *last_item,
     rc = 1;
 
   fail_ListCellsRPC:
+    xdr_free((xdrproc_t) xdr_string, &name);
 
     if (st != NULL) {
 	*st = tst;
@@ -2240,7 +2297,8 @@ util_CMLocalCell(struct rx_connection *conn, afs_CMCellName_p cellName,
 {
     int rc = 0;
     afs_status_t tst = 0;
-    afs_CMCellName_p name;
+    char *name = NULL;
+    size_t len;
 
     if (conn == NULL) {
 	tst = ADMRXCONNNULL;
@@ -2252,15 +2310,21 @@ util_CMLocalCell(struct rx_connection *conn, afs_CMCellName_p cellName,
 	goto fail_util_CMLocalCell;
     }
 
-    name = cellName;
     tst = RXAFSCB_GetLocalCell(conn, &name);
+    if (tst != 0) {
+	goto fail_util_CMLocalCell;
+    }
 
-    if (!tst) {
-	rc = 1;
+    len = admin_strlcpy(cellName, name, sizeof(cellName));
+    if (len >= sizeof(cellName)) {
+	tst = ADMRPCTOOBIG;
+	goto fail_util_CMLocalCell;
     }
+    rc = 1;
 
   fail_util_CMLocalCell:
 
+    xdr_free((xdrproc_t)xdr_string, &name);
     if (st != NULL) {
 	*st = tst;
     }
@@ -2313,6 +2377,9 @@ util_CMClientConfig(struct rx_connection *conn, afs_ClientConfig_p config,
     afs_uint32 allocbytes;
     struct cacheConfig tconfig;
 
+    tconfig.cacheConfig_val = NULL;
+    tconfig.cacheConfig_len = 0;
+
     if (conn == NULL) {
 	tst = ADMRXCONNNULL;
 	goto fail_util_CMClientConfig;
@@ -2324,8 +2391,6 @@ util_CMClientConfig(struct rx_connection *conn, afs_ClientConfig_p config,
     }
 
     config->clientVersion = AFS_CLIENT_RETRIEVAL_VERSION;
-    tconfig.cacheConfig_val = NULL;
-    tconfig.cacheConfig_len = 0;
     tst =
 	RXAFSCB_GetCacheConfig(conn, config->clientVersion,
 			       &config->serverVersion, &allocbytes, &tconfig);
@@ -2334,12 +2399,17 @@ util_CMClientConfig(struct rx_connection *conn, afs_ClientConfig_p config,
 	goto fail_util_CMClientConfig;
     }
 
+    if (tconfig.cacheConfig_len != sizeof(cm_initparams_v1)/sizeof(afs_uint32)) {
+	tst = RXGEN_CC_UNMARSHAL;
+	goto fail_util_CMClientConfig;
+    }
+
     UnmarshallCMClientConfig(config->serverVersion, tconfig.cacheConfig_val,
 			     &config->c);
     rc = 1;
-    free(tconfig.cacheConfig_val);
 
   fail_util_CMClientConfig:
+    free(tconfig.cacheConfig_val);
 
     if (st != NULL) {
 	*st = tst;
diff --git a/src/libadmin/bos/afs_bosAdmin.c b/src/libadmin/bos/afs_bosAdmin.c
index df53cf166..de37b82b6 100644
--- a/src/libadmin/bos/afs_bosAdmin.c
+++ b/src/libadmin/bos/afs_bosAdmin.c
@@ -34,6 +34,58 @@
 #endif
 #include <string.h>
 
+/*
+ * The 'admin_strlcpy' function is copied from heimdal, under the following
+ * license:
+ *
+ * Copyright (c) 1995-2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+static size_t
+admin_strlcpy(char *dst, const char *src, size_t dst_sz)
+{
+    size_t n;
+
+    for (n = 0; n < dst_sz; n++) {
+	if ((*dst++ = *src++) == '\0')
+	    break;
+    }
+
+    if (n < dst_sz)
+	return n;
+    if (n > 0)
+	*(dst - 1) = '\0';
+    return n + strlen (src);
+}
+
 typedef struct bos_server {
     int begin_magic;
     int is_valid;
@@ -535,6 +587,8 @@ bos_ProcessExecutionStateGet(const void *serverHandle,
     afs_status_t tst = 0;
     bos_server_p b_handle = (bos_server_p) serverHandle;
     afs_int32 state;
+    char *desc = NULL;
+    size_t len;
 
     if (!isValidServerHandle(b_handle, &tst)) {
 	goto fail_bos_ProcessExecutionStateGet;
@@ -556,18 +610,24 @@ bos_ProcessExecutionStateGet(const void *serverHandle,
     }
 
     tst =
-	BOZO_GetStatus(b_handle->server, processName, &state,
-		       &auxiliaryProcessStatus);
-
+	BOZO_GetStatus(b_handle->server, processName, &state, &desc);
     if (tst != 0) {
 	goto fail_bos_ProcessExecutionStateGet;
     }
 
+    /* This function assumes the caller provides a BOS_MAX_NAME_LEN sized buffer. */
+    len = admin_strlcpy(auxiliaryProcessStatus, desc, BOS_MAX_NAME_LEN);
+    if (len >= BOS_MAX_NAME_LEN) {
+	tst = ADMRPCTOOBIG;
+	goto fail_bos_ProcessExecutionStateGet;
+    }
     *processStatusP = (bos_ProcessExecutionState_t) state;
+
     rc = 1;
 
   fail_bos_ProcessExecutionStateGet:
 
+    xdr_free((xdrproc_t)xdr_string, &desc);
     if (st != NULL) {
 	*st = tst;
     }
@@ -716,11 +776,17 @@ GetProcessNameRPC(void *rpc_specific, int slot, int *last_item,
     int rc = 0;
     afs_status_t tst = 0;
     process_name_get_p proc = (process_name_get_p) rpc_specific;
-    char *ptr = (char *)&proc->process[slot];
+    char *name = NULL;
+    size_t len;
 
-    tst = BOZO_EnumerateInstance(proc->server, proc->next++, &ptr);
+    tst = BOZO_EnumerateInstance(proc->server, proc->next++, &name);
 
     if (tst == 0) {
+	len = admin_strlcpy(proc->process[slot], name, sizeof(proc->process[slot]));
+	if (len >= sizeof(proc->process[slot])) {
+	    tst = ADMRPCTOOBIG;
+	    goto fail_GetProcessNameRPC;
+	}
 	rc = 1;
     } else if (tst == BZDOM) {
 	tst = 0;
@@ -729,6 +795,9 @@ GetProcessNameRPC(void *rpc_specific, int slot, int *last_item,
 	*last_item_contains_data = 0;
     }
 
+  fail_GetProcessNameRPC:
+
+    xdr_free((xdrproc_t)xdr_string, &name);
     if (st != NULL) {
 	*st = tst;
     }
@@ -946,8 +1015,7 @@ bos_ProcessInfoGet(const void *serverHandle, char *processName,
     int rc = 0;
     afs_status_t tst = 0;
     bos_server_p b_handle = (bos_server_p) serverHandle;
-    char type[BOS_MAX_NAME_LEN];
-    char *ptr = type;
+    char *type = NULL;
     struct bozo_status status;
     int i;
 
@@ -970,13 +1038,12 @@ bos_ProcessInfoGet(const void *serverHandle, char *processName,
 	goto fail_bos_ProcessInfoGet;
     }
 
-    tst = BOZO_GetInstanceInfo(b_handle->server, processName, &ptr, &status);
+    tst = BOZO_GetInstanceInfo(b_handle->server, processName, &type, &status);
 
     if (tst != 0) {
 	goto fail_bos_ProcessInfoGet;
     }
 
-
     for (i = 0; (processTypes[i] != NULL); i++) {
 	if (!strcmp(processTypes[i], type)) {
 	    *processTypeP = (bos_ProcessType_t) i;
@@ -1011,6 +1078,7 @@ bos_ProcessInfoGet(const void *serverHandle, char *processName,
 
   fail_bos_ProcessInfoGet:
 
+    xdr_free((xdrproc_t)xdr_string, &type);
     if (st != NULL) {
 	*st = tst;
     }
@@ -1035,13 +1103,19 @@ GetParameterRPC(void *rpc_specific, int slot, int *last_item,
     int rc = 0;
     afs_status_t tst = 0;
     param_get_p param = (param_get_p) rpc_specific;
-    char *ptr = (char *)&param->param[slot];
+    char *parm = NULL;
+    size_t len;
 
     tst =
 	BOZO_GetInstanceParm(param->server, param->processName, param->next++,
-			     &ptr);
+			     &parm);
 
     if (tst == 0) {
+	len = admin_strlcpy(param->param[slot], parm, sizeof(param->param[slot]));
+	if (len >= sizeof(param->param[slot])) {
+	    tst = ADMRPCTOOBIG;
+	    goto fail_GetParameterRPC;
+	}
 	rc = 1;
     } else if (tst == BZDOM) {
 	tst = 0;
@@ -1050,6 +1124,9 @@ GetParameterRPC(void *rpc_specific, int slot, int *last_item,
 	*last_item_contains_data = 0;
     }
 
+  fail_GetParameterRPC:
+
+    xdr_free((xdrproc_t)xdr_string, &parm);
     if (st != NULL) {
 	*st = tst;
     }
@@ -1276,6 +1353,8 @@ bos_ProcessNotifierGet(const void *serverHandle, const char *processName,
     int rc = 0;
     afs_status_t tst = 0;
     bos_server_p b_handle = (bos_server_p) serverHandle;
+    char *tnotif = NULL;
+    size_t len;
 
     if (!isValidServerHandle(b_handle, &tst)) {
 	goto fail_bos_ProcessNotifierGet;
@@ -1292,14 +1371,22 @@ bos_ProcessNotifierGet(const void *serverHandle, const char *processName,
     }
 
     tst = BOZO_GetInstanceParm(b_handle->server, (char *)processName,
-			       999, &notifier);
+			       999, &tnotif);
+    if (tst != 0) {
+	goto fail_bos_ProcessNotifierGet;
+    }
 
-    if (tst == 0) {
-	rc = 1;
+    len = admin_strlcpy(notifier, tnotif, BOS_MAX_NAME_LEN);
+    if (len >= BOS_MAX_NAME_LEN) {
+	tst = ADMRPCTOOBIG;
+	goto fail_bos_ProcessNotifierGet;
     }
 
+    rc = 1;
+
   fail_bos_ProcessNotifierGet:
 
+    xdr_free((xdrproc_t)xdr_string, &tnotif);
     if (st != NULL) {
 	*st = tst;
     }
@@ -1703,23 +1790,32 @@ GetAdminRPC(void *rpc_specific, int slot, int *last_item,
     int rc = 0;
     afs_status_t tst = 0;
     admin_get_p admin = (admin_get_p) rpc_specific;
-    char *ptr = (char *)&admin->admin[slot];
+    char *name = NULL;
+    size_t len;
 
-    tst = BOZO_ListSUsers(admin->server, admin->next++, &ptr);
+    tst = BOZO_ListSUsers(admin->server, admin->next++, &name);
 
     /*
      * There's no way to tell the difference between an rpc failure
      * and the end of the list, so we assume that any error means the
      * end of the list
      */
-
-    if (tst != 0) {
+    if (tst == 0) {
+	len = admin_strlcpy(admin->admin[slot], name, sizeof(admin->admin[slot]));
+	if (len >= sizeof(admin->admin[slot])) {
+	    tst = ADMRPCTOOBIG;
+	    goto fail_GetAdminRPC;
+	}
+    } else {
 	tst = 0;
 	*last_item = 1;
 	*last_item_contains_data = 0;
     }
     rc = 1;
 
+  fail_GetAdminRPC:
+
+    xdr_free((xdrproc_t)xdr_string, &name);
     if (st != NULL) {
 	*st = tst;
     }
@@ -2291,6 +2387,8 @@ bos_CellGet(const void *serverHandle, char *cellName, afs_status_p st)
     int rc = 0;
     afs_status_t tst = 0;
     bos_server_p b_handle = (bos_server_p) serverHandle;
+    char *tcellname = NULL;
+    size_t len;
 
     if (!isValidServerHandle(b_handle, &tst)) {
 	goto fail_bos_CellGet;
@@ -2301,14 +2399,23 @@ bos_CellGet(const void *serverHandle, char *cellName, afs_status_p st)
 	goto fail_bos_CellGet;
     }
 
-    tst = BOZO_GetCellName(b_handle->server, &cellName);
+    tst = BOZO_GetCellName(b_handle->server, &tcellname);
+    if (tst != 0) {
+	goto fail_bos_CellGet;
+    }
 
-    if (tst == 0) {
-	rc = 1;
+    /* This function assumes the caller provides a BOS_MAX_NAME_LEN sized buffer. */
+    len = admin_strlcpy(cellName, tcellname, BOS_MAX_NAME_LEN);
+    if (len >= BOS_MAX_NAME_LEN) {
+	tst = ADMRPCTOOBIG;
+	goto fail_bos_CellGet;
     }
 
+    rc = 1;
+
   fail_bos_CellGet:
 
+    xdr_free((xdrproc_t)xdr_string, &tcellname);
     if (st != NULL) {
 	*st = tst;
     }
@@ -2430,11 +2537,17 @@ GetHostRPC(void *rpc_specific, int slot, int *last_item,
     int rc = 0;
     afs_status_t tst = 0;
     host_get_p host = (host_get_p) rpc_specific;
-    char *ptr = (char *)&host->host[slot];
+    char *name = NULL;
+    size_t len;
 
-    tst = BOZO_GetCellHost(host->server, host->next++, &ptr);
+    tst = BOZO_GetCellHost(host->server, host->next++, &name);
 
     if (tst == 0) {
+	len = admin_strlcpy(host->host[slot], name, sizeof(host->host[slot]));
+	if (len >= sizeof(host->host[slot])) {
+	    tst = ADMRPCTOOBIG;
+	    goto fail_GetHostRPC;
+	}
 	rc = 1;
     } else if (tst == BZDOM) {
 	tst = 0;
@@ -2443,6 +2556,9 @@ GetHostRPC(void *rpc_specific, int slot, int *last_item,
 	*last_item_contains_data = 0;
     }
 
+  fail_GetHostRPC:
+
+    xdr_free((xdrproc_t)xdr_string, &name);
     if (st != NULL) {
 	*st = tst;
     }
diff --git a/src/libadmin/client/afs_clientAdmin.c b/src/libadmin/client/afs_clientAdmin.c
index 35dbd6c90..cad0dca45 100644
--- a/src/libadmin/client/afs_clientAdmin.c
+++ b/src/libadmin/client/afs_clientAdmin.c
@@ -1445,6 +1445,9 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
     char tmp[64 + 35];
     int is_dfs;
 
+    memset(&cur_acl, 0, sizeof(cur_acl));
+    memset(cur_user, 0, sizeof(cur_user));
+
     if (client_init == 0) {
 	tst = ADMCLIENTNOINIT;
 	goto fail_afsclient_ACLEntryAdd;
@@ -1545,9 +1548,13 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
 	sscanf(old_acl_string, "%d dfs:%d %1024s", &cur_acl.nplus, &cur_acl.dfs,
 	       cur_acl.cell);
     ptr = strchr(old_acl_string, '\n');
+    if (ptr == NULL)
+	goto fail_afsclient_ACLEntryAdd;
     ptr++;
     sscanf(ptr, "%d", &cur_acl.nminus);
     ptr = strchr(ptr, '\n');
+    if (ptr == NULL)
+	goto fail_afsclient_ACLEntryAdd;
     ptr++;
     if (is_dfs == 3) {
 	tst = ADMMISCNODFSACL;
@@ -1574,6 +1581,8 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
 
 	if (strcmp(cur_user, user)) {
 	    ptr = strchr(ptr, '\n');
+	    if (ptr == NULL)
+		goto fail_afsclient_ACLEntryAdd;
 	    ptr++;
 	    sprintf(tmp, "%s %d\n", cur_user, cur_user_acl);
 	    strcat(new_acl_string, tmp);
diff --git a/src/libadmin/pts/afs_ptsAdmin.c b/src/libadmin/pts/afs_ptsAdmin.c
index 05bf37607..a25476d3d 100644
--- a/src/libadmin/pts/afs_ptsAdmin.c
+++ b/src/libadmin/pts/afs_ptsAdmin.c
@@ -122,6 +122,10 @@ TranslatePTSNames(const afs_cell_handle_p cellHandle, namelist * names,
 	goto fail_TranslatePTSNames;
     }
 
+    if (ids->idlist_len != names->namelist_len) {
+	tst = ADMPTSFAILEDNAMETRANSLATE;
+	goto fail_TranslatePTSNames;
+    }
 
     /*
      * Check to see if the lookup failed
diff --git a/src/libadmin/vos/afs_vosAdmin.c b/src/libadmin/vos/afs_vosAdmin.c
index 557feb90e..1b1987508 100644
--- a/src/libadmin/vos/afs_vosAdmin.c
+++ b/src/libadmin/vos/afs_vosAdmin.c
@@ -1228,6 +1228,10 @@ GetServerRPC(void *rpc_specific, int slot, int *last_item,
 		goto fail_GetServerRPC;
 	    }
 
+	    if (addr_multi.bulkaddrs_len < total_multi) {
+		total_multi = addr_multi.bulkaddrs_len;
+	    }
+
 	    /*
 	     * Remove any bogus IP addresses which the user may have
 	     * been unable to remove.
@@ -1380,6 +1384,10 @@ vos_FileServerGetBegin(const void *cellHandle, vos_MessageCallBack_t callBack,
 	goto fail_vos_FileServerGetBegin;
     }
 
+    if (serv->addresses.bulkaddrs_len < serv->total_addresses) {
+	serv->total_addresses = serv->addresses.bulkaddrs_len;
+    }
+
     /*
      * Remove any bogus IP addresses which the user may have
      * been unable to remove.
diff --git a/src/libadmin/vos/vosutils.c b/src/libadmin/vos/vosutils.c
index 4ac47bfe3..2c49cf04e 100644
--- a/src/libadmin/vos/vosutils.c
+++ b/src/libadmin/vos/vosutils.c
@@ -320,6 +320,9 @@ VLDB_ListAttributesN2(afs_cell_handle_p cellHandle,
 		  nextindexp);
     if (!tst) {
 	rc = 1;
+	if (blkentriesp->nbulkentries_len < *nentriesp) {
+	    *nentriesp = blkentriesp->nbulkentries_len;
+	}
     }
 
     if (st != NULL) {
@@ -361,6 +364,9 @@ VLDB_IsSameAddrs(afs_cell_handle_p cellHandle, afs_int32 serv1,
 	*equal = 0;
 	goto fail_VLDB_IsSameAddrs;
     }
+    if (addrs.bulkaddrs_len < nentries) {
+	nentries = addrs.bulkaddrs_len;
+    }
 
     addrp = addrs.bulkaddrs_val;
     for (i = 0; i < nentries; i++, addrp++) {
diff --git a/src/libadmin/vos/vsprocs.c b/src/libadmin/vos/vsprocs.c
index 2fb11deb0..c9f60f3dc 100644
--- a/src/libadmin/vos/vsprocs.c
+++ b/src/libadmin/vos/vsprocs.c
@@ -605,7 +605,7 @@ UV_MoveVolume(afs_cell_handle_p cellHandle, afs_uint32 afromvol,
      */
     volumeInfo.volEntries_val = (volintInfo *) 0;	/*this hints the stub to allocate space */
     volumeInfo.volEntries_len = 0;
-    tst = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
+    tst = ListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
     if (tst) {
 	goto fail_UV_MoveVolume;
     }
@@ -1167,6 +1167,18 @@ UV_BackupVolume(afs_cell_handle_p cellHandle, afs_int32 aserver,
     return rc;
 }
 
+static int
+ListOneVolume(struct rx_connection *aconn, afs_int32 apart, afs_uint32 avolid,
+	      volEntries *entries)
+{
+    afs_int32 code;
+    code = AFSVolListOneVolume(aconn, apart, avolid, entries);
+    if (code == 0 && entries->volEntries_len != 1) {
+	code = VOLSERFAILEDOP;
+    }
+    return code;
+}
+
 static int
 DelVol(struct rx_connection *conn, afs_uint32 vid, afs_int32 part,
        afs_int32 flags)
@@ -1422,7 +1434,7 @@ VolumeExists(afs_cell_handle_p cellHandle, afs_int32 server,
     if (conn) {
 	volumeInfo.volEntries_val = (volintInfo *) 0;
 	volumeInfo.volEntries_len = 0;
-	tst = AFSVolListOneVolume(conn, partition, volumeid, &volumeInfo);
+	tst = ListOneVolume(conn, partition, volumeid, &volumeInfo);
 	if (volumeInfo.volEntries_val)
 	    free(volumeInfo.volEntries_val);
 	if (tst == VOLSERILLEGAL_PARTITION) {
@@ -2893,7 +2905,9 @@ UV_XListOneVolume(struct rx_connection *server, afs_int32 a_partID,
     volumeXInfo.volXEntries_len = 0;
 
     tst = AFSVolXListOneVolume(server, a_partID, a_volID, &volumeXInfo);
-
+    if (tst == 0 && volumeXInfo.volXEntries_len != 1) {
+	tst = VOLSERFAILEDOP;
+    }
     if (tst) {
 	goto fail_UV_XListOneVolume;
     } else {
@@ -2953,7 +2967,7 @@ int UV_ListOneVolume(struct rx_connection *server, afs_int32 a_partID,
     volumeInfo.volEntries_val = (volintInfo *) 0;
     volumeInfo.volEntries_len = 0;
 
-    tst = AFSVolListOneVolume(server, a_partID, a_volID, &volumeInfo);
+    tst = ListOneVolume(server, a_partID, a_volID, &volumeInfo);
 
     if (tst) {
 	goto fail_UV_ListOneVolume;
diff --git a/src/libafscp/afscp_acl.c b/src/libafscp/afscp_acl.c
index 09b7df000..1bbacd0f9 100644
--- a/src/libafscp/afscp_acl.c
+++ b/src/libafscp/afscp_acl.c
@@ -56,6 +56,16 @@ afscp_FetchACL(const struct afscp_venusfid *dir, struct AFSOpaque *acl)
 		code = RXAFS_FetchACL(server->conns[j], &df, acl, &dfst, &vs);
 		if (code >= 0)
 		    break;
+		/* Zero-length or non-string ACLs are malformed. */
+		if (acl->AFSOpaque_len == 0 || memchr(acl->AFSOpaque_val, '\0',
+						      acl->AFSOpaque_len) == NULL) {
+		    code = EIO;
+		    break;
+		}
+		if (strlen(acl->AFSOpaque_val) + 1 != acl->AFSOpaque_len) {
+		    code = EIO;
+		    break;
+		}
 	    }
 	}
 	if (code >= 0)
diff --git a/src/libafscp/afscp_server.c b/src/libafscp/afscp_server.c
index e67ee48a9..5fdbe4445 100644
--- a/src/libafscp/afscp_server.c
+++ b/src/libafscp/afscp_server.c
@@ -304,6 +304,9 @@ afscp_ServerById(struct afscp_cell *thecell, afsUUID * u)
     if (code != 0) {
 	return NULL;
     }
+    if (addrs.bulkaddrs_len < nentries) {
+	nentries = addrs.bulkaddrs_len;
+    }
     if (nentries > AFS_MAXHOSTS) {
 	nentries = AFS_MAXHOSTS;
 	/* XXX I don't want to do *that* much dynamic allocation */
@@ -404,6 +407,10 @@ afscp_ServerByAddr(struct afscp_cell *thecell, afs_uint32 addr)
 	afsUUID_to_string(&uuid, s, 511);
 	afs_dprintf(("GetServerByAddr 0x%x -> uuid %s\n", addr, s));
 
+	if (addrs.bulkaddrs_len < nentries) {
+	    nentries = addrs.bulkaddrs_len;
+	}
+
 	if (nentries > AFS_MAXHOSTS) {
 	    nentries = AFS_MAXHOSTS;
 	    /* XXX I don't want to do *that* much dynamic allocation */
diff --git a/src/ptserver/pts.c b/src/ptserver/pts.c
index 0035f5bac..93556b07c 100644
--- a/src/ptserver/pts.c
+++ b/src/ptserver/pts.c
@@ -734,6 +734,7 @@ CheckEntry(struct cmd_syndesc *as, void *arock)
 
 	lids.idlist_val[0] = aentry.owner;
 	lids.idlist_val[1] = aentry.creator;
+	xdr_free((xdrproc_t) xdr_namelist, &lnames);
 	code = pr_IdToName(&lids, &lnames);
 	if (code) {
 	    rcode = code;
diff --git a/src/ptserver/ptuser.c b/src/ptserver/ptuser.c
index 501fada05..7838e9804 100644
--- a/src/ptserver/ptuser.c
+++ b/src/ptserver/ptuser.c
@@ -496,6 +496,9 @@ pr_NameToId(namelist *names, idlist *ids)
     for (i = 0; i < names->namelist_len; i++)
 	stolower(names->namelist_val[i]);
     code = ubik_PR_NameToID(pruclient, 0, names, ids);
+    if (code == 0 && ids->idlist_len != names->namelist_len) {
+	code = 267281L; /* PRINTERNAL */
+    }
     return code;
 }
 
diff --git a/src/ptserver/testpt.c b/src/ptserver/testpt.c
index d0a1c9392..d41db77cf 100644
--- a/src/ptserver/testpt.c
+++ b/src/ptserver/testpt.c
@@ -126,6 +126,7 @@ ListUsedIds(struct cmd_syndesc *as, void *arock)
 		startId++;
 	}
 	lids.idlist_len = i;
+	xdr_free((xdrproc_t) xdr_namelist, &lnames);
 	code = pr_IdToName(&lids, &lnames);
 	if (code) {
 	    afs_com_err(whoami, code, "converting id to name");
diff --git a/src/rx/xdr.c b/src/rx/xdr.c
index bd224a163..386abd2ab 100644
--- a/src/rx/xdr.c
+++ b/src/rx/xdr.c
@@ -410,10 +410,28 @@ xdr_bytes(XDR * xdrs, char **cpp, u_int * sizep,
     /*
      * first deal with the length since xdr bytes are counted
      */
-    if (!xdr_u_int(xdrs, sizep)) {
-	return (FALSE);
+
+    if (xdrs->x_op == XDR_DECODE && sp != NULL) {
+	/*
+	 * We've been given a preallocated array to decode into. Before we
+	 * modify *sizep, check that we have enough space to fit the elements
+	 * that follow.
+	 */
+	if (!xdr_u_int(xdrs, &nodesize)) {
+	   return FALSE;
+	}
+	if (nodesize > *sizep) {
+	   return FALSE;
+	}
+	*sizep = nodesize;
+
+    } else {
+	if (!xdr_u_int(xdrs, sizep)) {
+	    return (FALSE);
+	}
+	nodesize = *sizep;
     }
-    nodesize = *sizep;
+
     if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
 	return (FALSE);
     }
@@ -537,7 +555,7 @@ xdr_string(XDR * xdrs, char **cpp, u_int maxsize)
     if (!xdr_u_int(xdrs, &size)) {
 	return (FALSE);
     }
-    if (size > maxsize) {
+    if (xdrs->x_op != XDR_FREE && size > maxsize) {
 	return (FALSE);
     }
     nodesize = size + 1;
@@ -548,13 +566,40 @@ xdr_string(XDR * xdrs, char **cpp, u_int maxsize)
     switch (xdrs->x_op) {
 
     case XDR_DECODE:
-	if (sp == NULL)
-	    *cpp = sp = (char *)osi_alloc(nodesize);
+	if (sp != NULL) {
+	    /*
+	     * Refuse to use preallocated strings, since we cannot verify
+	     * whether enough memory has been allocated to handle the decoded
+	     * string.
+	     */
+	    return FALSE;
+	}
+
+	*cpp = sp = (char *)osi_alloc(nodesize);
 	if (sp == NULL) {
 	    return (FALSE);
 	}
 	sp[size] = 0;
-	/* fall into ... */
+
+	/* Get the actual string. */
+	if (!xdr_opaque(xdrs, sp, size)) {
+	    /* Make sure strlen(sp) == size, so we can calculate the correct
+	     * size for osi_free when freeing the string. */
+	    memset(sp, 'z', size);
+	    return FALSE;
+	}
+
+	/*
+	 * If the string contains a '\0' character, the string is invalid.
+	 * Don't allow this, because this makes it impossible for us to pass
+	 * the correct size to osi_free later on, when freeing the string.
+	 */
+	if (strlen(sp) != size) {
+	    /* Make sure strlen(sp) == size. */
+	    memset(sp, 'z', size);
+	    return FALSE;
+	}
+	return TRUE;
 
     case XDR_ENCODE:
 	return (xdr_opaque(xdrs, sp, size));
diff --git a/src/rx/xdr_array.c b/src/rx/xdr_array.c
index 886d2c6e4..8672d7e61 100644
--- a/src/rx/xdr_array.c
+++ b/src/rx/xdr_array.c
@@ -96,10 +96,28 @@ xdr_array(XDR * xdrs, caddr_t * addrp, u_int * sizep, u_int maxsize,
 	maxsize = i;
 
     /* like strings, arrays are really counted arrays */
-    if (!xdr_u_int(xdrs, sizep)) {
-	return (FALSE);
+
+    if (xdrs->x_op == XDR_DECODE && target != NULL) {
+	/*
+	 * We've been given a preallocated array to decode into. Before we
+	 * modify *sizep, check that we have enough space to fit the elements
+	 * that follow.
+	 */
+	if (!xdr_u_int(xdrs, &c)) {
+	    return FALSE;
+	}
+	if (c > *sizep) {
+	    return FALSE;
+	}
+	*sizep = c;
+
+    } else {
+	if (!xdr_u_int(xdrs, sizep)) {
+	    return (FALSE);
+	}
+	c = *sizep;
     }
-    c = *sizep;
+
     if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
 	return (FALSE);
     }
diff --git a/src/rx/xdr_arrayn.c b/src/rx/xdr_arrayn.c
index 5b6659887..504075beb 100644
--- a/src/rx/xdr_arrayn.c
+++ b/src/rx/xdr_arrayn.c
@@ -97,10 +97,28 @@ xdr_arrayN(XDR * xdrs, caddr_t * addrp, u_int * sizep, u_int maxsize,
 	maxsize = i;
 
     /* like strings, arrays are really counted arrays */
-    if (!xdr_u_int(xdrs, sizep)) {
-	return (FALSE);
+
+    if (xdrs->x_op == XDR_DECODE && target != NULL) {
+	/*
+	 * We've been given a preallocated array to decode into. Before we
+	 * modify *sizep, check that we have enough space to fit the elements
+	 * that follow.
+	 */
+	if (!xdr_u_int(xdrs, &c)) {
+	    return FALSE;
+	}
+	if (c > *sizep) {
+	    return FALSE;
+	}
+	*sizep = c;
+
+    } else {
+	if (!xdr_u_int(xdrs, sizep)) {
+	    return (FALSE);
+	}
+	c = *sizep;
     }
-    c = *sizep;
+
     if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
 	return (FALSE);
     }
diff --git a/src/sys/rmtsysc.c b/src/sys/rmtsysc.c
index 490626111..69bae83ef 100644
--- a/src/sys/rmtsysc.c
+++ b/src/sys/rmtsysc.c
@@ -245,7 +245,7 @@ pioctl(char *path, afs_int32 cmd, struct ViceIoctl *data, afs_int32 follow)
     inparam_conversion(cmd, InData.rmtbulk_val, 0);
 
     OutData.rmtbulk_len = MAXBUFFERLEN * sizeof(*OutData.rmtbulk_val);
-    OutData.rmtbulk_val = malloc(OutData.rmtbulk_len);
+    OutData.rmtbulk_val = calloc(1, OutData.rmtbulk_len);
     if (!OutData.rmtbulk_val) {
 	free(inbuffer);
 	return -1;
@@ -291,7 +291,7 @@ pioctl(char *path, afs_int32 cmd, struct ViceIoctl *data, afs_int32 follow)
 	    errno = EINVAL;
 	    errorcode = -1;
 	} else {
-	    memcpy(data->out, OutData.rmtbulk_val, data->out_size);
+	    memcpy(data->out, OutData.rmtbulk_val, OutData.rmtbulk_len);
 	    outparam_conversion(cmd, data->out, 1);
 	}
     }
diff --git a/src/sys/rmtsysnet.c b/src/sys/rmtsysnet.c
index df350d21b..ce1c9f337 100644
--- a/src/sys/rmtsysnet.c
+++ b/src/sys/rmtsysnet.c
@@ -64,9 +64,10 @@ struct ClearToken {
 char *
 RSkipLine(char *astr)
 {
-    while (*astr != '\n')
+    while (*astr != '\0' && *astr != '\n')
+	astr++;
+    if (*astr == '\n')
 	astr++;
-    astr++;
     return astr;
 }
 
@@ -74,8 +75,8 @@ RSkipLine(char *astr)
 struct Acl *
 RParseAcl(char *astr)
 {
-    int nplus, nminus, i, trights;
-    char tname[MAXNAME];
+    int nplus = 0, nminus = 0, i, trights = 0;
+    char tname[MAXNAME + 1] = "";
     struct AclEntry *first, *last, *tl;
     struct Acl *ta;
     sscanf(astr, "%d", &nplus);
@@ -83,7 +84,7 @@ RParseAcl(char *astr)
     sscanf(astr, "%d", &nminus);
     astr = RSkipLine(astr);
 
-    ta = (struct Acl *)malloc(sizeof(struct Acl));
+    ta = calloc(sizeof(*ta), 1);
     ta->nplus = nplus;
     ta->nminus = nminus;
 
@@ -92,7 +93,7 @@ RParseAcl(char *astr)
     for (i = 0; i < nplus; i++) {
 	sscanf(astr, "%100s %d", tname, &trights);
 	astr = RSkipLine(astr);
-	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	if (!first)
 	    first = tl;
 	strcpy(tl->name, tname);
@@ -109,7 +110,7 @@ RParseAcl(char *astr)
     for (i = 0; i < nminus; i++) {
 	sscanf(astr, "%100s %d", tname, &trights);
 	astr = RSkipLine(astr);
-	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	if (!first)
 	    first = tl;
 	strcpy(tl->name, tname);
diff --git a/src/uss/uss_acl.c b/src/uss/uss_acl.c
index 30a696eaa..3690208ec 100644
--- a/src/uss/uss_acl.c
+++ b/src/uss/uss_acl.c
@@ -343,9 +343,10 @@ static char *
 SkipLine(char *a_str)
 {				/*SkipLine */
 
-    while (*a_str != '\n')
+    while (*a_str != '\0' && *a_str != '\n')
+	a_str++;
+    if (*a_str == '\n')
 	a_str++;
-    a_str++;
     return (a_str);
 
 }				/*SkipLine */
@@ -408,8 +409,8 @@ static struct Acl *
 ParseAcl(char *a_str)
 {				/*ParseAcl */
 
-    int nplus, nminus, i, trights;
-    char tname[MAXNAME];
+    int nplus = 0, nminus = 0, i, trights = 0;
+    char tname[MAXNAME + 1] = "";
     struct AclEntry *first, *last, *tl;
     struct Acl *ta;
 
@@ -425,7 +426,7 @@ ParseAcl(char *a_str)
     /*
      * Allocate and initialize the first entry.
      */
-    ta = (struct Acl *)malloc(sizeof(struct Acl));
+    ta = calloc(sizeof(*ta), 1);
     ta->nplus = nplus;
     ta->nminus = nminus;
 
@@ -437,7 +438,7 @@ ParseAcl(char *a_str)
     for (i = 0; i < nplus; i++) {
 	sscanf(a_str, "%100s %d", tname, &trights);
 	a_str = SkipLine(a_str);
-	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	if (!first)
 	    first = tl;
 	strcpy(tl->name, tname);
@@ -457,7 +458,7 @@ ParseAcl(char *a_str)
     for (i = 0; i < nminus; i++) {
 	sscanf(a_str, "%100s %d", tname, &trights);
 	a_str = SkipLine(a_str);
-	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	if (!first)
 	    first = tl;
 	strcpy(tl->name, tname);
diff --git a/src/venus/cacheout.c b/src/venus/cacheout.c
index 3d44fd9fc..03f6e297e 100644
--- a/src/venus/cacheout.c
+++ b/src/venus/cacheout.c
@@ -82,6 +82,10 @@ ListServers(void)
 	return 1;
     }
 
+    if (addrs.bulkaddrs_len < server_count) {
+	server_count = addrs.bulkaddrs_len;
+    }
+
     for (i = 0; i < server_count; ++i) {
 	ip = addrs.bulkaddrs_val[i];
 
diff --git a/src/venus/fs.c b/src/venus/fs.c
index 9bdd1fba1..1e7acaac8 100644
--- a/src/venus/fs.c
+++ b/src/venus/fs.c
@@ -537,9 +537,10 @@ PruneList(struct AclEntry **ae, int dfs)
 static char *
 SkipLine(char *astr)
 {
-    while (*astr != '\n')
+    while (*astr != '\0' && *astr != '\n')
+	astr++;
+    if (*astr == '\n')
 	astr++;
-    astr++;
     return astr;
 }
 
@@ -556,7 +557,7 @@ EmptyAcl(char *astr)
     struct Acl *tp;
     int junk;
 
-    tp = (struct Acl *)malloc(sizeof(struct Acl));
+    tp = calloc(sizeof(*tp), 1);
     assert(tp);
     tp->nplus = tp->nminus = 0;
     tp->pluslist = tp->minuslist = 0;
@@ -568,12 +569,12 @@ EmptyAcl(char *astr)
 static struct Acl *
 ParseAcl(char *astr)
 {
-    int nplus, nminus, i, trights;
-    char tname[MAXNAME];
+    int nplus = 0, nminus = 0, i, trights = 0;
+    char tname[MAXNAME + 1] = "";
     struct AclEntry *first, *last, *tl;
     struct Acl *ta;
 
-    ta = (struct Acl *)malloc(sizeof(struct Acl));
+    ta = calloc(sizeof(*ta), 1);
     assert(ta);
     ta->dfs = 0;
     sscanf(astr, "%d dfs:%d %1024s", &ta->nplus, &ta->dfs, ta->cell);
@@ -589,7 +590,7 @@ ParseAcl(char *astr)
     for (i = 0; i < nplus; i++) {
 	sscanf(astr, "%99s %d", tname, &trights);
 	astr = SkipLine(astr);
-	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	assert(tl);
 	if (!first)
 	    first = tl;
@@ -607,7 +608,7 @@ ParseAcl(char *astr)
     for (i = 0; i < nminus; i++) {
 	sscanf(astr, "%99s %d", tname, &trights);
 	astr = SkipLine(astr);
-	tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	assert(tl);
 	if (!first)
 	    first = tl;
diff --git a/src/viced/afsfileprocs.c b/src/viced/afsfileprocs.c
index e145d67be..2634e5fc3 100644
--- a/src/viced/afsfileprocs.c
+++ b/src/viced/afsfileprocs.c
@@ -1275,18 +1275,26 @@ RXFetch_AccessList(Vnode * targetptr, Vnode * parentwhentargetnotdir,
  * the target dir's vnode storage.
  */
 static afs_int32
-RXStore_AccessList(Vnode * targetptr, struct AFSOpaque *AccessList)
+RXStore_AccessList(Vnode * targetptr, char *AccessList)
 {
-    struct acl_accessList *newACL;	/* PlaceHolder for new access list */
+    int code;
+    struct acl_accessList *newACL = NULL;
 
-    if (acl_Internalize_pr(hpr_NameToId, AccessList->AFSOpaque_val, &newACL)
-	!= 0)
-	return (EINVAL);
-    if ((newACL->size + 4) > VAclSize(targetptr))
-	return (E2BIG);
+    if (acl_Internalize_pr(hpr_NameToId, AccessList, &newACL)
+	!= 0) {
+	code = EINVAL;
+	goto done;
+    }
+    if ((newACL->size + 4) > VAclSize(targetptr)) {
+	code = E2BIG;
+	goto done;
+    }
     memcpy((char *)VVnodeACL(targetptr), (char *)newACL, (int)(newACL->size));
+    code = 0;
+
+ done:
     acl_FreeACL(&newACL);
-    return (0);
+    return code;
 
 }				/*RXStore_AccessList */
 
@@ -3462,9 +3470,39 @@ SRXAFS_StoreData64(struct rx_call * acall, struct AFSFid * Fid,
     return code;
 }
 
+/**
+ * Check if the given ACL blob is okay to use.
+ *
+ * If the given ACL is 0-length, or doesn't contain a NUL byte, return an error
+ * and refuse the process the given ACL. The ACL must contain a NUL byte,
+ * otherwise ACL-processing code may run off the end of the buffer and process
+ * uninitialized memory.
+ *
+ * If there is any data beyond the NUL byte, just ignore it and return success.
+ * We won't look at any post-NUL data, but theoretically clients could send
+ * such an ACL to us, since historically it's been allowed.
+ *
+ * @param[in] AccessList    The ACL blob to check
+ *
+ * @returns errno error code to abort the call with
+ * @retval 0 ACL is okay to use
+ */
+static afs_int32
+check_acl(struct AFSOpaque *AccessList)
+{
+    if (AccessList->AFSOpaque_len == 0) {
+	return EINVAL;
+    }
+    if (memchr(AccessList->AFSOpaque_val, '\0',
+	       AccessList->AFSOpaque_len) == NULL) {
+	return EINVAL;
+    }
+    return 0;
+}
+
 afs_int32
 SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
-		struct AFSOpaque * AccessList,
+		struct AFSOpaque *uncheckedACL,
 		struct AFSFetchStatus * OutStatus, struct AFSVolSync * Sync)
 {
     Vnode *targetptr = 0;	/* pointer to input fid */
@@ -3478,6 +3516,7 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
     struct host *thost;
     struct client *t_client = NULL;	/* tmp ptr to client data */
     struct in_addr logHostAddr;	/* host ip holder for inet_ntoa */
+    char *rawACL = NULL;
 #if FS_STATS_DETAILED
     struct fs_stats_opTimingData *opP;	/* Ptr to this op's timing struct */
     struct timeval opStartTime, opStopTime;	/* Start/stop times for RPC op */
@@ -3496,12 +3535,18 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
     if ((errorCode = CallPreamble(acall, ACTIVECALL, Fid, &tcon, &thost)))
 	goto Bad_StoreACL;
 
+    errorCode = check_acl(uncheckedACL);
+    if (errorCode != 0) {
+	goto Bad_StoreACL;
+    }
+    rawACL = uncheckedACL->AFSOpaque_val;
+
     /* Get ptr to client data for user Id for logging */
     t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
     logHostAddr.s_addr = rxr_HostOf(tcon);
     ViceLog(1,
 	    ("SAFS_StoreACL, Fid = %u.%u.%u, ACL=%s, Host %s:%d, Id %d\n",
-	     Fid->Volume, Fid->Vnode, Fid->Unique, AccessList->AFSOpaque_val,
+	     Fid->Volume, Fid->Vnode, Fid->Unique, rawACL,
 	     inet_ntoa(logHostAddr), ntohs(rxr_PortOf(tcon)), t_client->ViceId));
     FS_LOCK;
     AFSCallStats.StoreACL++, AFSCallStats.TotalCalls++;
@@ -3530,7 +3575,7 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
     }
 
     /* Build and store the new Access List for the dir */
-    if ((errorCode = RXStore_AccessList(targetptr, AccessList))) {
+    if ((errorCode = RXStore_AccessList(targetptr, rawACL))) {
 	goto Bad_StoreACL;
     }
 
@@ -3575,7 +3620,7 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
 
     osi_auditU(acall, StoreACLEvent, errorCode,
                AUD_ID, t_client ? t_client->ViceId : 0,
-               AUD_FID, Fid, AUD_ACL, AccessList->AFSOpaque_val, AUD_END);
+               AUD_FID, Fid, AUD_ACL, rawACL, AUD_END);
     return errorCode;
 
 }				/*SRXAFS_StoreACL */
diff --git a/src/viced/host.c b/src/viced/host.c
index 4edcf43e4..61f698943 100644
--- a/src/viced/host.c
+++ b/src/viced/host.c
@@ -44,6 +44,7 @@
 #endif
 #include <afs/acl.h>
 #include <afs/ptclient.h>
+#include <afs/pterror.h>
 #include <afs/ptuser.h>
 #include <afs/prs_fs.h>
 #include <afs/auth.h>
@@ -409,6 +410,9 @@ hpr_NameToId(namelist *names, idlist *ids)
     for (i = 0; i < names->namelist_len; i++)
         stolower(names->namelist_val[i]);
     code = ubik_PR_NameToID(uclient, 0, names, ids);
+    if (code == 0 && ids->idlist_len != names->namelist_len) {
+	code = 267281L; /* PRINTERNAL */
+    }
     return code;
 #else
     return pr_NameToId(names, ids);
diff --git a/src/vlserver/vlclient.c b/src/vlserver/vlclient.c
index b29c5d860..757b0803f 100644
--- a/src/vlserver/vlclient.c
+++ b/src/vlserver/vlclient.c
@@ -584,6 +584,9 @@ handleit(struct cmd_syndesc *as, void *arock)
 		    printf("VL_ListAttributes returned code = %d\n", code);
 		    continue;
 		}
+		if (entries.bulkentries_len < nentries) {
+		    nentries = entries.bulkentries_len;
+		}
 		entry = (struct vldbentry *)entries.bulkentries_val;
 		for (i = 0; i < nentries; i++, entry++)
 		    display_entry(entry, 0);
@@ -619,6 +622,9 @@ handleit(struct cmd_syndesc *as, void *arock)
 			       code);
 			break;
 		    }
+		    if (entries.nbulkentries_len < nentries) {
+			nentries = entries.nbulkentries_len;
+		    }
 
 		    t += nentries;
 		    entry = (struct nvldbentry *)entries.nbulkentries_val;
@@ -787,6 +793,9 @@ handleit(struct cmd_syndesc *as, void *arock)
 		    printf("VL_GetAddrs returned code = %d\n", code);
 		    continue;
 		}
+		if (addrs.bulkaddrs_len < nentries) {
+		    nentries = addrs.bulkaddrs_len;
+		}
 		addrp = addrs.bulkaddrs_val;
 		for (i = 0; i < nentries; i++, addrp++) {
 		    if ((*addrp & 0xff000000) == 0xff000000)
@@ -812,6 +821,9 @@ handleit(struct cmd_syndesc *as, void *arock)
 		    printf("VL_GetAddrs returned code = %d\n", code);
 		    continue;
 		}
+		if (addrs.bulkaddrs_len < nentries) {
+		    nentries = addrs.bulkaddrs_len;
+		}
 		addrp = addrs.bulkaddrs_val;
 		for (i = 0; i < nentries; i++, addrp++) {
 		    if ((*addrp & 0xff000000) == 0xff000000) {
@@ -837,6 +849,9 @@ handleit(struct cmd_syndesc *as, void *arock)
 			    printf("VL_GetAddrsU returned code = %d\n", code);
 			    continue;
 			}
+			if (mhaddrs.bulkaddrs_len < mhnentries) {
+			    mhnentries = mhaddrs.bulkaddrs_len;
+			}
 			printf
 			    ("   [%d]: uuid[%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x]\n   addrunique=%d, ip address(es):\n",
 			     attrs.index, uuid.time_low, uuid.time_mid,
@@ -887,6 +902,9 @@ handleit(struct cmd_syndesc *as, void *arock)
 		    printf("VL_GetAddrs returned code = %d\n", code);
 		    continue;
 		}
+		if (addrs1.bulkaddrs_len < nentries1) {
+		    nentries1 = addrs1.bulkaddrs_len;
+		}
 		addrp1 = addrs1.bulkaddrs_val;
 		for (i = 0; i < nentries1; i++, addrp1++) {
 		    if ((*addrp1 & 0xff000000) != 0xff000000) {
@@ -910,6 +928,9 @@ handleit(struct cmd_syndesc *as, void *arock)
 			    printf("VL_GetAddrsU returned code = %d\n", code);
 			    break;
 			}
+			if (addrs2.bulkaddrs_len < nentries2) {
+			    nentries2 = addrs2.bulkaddrs_len;
+			}
 
 			addrp2 = addrs2.bulkaddrs_val;
 			for (j = 0; j < nentries2; j++) {
diff --git a/src/volser/vos.c b/src/volser/vos.c
index a7b4851fc..cda14f05b 100644
--- a/src/volser/vos.c
+++ b/src/volser/vos.c
@@ -4580,6 +4580,7 @@ ListVLDB(struct cmd_syndesc *as, void *arock)
 				  &arrayEntries, &nextindex);
 	if (vcode == RXGEN_OPCODE) {
 	    /* Vlserver not running with ListAttributesN2. Fall back */
+	    xdr_free((xdrproc_t) xdr_nbulkentries, &arrayEntries);
 	    vcode =
 		VLDB_ListAttributes(&attributes, &centries, &arrayEntries);
 	    nextindex = -1;
diff --git a/src/volser/vsprocs.c b/src/volser/vsprocs.c
index c8f68daa8..59916a295 100644
--- a/src/volser/vsprocs.c
+++ b/src/volser/vsprocs.c
@@ -2856,6 +2856,18 @@ UV_BackupVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid)
     return error;
 }
 
+static int
+ListOneVolume(struct rx_connection *aconn, afs_int32 apart, afs_uint32 avolid,
+	      volEntries *entries)
+{
+    afs_int32 code;
+    code = AFSVolListOneVolume(aconn, apart, avolid, entries);
+    if (code == 0 && entries->volEntries_len != 1) {
+	code = VOLSERFAILEDOP;
+    }
+    return code;
+}
+
 /* Make a new clone of volume <avolid> on <aserver> and <apart>
  * using volume ID <acloneid>, or a new ID allocated from the VLDB.
  * The new volume is named by <aname>, or by appending ".clone" to
@@ -2883,7 +2895,7 @@ UV_CloneVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid,
     if (!aname) {
 	volumeInfo.volEntries_val = (volintInfo *) 0;
 	volumeInfo.volEntries_len = 0;
-	code = AFSVolListOneVolume(aconn, apart, avolid, &volumeInfo);
+	code = ListOneVolume(aconn, apart, avolid, &volumeInfo);
 	if (code) {
 	    fprintf(stderr, "Could not get info for volume %lu\n",
 		    (unsigned long)avolid);
@@ -3621,9 +3633,8 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver,
 		}
 		volumeInfo.volEntries_val = NULL;
 		volumeInfo.volEntries_len = 0;
-		code = AFSVolListOneVolume(conn, entry.serverPartition[vldbindex],
-		                           entry.volumeId[ROVOL],
-		                           &volumeInfo);
+		code = ListOneVolume(conn, entry.serverPartition[vldbindex],
+				     entry.volumeId[ROVOL], &volumeInfo);
 		if (code) {
 		    fprintf(STDERR, "Could not fetch information about RO vol %lu from server %s\n",
 		                    (unsigned long)entry.volumeId[ROVOL],
@@ -3651,8 +3662,7 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver,
 	    volEntries volumeInfo;
 	    volumeInfo.volEntries_val = NULL;
 	    volumeInfo.volEntries_len = 0;
-	    code = AFSVolListOneVolume(fromconn, afrompart, afromvol,
-	                               &volumeInfo);
+	    code = ListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
 	    if (code) {
 		fprintf(STDERR, "Could not fetch information about RW vol %lu from server %s\n",
 		                (unsigned long)afromvol,
@@ -4000,6 +4010,10 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver,
 	    nservers = 1;
 	}
 
+	if (code == 0 && results.manyResults_len != tr.manyDests_len) {
+	    code = VOLSERFAILEDOP;
+	}
+
 	if (code) {
 	    PrintError("Release failed: ", code);
 	} else {
@@ -5666,7 +5680,7 @@ UV_ListOneVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 volid,
     volumeInfo.volEntries_len = 0;
 
     aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
-    code = AFSVolListOneVolume(aconn, apart, volid, &volumeInfo);
+    code = ListOneVolume(aconn, apart, volid, &volumeInfo);
     if (code) {
 	fprintf(STDERR,
 		"Could not fetch the information about volume %lu from the server\n",
@@ -5734,6 +5748,9 @@ UV_XListOneVolume(afs_uint32 a_serverID, afs_int32 a_partID, afs_uint32 a_volID,
      */
     rxConnP = UV_Bind(a_serverID, AFSCONF_VOLUMEPORT);
     code = AFSVolXListOneVolume(rxConnP, a_partID, a_volID, &volumeXInfo);
+    if (code == 0 && volumeXInfo.volXEntries_len != 1) {
+	code = VOLSERFAILEDOP;
+    }
     if (code)
 	fprintf(STDERR,
 		"[UV_XListOneVolume] Couldn't fetch the volume information\n");
@@ -6355,9 +6372,7 @@ UV_SyncVolume(afs_uint32 aserver, afs_int32 apart, char *avolname, int flags)
 	/* If a volume ID were given, search for it on each partition */
 	if ((volumeid = atol(avolname))) {
 	    for (j = 0; j < pcnt; j++) {
-		code =
-		    AFSVolListOneVolume(aconn, PartList.partId[j], volumeid,
-					&volumeInfo);
+		code = ListOneVolume(aconn, PartList.partId[j], volumeid, &volumeInfo);
 		if (code) {
 		    if (code != ENODEV) {
 			fprintf(STDERR, "Could not query server\n");
@@ -6395,9 +6410,8 @@ UV_SyncVolume(afs_uint32 aserver, afs_int32 apart, char *avolname, int flags)
 	    for (k = 0; k < pcnt; k++) {	/* For each partition */
 		volumeInfo.volEntries_val = (volintInfo *) 0;
 		volumeInfo.volEntries_len = 0;
-		code =
-		    AFSVolListOneVolume(aconn, PartList.partId[k],
-					vldbentry.volumeId[j], &volumeInfo);
+		code = ListOneVolume(aconn, PartList.partId[k],
+				     vldbentry.volumeId[j], &volumeInfo);
 		if (code) {
 		    if (code != ENODEV) {
 			fprintf(STDERR, "Could not query server\n");
@@ -6649,7 +6663,7 @@ VolumeExists(afs_uint32 server, afs_int32 partition, afs_uint32 volumeid)
     if (conn) {
 	volumeInfo.volEntries_val = (volintInfo *) 0;
 	volumeInfo.volEntries_len = 0;
-	code = AFSVolListOneVolume(conn, partition, volumeid, &volumeInfo);
+	code = ListOneVolume(conn, partition, volumeid, &volumeInfo);
 	if (volumeInfo.volEntries_val)
 	    free(volumeInfo.volEntries_val);
 	if (code == VOLSERILLEGAL_PARTITION)
diff --git a/src/volser/vsutils.c b/src/volser/vsutils.c
index 711673f63..e9578f287 100644
--- a/src/volser/vsutils.c
+++ b/src/volser/vsutils.c
@@ -389,6 +389,9 @@ VLDB_IsSameAddrs(afs_uint32 serv1, afs_uint32 serv2, afs_int32 *errorp)
     }
 
     code = 0;
+    if (addrs.bulkaddrs_len < nentries) {
+	nentries = addrs.bulkaddrs_len;
+    }
     if (nentries > GETADDRUCACHESIZE)
 	nentries = GETADDRUCACHESIZE;	/* safety check; should not happen */
     if (++cacheip_index >= GETADDRUCACHESIZE)
