Package: xfstt
Version: 1.4-3
Author: Guillem Jover <guillem@hadrons.org>
Status: applied
Description:
 Fixed multiple buffer overflows in the network packet handling:
  CAN-2003-0581.

diff -Naur xfstt-1.4/debian/changelog xfstt-1.4-sec/debian/changelog
--- xfstt-1.4/debian/changelog	2003-07-29 08:54:19.000000000 +0200
+++ xfstt-1.4-sec/debian/changelog	2003-07-29 08:33:02.000000000 +0200
@@ -1,3 +1,10 @@
+xfstt (1.4-4) testing-security; urgency=high
+
+  * Fixed multiple buffer overflows in the network packet handling:
+    CAN-2003-0581.
+
+ -- Guillem Jover <guillem@debian.org>  Tue, 29 Jul 2003 08:32:40 +0200
+
 xfstt (1.4-3) unstable; urgency=low
 
   * Corrected the watch file.
diff -Naur xfstt-1.4/src/xfstt.cc xfstt-1.4-sec/src/xfstt.cc
--- xfstt-1.4/src/xfstt.cc	2002-11-14 13:08:08.000000000 +0100
+++ xfstt-1.4-sec/src/xfstt.cc	2003-07-29 08:53:10.000000000 +0200
@@ -809,6 +809,32 @@
 }
 
 static int
+send_fserror(int sd, int seqno)
+{
+	fsError reply;
+
+	reply.type = FS_Error;
+	reply.request = FSBadLength;
+	reply.sequenceNumber = seqno;
+	reply.length = sizeof(reply) >> 2;
+
+	return write(sd, (void *)&reply, sizeof(reply));
+}
+
+static int
+check_length(int sd, int seqno, fsReq *req, int expected_size)
+{
+	if (req->length < (expected_size >> 2)) {
+		dprintf2("packet size mismatch: %d received bytes, "
+		      "%d expected bytes\n", req->length << 2, expected_size);
+		send_fserror(sd, seqno);
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+static int
 prepare2connect(int portno)
 {
 	static struct sockaddr_un s_unix;
@@ -1032,17 +1058,12 @@
 		sync();
 #endif
 
-		int length = ((fsReq *)buf)->length << 2;
+		fsReq *fsreq = (fsReq *)buf;
+		int length = fsreq->length << 2;
 		if (length > MAXREQSIZE) {
-			dprintf1("request too big: %d bytes\n", length);
-
-			fsError reply;
-			reply.type = FS_Error;
-			reply.request = FSBadLength;
-			reply.sequenceNumber = seqno;
-			reply.length = sizeof(reply) >> 2;
-
-			write(sd, (void *)&reply, sizeof(reply));
+			dprintf2("too much data: %d bytes (max=%d)\n",
+			         length, MAXREQSIZE);
+			send_fserror(sd, seqno);
 			break;
 		}
 
@@ -1192,7 +1213,13 @@
 		case FS_SetResolution:
 			{
 			fsSetResolutionReq *req = (fsSetResolutionReq *)buf;
-			int numres = req->num_resolutions;	// XXX 1
+			int numres = req->num_resolutions;
+			int expected_size = numres * sz_fsResolution
+					    + sz_fsSetResolutionReq;
+
+			if (!check_length(sd, seqno, fsreq, expected_size))
+				break;
+
 			fsResolution *res = (fsResolution *)(req + 1);
 
 			dprintf1("FS_SetResolution * %d\n", numres);
@@ -1237,6 +1264,10 @@
 			{
 			fsListFontsReq* req = (fsListFontsReq *)buf;
 			char *pattern = (char *)(req + 1);
+			int expected_size = sz_fsListFontsReq + req->nbytes;
+
+			if (!check_length(sd, seqno, fsreq, expected_size))
+				break;
 
 			pattern[req->nbytes] = 0;
 			dprintf2("FS_ListFonts \"%s\" * %ld\n",
@@ -1440,15 +1471,6 @@
 			break;
 
 		case FS_QueryXExtents8:
-			// convert to QueryXExtents16 request
-			{
-			fsQueryXExtents8Req *req = (fsQueryXExtents8Req *)buf;
-			U8 *p8 = (U8 *)(req + 1);
-			U16 *p16 = (U16 *)p8;
-			for (i = req->num_ranges; --i >= 0;)
-				p16[i] = htons(p8[i]);
-			}
-			// fall through
 		case FS_QueryXExtents16:
 			{
 			fsQueryXExtents16Req *req = (fsQueryXExtents16Req *)buf;
@@ -1458,6 +1480,24 @@
 			dprintf2("range=%d, nranges=%ld\n",
 				req->range, req->num_ranges);
 
+			int item_size = (req->reqType == FS_QueryXExtents8)
+				        ? 1 : 2;
+			int expected_size = sz_fsQueryXExtents8Req
+				            + req->num_ranges * item_size;
+
+			if (!check_length(sd, seqno, fsreq, expected_size))
+				break;
+
+			if (req->reqType == FS_QueryXExtents8) {
+				/*
+				 * Convert to QueryXExtents16 request
+				 */
+				U8 *p8 = (U8 *)(req + 1);
+				U16 *p16 = (U16 *)p8;
+				for (i = req->num_ranges; --i >= 0;)
+					p16[i] = htons(p8[i]);
+			}
+
 			XFSFont *xfs = findFont(req->fid, sd, seqno);
 			if (!xfs)
 				break;
@@ -1527,15 +1567,6 @@
 			break;
 
 		case FS_QueryXBitmaps8:
-			// convert to QueryXBitmaps16 request
-			{
-			fsQueryXBitmaps8Req *req = (fsQueryXBitmaps8Req *)buf;
-			U8 *p8 = (U8 *)(req + 1);
-			U16 *p16 = (U16 *)p8;
-			for (i = req->num_ranges; --i >= 0;)
-				p16[i] = ntohs(p8[i]);
-			}
-			// fall through
 		case FS_QueryXBitmaps16:
 			{
 			fsQueryXBitmaps16Req *req = (fsQueryXBitmaps16Req *)buf;
@@ -1544,6 +1575,24 @@
 			dprintf2("range=%d, nranges=%ld\n",
 				 req->range, req->num_ranges);
 
+			int item_size = (req->reqType == FS_QueryXExtents8)
+				        ? 1: 2;
+			int expected_size = sz_fsQueryXBitmaps8Req
+					    + req->num_ranges * item_size;
+
+			if (!check_length(sd, seqno, fsreq, expected_size))
+				break;
+
+			if (req->reqType == FS_QueryXBitmaps8) {
+				/*
+				 * Convert to QueryXBitmaps16 request
+				 */
+				U8 *p8 = (U8 *)(req + 1);
+				U16 *p16 = (U16 *)p8;
+				for (i = req->num_ranges; --i >= 0;)
+					p16[i] = ntohs(p8[i]);
+			}
+
 			XFSFont *xfs = findFont(req->fid, sd, seqno);
 			if (!xfs)
 				break;
