- djm@cvs.openbsd.org 2006/03/25 01:13:23
     [buffer.c channels.c deattack.c misc.c scp.c session.c sftp-client.c]
     [sftp-server.c ssh-agent.c ssh-rsa.c xmalloc.c xmalloc.h auth-pam.c]
     [uidswap.c]
     change OpenSSH's xrealloc() function from being xrealloc(p, new_size)
     to xrealloc(p, new_nmemb, new_itemsize).

     realloc is particularly prone to integer overflows because it is
     almost always allocating "n * size" bytes, so this is a far safer
     API; ok deraadt@
diff --git a/channels.c b/channels.c
index 0e7d5cf..5706833 100644
--- a/channels.c
+++ b/channels.c
@@ -266,8 +266,8 @@
 		if (channels_alloc > 10000)
 			fatal("channel_new: internal error: channels_alloc %d "
 			    "too big.", channels_alloc);
-		channels = xrealloc(channels,
-		    (channels_alloc + 10) * sizeof(Channel *));
+		channels = xrealloc(channels, channels_alloc + 10,
+		    sizeof(Channel *));
 		channels_alloc += 10;
 		debug2("channel: expanding %d", channels_alloc);
 		for (i = found; i < channels_alloc; i++)
@@ -1789,15 +1789,20 @@
 channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
     u_int *nallocp, int rekeying)
 {
-	u_int n, sz;
+	u_int n, sz, nfdset;
 
 	n = MAX(*maxfdp, channel_max_fd);
 
-	sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
+	nfdset = howmany(n+1, NFDBITS);
+	/* Explicitly test here, because xrealloc isn't always called */
+	if (nfdset && SIZE_T_MAX / nfdset < sizeof(fd_mask))
+		fatal("channel_prepare_select: max_fd (%d) is too large", n);
+	sz = nfdset * sizeof(fd_mask);
+
 	/* perhaps check sz < nalloc/2 and shrink? */
 	if (*readsetp == NULL || sz > *nallocp) {
-		*readsetp = xrealloc(*readsetp, sz);
-		*writesetp = xrealloc(*writesetp, sz);
+		*readsetp = xrealloc(*readsetp, nfdset, sizeof(fd_mask));
+		*writesetp = xrealloc(*writesetp, nfdset, sizeof(fd_mask));
 		*nallocp = sz;
 	}
 	*maxfdp = n;