diff --git a/NEWS b/NEWS
index 0be2de3018..eb75f6dc83 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,34 @@
                        User-Visible OpenAFS Changes
 
+OpenAFS 1.8.13
+
+  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.8.12.2
 
   Linux clients
diff --git a/configure-libafs.ac b/configure-libafs.ac
index 529ac1108c..9f4cb976c3 100644
--- a/configure-libafs.ac
+++ b/configure-libafs.ac
@@ -4,7 +4,7 @@ AC_CONFIG_AUX_DIR([build-tools])
 AC_CONFIG_SRCDIR([src/libafs/Makefile.common.in])
 
 AC_CONFIG_HEADERS([src/config/afsconfig.h])
-MACOS_VERSION=1.8.13d2
+MACOS_VERSION=1.8.13
 
 AC_SUBST([MACOS_VERSION])
 
diff --git a/configure.ac b/configure.ac
index ada3aa3d86..212f8d544c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@ AC_CONFIG_MACRO_DIR([src/cf])
 AC_CONFIG_SRCDIR([src/config/stds.h])
 
 AC_CONFIG_HEADERS([src/config/afsconfig.h])
-MACOS_VERSION=1.8.13d2
+MACOS_VERSION=1.8.13
 
 AC_SUBST([MACOS_VERSION])
 
diff --git a/src/WINNT/afsd/cm_getaddrs.c b/src/WINNT/afsd/cm_getaddrs.c
index 29e9d1a6cc..a165271e2a 100644
--- a/src/WINNT/afsd/cm_getaddrs.c
+++ b/src/WINNT/afsd/cm_getaddrs.c
@@ -234,6 +234,7 @@ cm_GetAddrsU(cm_cell_t *cellp, cm_user_t *userp, cm_req_t *reqp,
 	    code = cm_ConnByMServers(cellp->vlServersp, 0, userp, reqp, &connp);
 	    if (code)
 		continue;
+	    xdr_free((xdrproc_t) xdr_bulkaddrs, &addrs);
 	    rxconnp = cm_GetRxConn(connp);
 	    code = VL_GetAddrsU(rxconnp, &attrs, &uuid, &unique, &nentries,
 				 &addrs);
@@ -260,6 +261,8 @@ cm_GetAddrsU(cm_cell_t *cellp, cm_user_t *userp, cm_req_t *reqp,
 	if (code)
 	    return CM_ERROR_RETRY;
 
+	nentries = min(nentries, addrs.bulkaddrs_len);
+
 	if (nentries == 0) {
 	    xdr_free((xdrproc_t) xdr_bulkaddrs, &addrs);
 	    code = CM_ERROR_INVAL;
diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c
index ba4530fc8d..87e4ac5f89 100644
--- a/src/WINNT/afsd/cm_ioctl.c
+++ b/src/WINNT/afsd/cm_ioctl.c
@@ -433,7 +433,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;
@@ -447,6 +447,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;
@@ -755,9 +762,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
@@ -776,19 +780,23 @@ cm_IoctlGetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
     {
         cm_fid_t    vfid;
         cm_scache_t *vscp;
+	char *Name = NULL;
+	char *OfflineMsg = NULL;
+	char *MOTD = NULL;
 
         cm_SetFid(&vfid, scp->fid.cell, scp->fid.volume, 1, 1);
         code = cm_GetSCache(&vfid, NULL, &vscp, userp, reqp);
         if (code)
             return code;
 
-        Name = volName;
-        OfflineMsg = offLineMsg;
-        MOTD = motd;
         do {
             code = cm_ConnFromFID(&vfid, 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, vfid.volume,
                                          &volStat, &Name, &OfflineMsg, &MOTD);
@@ -798,6 +806,19 @@ cm_IoctlGetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
         code = cm_MapRPCError(code, reqp);
 
         cm_ReleaseSCache(vscp);
+
+	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 074a970450..64a3dbe65d 100644
--- a/src/WINNT/afsd/cm_vnodeops.c
+++ b/src/WINNT/afsd/cm_vnodeops.c
@@ -2519,6 +2519,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
@@ -2743,12 +2750,6 @@ cm_IsSpaceAvailable(cm_fid_t * fidp, osi_hyper_t *sizep, cm_user_t *userp, cm_re
     AFSFetchVolumeStatus volStat;
     cm_volume_t *volp = NULL;
     afs_uint32   volType;
-    char *Name;
-    char *OfflineMsg;
-    char *MOTD;
-    char volName[32]="(unknown)";
-    char offLineMsg[256]="server temporarily inaccessible";
-    char motd[256]="server temporarily inaccessible";
     osi_hyper_t freespace;
     cm_fid_t    vfid;
     cm_scache_t *vscp;
@@ -2778,11 +2779,11 @@ cm_IsSpaceAvailable(cm_fid_t * fidp, osi_hyper_t *sizep, cm_user_t *userp, cm_re
                           CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
         lock_ReleaseWrite(&vscp->rw);
         if (code == 0) {
-            Name = volName;
-            OfflineMsg = offLineMsg;
-            MOTD = motd;
-
             do {
+		char *Name = NULL;
+		char *OfflineMsg = NULL;
+		char *MOTD = NULL;
+
                 code = cm_ConnFromFID(&vfid, userp, reqp, &connp);
                 if (code) continue;
 
@@ -2791,6 +2792,10 @@ cm_IsSpaceAvailable(cm_fid_t * fidp, osi_hyper_t *sizep, cm_user_t *userp, cm_re
                                              &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, userp, reqp, &vfid, NULL, 0, NULL, NULL, NULL, NULL, code));
             code = cm_MapRPCError(code, reqp);
         }
diff --git a/src/WINNT/afsd/cm_volume.c b/src/WINNT/afsd/cm_volume.c
index c85107ba76..de2d80be41 100644
--- a/src/WINNT/afsd/cm_volume.c
+++ b/src/WINNT/afsd/cm_volume.c
@@ -1311,24 +1311,14 @@ 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];
     afs_uint32 volType;
-    char offLineMsg[256];
-    char motd[256];
     long alldown, alldeleted;
     cm_serverRef_t *serversp;
     cm_fid_t vfid;
     cm_scache_t *vscp = NULL;
 
-    Name = volName;
-    OfflineMsg = offLineMsg;
-    MOTD = motd;
-
     volType = cm_VolumeType(volp, volID);
 
     if (statep->ID != 0 && (!volID || volID == statep->ID)) {
@@ -1374,6 +1364,10 @@ cm_CheckOfflineVolumeState(cm_volume_t *volp, cm_vol_state_t *statep, afs_uint32
                 code = cm_GetSCache(&vfid, NULL, &vscp, cm_rootUserp, &req);
                 if (code = 0) {
 		    do {
+			char *Name = NULL;
+			char *OfflineMsg = NULL;
+			char *MOTD = NULL;
+
 			code = cm_ConnFromVolume(volp, statep->ID, cm_rootUserp, &req, &connp);
 			if (code)
 			   continue;
@@ -1382,6 +1376,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, &vfid, NULL, 0, NULL, NULL, NULL, NULL, code));
 		    code = cm_MapRPCError(code, &req);
 
diff --git a/src/WINNT/afsd/fs_acl.c b/src/WINNT/afsd/fs_acl.c
index 8012891cd8..45218ae3d8 100644
--- a/src/WINNT/afsd/fs_acl.c
+++ b/src/WINNT/afsd/fs_acl.c
@@ -81,9 +81,10 @@ PruneList (struct AclEntry **ae, int dfs)
 static char *
 SkipLine (char *astr)
 {
-    while (*astr !='\n')
+    while (*astr != '\0' && *astr !='\n')
         astr++;
-    astr++;
+    if (*astr == '\n')
+	astr++;
     return astr;
 }
 
@@ -166,7 +167,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;
@@ -231,9 +232,9 @@ CleanAcl(struct Acl *aa, char *cellname)
 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[ACL_MAXNAME];
+    char tname[ACL_MAXNAME + 1] = "";
     struct AclEntry *first, *next, *last, *tl;
     struct Acl *ta;
 
@@ -280,7 +281,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)
@@ -308,7 +309,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/WINNT/afsrdr/user/RDRFunction.c b/src/WINNT/afsrdr/user/RDRFunction.c
index cffb9b58c6..db767cbb8a 100644
--- a/src/WINNT/afsrdr/user/RDRFunction.c
+++ b/src/WINNT/afsrdr/user/RDRFunction.c
@@ -5820,14 +5820,8 @@ RDR_GetVolumeInfo( IN cm_user_t     *userp,
     DWORD       status;
     FILETIME ft = {0x832cf000, 0x01abfcc4}; /* October 1, 1982 00:00:00 +0600 */
 
-    char volName[32]="(unknown)";
-    char offLineMsg[256]="server temporarily inaccessible";
-    char motd[256]="server temporarily inaccessible";
     cm_conn_t *connp;
     AFSFetchVolumeStatus volStat;
-    char *Name;
-    char *OfflineMsg;
-    char *MOTD;
     struct rx_connection * rxconnp;
     int scp_locked = 0;
 
@@ -5928,13 +5922,14 @@ RDR_GetVolumeInfo( IN cm_user_t     *userp,
         
         if (code == -1)
         {
-	    Name = volName;
-	    OfflineMsg = offLineMsg;
-	    MOTD = motd;
 	    lock_ReleaseWrite(&scp->rw);
 	    scp_locked = 0;
 
 	    do {
+		char *Name = NULL;
+		char *OfflineMsg = NULL;
+		char *MOTD = NULL;
+
 		code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
 		if (code) continue;
 
@@ -5943,6 +5938,10 @@ RDR_GetVolumeInfo( IN cm_user_t     *userp,
 					     &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, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
 	    code = cm_MapRPCError(code, &req);
 
@@ -6056,14 +6055,8 @@ RDR_GetVolumeSizeInfo( IN cm_user_t     *userp,
     cm_req_t    req;
     DWORD       status;
 
-    char volName[32]="(unknown)";
-    char offLineMsg[256]="server temporarily inaccessible";
-    char motd[256]="server temporarily inaccessible";
     cm_conn_t *connp;
     AFSFetchVolumeStatus volStat;
-    char *Name;
-    char *OfflineMsg;
-    char *MOTD;
     struct rx_connection * rxconnp;
     int scp_locked = 0;
 
@@ -6141,13 +6134,14 @@ RDR_GetVolumeSizeInfo( IN cm_user_t     *userp,
         
         if (code == -1)
         {
-	    Name = volName;
-	    OfflineMsg = offLineMsg;
-	    MOTD = motd;
 	    lock_ReleaseWrite(&scp->rw);
 	    scp_locked = 0;
 
 	    do {
+		char *Name = NULL;
+		char *OfflineMsg = NULL;
+		char *MOTD = NULL;
+
 		code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
 		if (code) continue;
 
@@ -6156,6 +6150,10 @@ RDR_GetVolumeSizeInfo( IN cm_user_t     *userp,
 					     &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, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
 	    code = cm_MapRPCError(code, &req);
 
diff --git a/src/afs/AIX/osi_groups.c b/src/afs/AIX/osi_groups.c
index 219dd6db7d..0a916a39f7 100644
--- a/src/afs/AIX/osi_groups.c
+++ b/src/afs/AIX/osi_groups.c
@@ -87,6 +87,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) {
@@ -100,7 +108,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 5899c7287e..ecb49d6df6 100644
--- a/src/afs/DARWIN/osi_groups.c
+++ b/src/afs/DARWIN/osi_groups.c
@@ -98,6 +98,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 */
@@ -109,7 +117,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 2267550bf8..e288326c7d 100644
--- a/src/afs/FBSD/osi_groups.c
+++ b/src/afs/FBSD/osi_groups.c
@@ -80,6 +80,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;
+	}
+    }
+
     gidset = osi_Alloc(gidset_len * sizeof(gid_t));
     ngroups = afs_getgroups(*cred, gidset_len, gidset);
     if (afs_get_pag_from_groups(gidset[1], gidset[2]) == NOPAG) {
@@ -92,7 +100,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);
     osi_Free(gidset, gidset_len * sizeof(gid_t));
diff --git a/src/afs/HPUX/osi_groups.c b/src/afs/HPUX/osi_groups.c
index c3b024c23e..1b28a43f5d 100644
--- a/src/afs/HPUX/osi_groups.c
+++ b/src/afs/HPUX/osi_groups.c
@@ -71,6 +71,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 */
@@ -82,7 +90,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 d3f8b33474..9e1d5c0095 100644
--- a/src/afs/IRIX/osi_groups.c
+++ b/src/afs/IRIX/osi_groups.c
@@ -194,6 +194,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 */
@@ -209,7 +220,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 901312d2a5..a63724b688 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(*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 9ee543932b..81043f4ff3 100644
--- a/src/afs/NBSD/osi_groups.c
+++ b/src/afs/NBSD/osi_groups.c
@@ -84,6 +84,13 @@ setpag(afs_proc_t *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 */
@@ -95,7 +102,7 @@ setpag(afs_proc_t *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 208e5a7447..98ccf0421d 100644
--- a/src/afs/OBSD/osi_groups.c
+++ b/src/afs/OBSD/osi_groups.c
@@ -81,6 +81,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
@@ -102,7 +110,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 4cbb62f9e4..3291009ba8 100644
--- a/src/afs/SOLARIS/osi_groups.c
+++ b/src/afs/SOLARIS/osi_groups.c
@@ -165,6 +165,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).
@@ -174,8 +181,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 c053e150d3..b25d22d112 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(*cred, &pagvalue);
+	if (code != 0) {
+	    return code;
+	}
+    }
+
     gidset = 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 162735b1fc..ec0a0dd435 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_LINUX_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_LINUX_ENV
@@ -182,6 +182,18 @@ afs_pag_wait(afs_ucred_t *acred)
     return code;
 }
 
+afs_int32
+afs_genpag(afs_ucred_t *acred, afs_uint32 *apag)
+{
+    afs_int32 code;
+    code = afs_pag_wait(acred);
+    if (code) {
+	return code;
+    }
+    *apag = genpagval();
+    return 0;
+}
+
 int
 #if	defined(AFS_SUN5_ENV)
 afs_setpag(afs_ucred_t **credpp)
@@ -205,6 +217,7 @@ afs_setpag(void)
 #endif
 
     int code = 0;
+    afs_uint32 pag;
 
 #if defined(AFS_SGI_ENV) && defined(MP)
     /* This is our first chance to get the global lock. */
@@ -213,20 +226,19 @@ afs_setpag(void)
 
     AFS_STATCNT(afs_setpag);
 
-    code = afs_pag_wait(acred);
+    code = afs_genpag(acred, &pag);
     if (code) {
 	goto done;
     }
 
-
 #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)
-    code = AddPag(p, genpag(), &p->l_proc->p_cred);
+    code = AddPag(p, pag, &p->l_proc->p_cred);
 #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;
@@ -234,7 +246,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);
@@ -243,36 +255,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_LINUX_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
 
   done:
@@ -294,7 +306,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 610cfb3a84..679ef3a701 100644
--- a/src/afs/afs_pag_call.c
+++ b/src/afs/afs_pag_call.c
@@ -461,6 +461,8 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int 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 7ddb5add29..faafdd3d2d 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;
 }
 
@@ -1984,32 +1995,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
@@ -2030,8 +2040,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;
 }
 
@@ -4714,7 +4725,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 2ca80a563c..0e7f8a258d 100644
--- a/src/afs/afs_prototypes.h
+++ b/src/afs/afs_prototypes.h
@@ -536,7 +536,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 97210c9e88..1a05a78d89 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 d3d4d00ff1..42f1ba9d91 100644
--- a/src/afs/afs_volume.c
+++ b/src/afs/afs_volume.c
@@ -1205,6 +1205,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);
@@ -1225,6 +1226,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/bucoord/commands.c b/src/bucoord/commands.c
index 10f088a478..dc7847fd14 100644
--- a/src/bucoord/commands.c
+++ b/src/bucoord/commands.c
@@ -2725,6 +2725,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 b73a9351f3..b7fb1d4b3f 100644
--- a/src/bucoord/restore.c
+++ b/src/bucoord/restore.c
@@ -191,7 +191,7 @@ bc_Restorer(afs_int32 aindex)
     serverAll = HOSTADDR(&dumpTaskPtr->destServer);
     partitionAll = dumpTaskPtr->destPartition;
 
-    volumeEntries = malloc(MAXTAPESATONCE * sizeof(struct budb_volumeEntry));
+    volumeEntries = 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 be58e3bbb7..9a05459410 100644
--- a/src/bucoord/ubik_db_if.c
+++ b/src/bucoord/ubik_db_if.c
@@ -120,6 +120,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 8139d572ce..365544ec7b 100644
--- a/src/butc/dump.c
+++ b/src/butc/dump.c
@@ -173,6 +173,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
@@ -217,8 +229,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;
@@ -543,8 +554,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 e8d54ba35c..5e1b3b00cc 100644
--- a/src/config/NTMakefile.amd64_w2k
+++ b/src/config/NTMakefile.amd64_w2k
@@ -88,7 +88,7 @@ AFSPRODUCT_VER_MAJOR=1
 AFSPRODUCT_VER_MINOR=8
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_PATCH)
-AFSPRODUCT_VER_PATCH=1203
+AFSPRODUCT_VER_PATCH=1300
 !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 f00a981ab2..915ce17e01 100644
--- a/src/config/NTMakefile.i386_nt40
+++ b/src/config/NTMakefile.i386_nt40
@@ -88,7 +88,7 @@ AFSPRODUCT_VER_MAJOR=1
 AFSPRODUCT_VER_MINOR=8
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_PATCH)
-AFSPRODUCT_VER_PATCH=1203
+AFSPRODUCT_VER_PATCH=1300
 !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 e8cfb0bea5..e6f62e7ca0 100644
--- a/src/config/NTMakefile.i386_w2k
+++ b/src/config/NTMakefile.i386_w2k
@@ -92,7 +92,7 @@ AFSPRODUCT_VER_MAJOR=1
 AFSPRODUCT_VER_MINOR=8
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_PATCH)
-AFSPRODUCT_VER_PATCH=1203
+AFSPRODUCT_VER_PATCH=1300
 !ENDIF
 !IF !DEFINED(AFSPRODUCT_VER_BUILD)
 AFSPRODUCT_VER_BUILD=0
diff --git a/src/fsprobe/fsprobe.c b/src/fsprobe/fsprobe.c
index f29a56fdd9..18a03cad1e 100644
--- a/src/fsprobe/fsprobe.c
+++ b/src/fsprobe/fsprobe.c
@@ -223,6 +223,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 = malloc(STATS64_VERSION *
 					  sizeof(afs_uint64));
     while (1) {			/*Service loop */
diff --git a/src/kauth/authclient.c b/src/kauth/authclient.c
index 4db0cbc134..c64f330edf 100644
--- a/src/kauth/authclient.c
+++ b/src/kauth/authclient.c
@@ -525,12 +525,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;
@@ -538,6 +541,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 eea1402a24..e951af52a2 100644
--- a/src/kauth/kaaux.c
+++ b/src/kauth/kaaux.c
@@ -34,7 +34,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 = malloc(len);
 	abbs->SeqLen = len;
 	xdr_opaque(x, abbs->SeqBody, len);
@@ -61,7 +71,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 = malloc(maxLen);
 	abbs->MaxSeqLen = maxLen;
 	abbs->SeqLen = len;
diff --git a/src/kauth/kkids.c b/src/kauth/kkids.c
index d5437f152f..7e9043fdd6 100644
--- a/src/kauth/kkids.c
+++ b/src/kauth/kkids.c
@@ -190,7 +190,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
@@ -228,7 +228,7 @@ struct AclEntry {
 static struct Acl *
 ParseAcl(char *astr)
 {
-    int nplus, nminus, i, trights;
+    int nplus = 0, nminus = 0, i, trights = 0;
     char tname[MAXNAME + 1] = "";
     struct AclEntry *first, *last, *tl;
     struct Acl *ta;
@@ -237,7 +237,7 @@ ParseAcl(char *astr)
     sscanf(astr, "%d", &nminus);
     SkipLine(astr);
 
-    ta = 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 58cf061fd5..bc58f8668b 100644
--- a/src/kauth/test/test_interim_ktc.c
+++ b/src/kauth/test/test_interim_ktc.c
@@ -385,9 +385,10 @@ char *
 SkipLine(astr)
      char *astr;
 {
-    while (*astr != '\n')
+    while (*astr != '\0' && *astr != '\n')
+	astr++;
+    if (*astr == '\n')
 	astr++;
-    astr++;
     return astr;
 }
 
@@ -395,8 +396,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);
@@ -404,7 +405,7 @@ ParseAcl(astr)
     sscanf(astr, "%d", &nminus);
     astr = SkipLine(astr);
 
-    ta = malloc(sizeof(struct Acl));
+    ta = calloc(sizeof(*ta), 1);
     ta->nplus = nplus;
     ta->nminus = nminus;
 
@@ -413,7 +414,7 @@ ParseAcl(astr)
     for (i = 0; i < nplus; i++) {
 	sscanf(astr, "%100s %d", tname, &trights);
 	astr = SkipLine(astr);
-	tl = malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	if (!first)
 	    first = tl;
 	strcpy(tl->name, tname);
@@ -430,7 +431,7 @@ ParseAcl(astr)
     for (i = 0; i < nminus; i++) {
 	sscanf(astr, "%100s %d", tname, &trights);
 	astr = SkipLine(astr);
-	tl = 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 d4c3f8c4c9..fbdfaa6f9c 100644
--- a/src/libacl/aclprocs.c
+++ b/src/libacl/aclprocs.c
@@ -116,6 +116,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;
@@ -260,10 +264,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) {
@@ -272,6 +278,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;
@@ -284,6 +294,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_utilAdmin.c b/src/libadmin/adminutil/afs_utilAdmin.c
index 20da3320b7..3afb5cc9be 100644
--- a/src/libadmin/adminutil/afs_utilAdmin.c
+++ b/src/libadmin/adminutil/afs_utilAdmin.c
@@ -2322,6 +2322,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;
@@ -2333,8 +2336,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);
@@ -2343,12 +2344,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 76436c0496..8ec0129770 100644
--- a/src/libadmin/bos/afs_bosAdmin.c
+++ b/src/libadmin/bos/afs_bosAdmin.c
@@ -1289,6 +1289,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;
@@ -1305,14 +1307,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 = 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;
     }
diff --git a/src/libadmin/client/afs_clientAdmin.c b/src/libadmin/client/afs_clientAdmin.c
index d0f61f1063..b485f48e7c 100644
--- a/src/libadmin/client/afs_clientAdmin.c
+++ b/src/libadmin/client/afs_clientAdmin.c
@@ -1435,6 +1435,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;
@@ -1535,9 +1538,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;
@@ -1564,6 +1571,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 80f7d4ccff..97c44ce09d 100644
--- a/src/libadmin/pts/afs_ptsAdmin.c
+++ b/src/libadmin/pts/afs_ptsAdmin.c
@@ -125,6 +125,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 c93875d5d7..8231ca0028 100644
--- a/src/libadmin/vos/afs_vosAdmin.c
+++ b/src/libadmin/vos/afs_vosAdmin.c
@@ -1217,6 +1217,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.
@@ -1368,6 +1372,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 1b99d2b551..eb788b20ff 100644
--- a/src/libadmin/vos/vosutils.c
+++ b/src/libadmin/vos/vosutils.c
@@ -324,6 +324,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) {
@@ -365,6 +368,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 081825fe9b..ab39cd2b36 100644
--- a/src/libadmin/vos/vsprocs.c
+++ b/src/libadmin/vos/vsprocs.c
@@ -600,7 +600,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;
     }
@@ -1162,6 +1162,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)
@@ -1314,7 +1326,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) {
@@ -2773,7 +2785,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 {
@@ -2833,7 +2847,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 596d0e436d..f9cd3740dc 100644
--- a/src/libafscp/afscp_acl.c
+++ b/src/libafscp/afscp_acl.c
@@ -58,6 +58,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 726d2e5a3b..af1fb4bb43 100644
--- a/src/libafscp/afscp_server.c
+++ b/src/libafscp/afscp_server.c
@@ -305,6 +305,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 */
@@ -405,6 +408,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 c97307bdf1..05508a70df 100644
--- a/src/ptserver/pts.c
+++ b/src/ptserver/pts.c
@@ -681,6 +681,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 7df92916a1..1eb7c5c500 100644
--- a/src/ptserver/ptuser.c
+++ b/src/ptserver/ptuser.c
@@ -521,6 +521,9 @@ pr_NameToId(namelist *names, idlist *ids)
 	stolower(names->namelist_val[i]);
     }
     code = ubik_PR_NameToID(pruclient, 0, names, ids);
+    if (code == 0 && ids->idlist_len != names->namelist_len) {
+	code = PRINTERNAL;
+    }
     return code;
 }
 
@@ -566,6 +569,9 @@ string_PR_IDToName(struct ubik_client *client, afs_int32 flags,
     code = ubik_PR_IDToName(client, flags, ids, names);
     if (code)
 	return code;
+    if (names->namelist_len != ids->idlist_len) {
+	return PRINTERNAL;
+    }
     for (i = 0; i < names->namelist_len; i++) {
 	code = check_length(names->namelist_val[i]);
 	if (code)
diff --git a/src/ptserver/testpt.c b/src/ptserver/testpt.c
index c359f8f465..50f0029f6f 100644
--- a/src/ptserver/testpt.c
+++ b/src/ptserver/testpt.c
@@ -112,6 +112,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 bfc1b7f6fe..6826a28715 100644
--- a/src/rx/xdr.c
+++ b/src/rx/xdr.c
@@ -404,10 +404,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);
     }
@@ -530,7 +548,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;
@@ -541,13 +559,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;
-	AFS_FALLTHROUGH;
+
+	/* 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 1785019922..bfbd429db8 100644
--- a/src/rx/xdr_array.c
+++ b/src/rx/xdr_array.c
@@ -93,10 +93,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 d6cb1f7d12..80d1dfa054 100644
--- a/src/rx/xdr_arrayn.c
+++ b/src/rx/xdr_arrayn.c
@@ -93,10 +93,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 cf16afcea0..6881234220 100644
--- a/src/sys/rmtsysc.c
+++ b/src/sys/rmtsysc.c
@@ -214,7 +214,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;
@@ -260,7 +260,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 da6b3e64e4..1e6911f59a 100644
--- a/src/sys/rmtsysnet.c
+++ b/src/sys/rmtsysnet.c
@@ -55,9 +55,10 @@ struct ClearToken {
 char *
 RSkipLine(char *astr)
 {
-    while (*astr != '\n')
+    while (*astr != '\0' && *astr != '\n')
+	astr++;
+    if (*astr == '\n')
 	astr++;
-    astr++;
     return astr;
 }
 
@@ -65,7 +66,7 @@ RSkipLine(char *astr)
 struct Acl *
 RParseAcl(char *astr)
 {
-    int nplus, nminus, i, trights;
+    int nplus = 0, nminus = 0, i, trights = 0;
     char tname[MAXNAME + 1] = "";
     struct AclEntry *first, *last, *tl;
     struct Acl *ta;
@@ -74,7 +75,7 @@ RParseAcl(char *astr)
     sscanf(astr, "%d", &nminus);
     astr = RSkipLine(astr);
 
-    ta = malloc(sizeof(struct Acl));
+    ta = calloc(sizeof(*ta), 1);
     ta->nplus = nplus;
     ta->nminus = nminus;
 
@@ -83,7 +84,7 @@ RParseAcl(char *astr)
     for (i = 0; i < nplus; i++) {
 	sscanf(astr, "%" opr_stringize(MAXNAME) "s %d", tname, &trights);
 	astr = RSkipLine(astr);
-	tl = malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	if (!first)
 	    first = tl;
 	strcpy(tl->name, tname);
@@ -100,7 +101,7 @@ RParseAcl(char *astr)
     for (i = 0; i < nminus; i++) {
 	sscanf(astr, "%" opr_stringize(MAXNAME) "s %d", tname, &trights);
 	astr = RSkipLine(astr);
-	tl = 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 003eff8b93..0eb4b53bca 100644
--- a/src/uss/uss_acl.c
+++ b/src/uss/uss_acl.c
@@ -339,9 +339,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 */
@@ -404,7 +405,7 @@ static struct Acl *
 ParseAcl(char *a_str)
 {				/*ParseAcl */
 
-    int nplus, nminus, i, trights;
+    int nplus = 0, nminus = 0, i, trights = 0;
     char tname[MAXNAME + 1] = "";
     struct AclEntry *first, *last, *tl;
     struct Acl *ta;
@@ -421,7 +422,7 @@ ParseAcl(char *a_str)
     /*
      * Allocate and initialize the first entry.
      */
-    ta = malloc(sizeof(struct Acl));
+    ta = calloc(sizeof(*ta), 1);
     ta->nplus = nplus;
     ta->nminus = nminus;
 
@@ -433,7 +434,7 @@ ParseAcl(char *a_str)
     for (i = 0; i < nplus; i++) {
 	sscanf(a_str, "%" opr_stringize(MAXNAME) "s %d", tname, &trights);
 	a_str = SkipLine(a_str);
-	tl = malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	if (!first)
 	    first = tl;
 	strcpy(tl->name, tname);
@@ -453,7 +454,7 @@ ParseAcl(char *a_str)
     for (i = 0; i < nminus; i++) {
 	sscanf(a_str, "%" opr_stringize(MAXNAME) "s %d", tname, &trights);
 	a_str = SkipLine(a_str);
-	tl = 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 656bceb57b..810bea3b91 100644
--- a/src/venus/cacheout.c
+++ b/src/venus/cacheout.c
@@ -71,6 +71,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 ac16bb43b1..fa914a4c42 100644
--- a/src/venus/fs.c
+++ b/src/venus/fs.c
@@ -553,9 +553,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;
 }
 
@@ -572,7 +573,7 @@ EmptyAcl(char *astr)
     struct Acl *tp;
     int junk;
 
-    tp = malloc(sizeof(struct Acl));
+    tp = calloc(sizeof(*tp), 1);
     assert(tp);
     tp->nplus = tp->nminus = 0;
     tp->pluslist = tp->minuslist = 0;
@@ -584,12 +585,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 = 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);
@@ -605,7 +606,7 @@ ParseAcl(char *astr)
     for (i = 0; i < nplus; i++) {
 	sscanf(astr, "%99s %d", tname, &trights);
 	astr = SkipLine(astr);
-	tl = malloc(sizeof(struct AclEntry));
+	tl = calloc(sizeof(*tl), 1);
 	assert(tl);
 	if (!first)
 	    first = tl;
@@ -623,7 +624,7 @@ ParseAcl(char *astr)
     for (i = 0; i < nminus; i++) {
 	sscanf(astr, "%99s %d", tname, &trights);
 	astr = SkipLine(astr);
-	tl = 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 31ce69a93d..5e6655fa26 100644
--- a/src/viced/afsfileprocs.c
+++ b/src/viced/afsfileprocs.c
@@ -1246,18 +1246,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 */
 
@@ -3059,9 +3067,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 */
@@ -3076,18 +3114,25 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
     struct client *t_client = NULL;	/* tmp ptr to client data */
     struct in_addr logHostAddr;	/* host ip holder for inet_ntoa */
     struct fsstats fsstats;
+    char *rawACL = NULL;
 
     fsstats_StartOp(&fsstats, FS_STATS_RPCIDX_STOREACL);
 
     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->z.ViceId));
     FS_LOCK;
     AFSCallStats.StoreACL++, AFSCallStats.TotalCalls++;
@@ -3116,7 +3161,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;
     }
 
@@ -3143,7 +3188,7 @@ SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
 
     osi_auditU(acall, StoreACLEvent, errorCode,
 	       AUD_ID, t_client ? t_client->z.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 f2ce790ba3..1adc7aa199 100644
--- a/src/viced/host.c
+++ b/src/viced/host.c
@@ -30,6 +30,7 @@
 #include <afs/ihandle.h>
 #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>
@@ -403,6 +404,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 = PRINTERNAL;
+    }
     return code;
 }
 
diff --git a/src/vlserver/vlclient.c b/src/vlserver/vlclient.c
index 20c14a5c1f..8426e7f680 100644
--- a/src/vlserver/vlclient.c
+++ b/src/vlserver/vlclient.c
@@ -561,6 +561,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);
@@ -596,6 +599,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;
@@ -764,6 +770,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)
@@ -789,6 +798,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) {
@@ -814,6 +826,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,
@@ -864,6 +879,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) {
@@ -887,6 +905,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 007bfe5064..6efc1c73fd 100644
--- a/src/volser/vos.c
+++ b/src/volser/vos.c
@@ -4520,6 +4520,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 b24ec77f74..e20749fb81 100644
--- a/src/volser/vsprocs.c
+++ b/src/volser/vsprocs.c
@@ -2865,6 +2865,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
@@ -2892,7 +2904,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);
@@ -3620,9 +3632,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],
@@ -3650,8 +3661,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,
@@ -3993,6 +4003,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 {
@@ -5503,7 +5517,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",
@@ -5570,6 +5584,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");
@@ -6191,9 +6208,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");
@@ -6231,9 +6246,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");
@@ -6485,7 +6499,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 e5d0beb7ec..fca2283e7a 100644
--- a/src/volser/vsutils.c
+++ b/src/volser/vsutils.c
@@ -377,6 +377,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)
