Apply by doing:
	cd /usr/src
	patch -p0 < 011_cvs3.patch

And then rebuild and install cvs:
	cd gnu/usr.bin/cvs
	make -f Makefile.bsd-wrapper obj
	make -f Makefile.bsd-wrapper
	make -f Makefile.bsd-wrapper install

Index: gnu/usr.bin/cvs/lib/xsize.h
===================================================================
RCS file: gnu/usr.bin/cvs/lib/xsize.h
diff -N gnu/usr.bin/cvs/lib/xsize.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/usr.bin/cvs/lib/xsize.h	9 Jun 2004 18:30:14 -0000
@@ -0,0 +1,108 @@
+/* xsize.h -- Checked size_t computations.
+
+   Copyright (C) 2003 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _XSIZE_H
+#define _XSIZE_H
+
+/* Get size_t.  */
+#include <stddef.h>
+
+/* Get SIZE_MAX.  */
+#include <limits.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+/* The size of memory objects is often computed through expressions of
+   type size_t. Example:
+      void* p = malloc (header_size + n * element_size).
+   These computations can lead to overflow.  When this happens, malloc()
+   returns a piece of memory that is way too small, and the program then
+   crashes while attempting to fill the memory.
+   To avoid this, the functions and macros in this file check for overflow.
+   The convention is that SIZE_MAX represents overflow.
+   malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
+   implementation that uses mmap --, it's recommended to use size_overflow_p()
+   or size_in_bounds_p() before invoking malloc().
+   The example thus becomes:
+      size_t size = xsum (header_size, xtimes (n, element_size));
+      void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
+*/
+
+/* Convert an arbitrary value >= 0 to type size_t.  */
+#define xcast_size_t(N) \
+  ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
+
+/* Sum of two sizes, with overflow check.  */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum (size_t size1, size_t size2)
+{
+  size_t sum = size1 + size2;
+  return (sum >= size1 ? sum : SIZE_MAX);
+}
+
+/* Sum of three sizes, with overflow check.  */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum3 (size_t size1, size_t size2, size_t size3)
+{
+  return xsum (xsum (size1, size2), size3);
+}
+
+/* Sum of four sizes, with overflow check.  */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
+{
+  return xsum (xsum (xsum (size1, size2), size3), size4);
+}
+
+/* Maximum of two sizes, with overflow check.  */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xmax (size_t size1, size_t size2)
+{
+  /* No explicit check is needed here, because for any n:
+     max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX.  */
+  return (size1 >= size2 ? size1 : size2);
+}
+
+/* Multiplication of a count with an element size, with overflow check.
+   The count must be >= 0 and the element size must be > 0.
+   This is a macro, not an inline function, so that it works correctly even
+   when N is of a wider tupe and N > SIZE_MAX.  */
+#define xtimes(N, ELSIZE) \
+  ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
+
+/* Check for overflow.  */
+#define size_overflow_p(SIZE) \
+  ((SIZE) == SIZE_MAX)
+/* Check against overflow.  */
+#define size_in_bounds_p(SIZE) \
+  ((SIZE) != SIZE_MAX)
+
+#endif /* _XSIZE_H */
Index: gnu/usr.bin/cvs/src/commit.c
===================================================================
RCS file: /home/cvs/openbsd/src/gnu/usr.bin/cvs/src/commit.c,v
retrieving revision 1.18
diff -u -r1.18 commit.c
--- gnu/usr.bin/cvs/src/commit.c	28 Sep 2001 23:26:33 -0000	1.18
+++ gnu/usr.bin/cvs/src/commit.c	9 Jun 2004 18:30:14 -0000
@@ -472,7 +472,12 @@
 	   operate on, and only work with those files in the future.
 	   This saves time--we don't want to search the file system
 	   of the working directory twice.  */
-	find_args.argv = (char **) xmalloc (find_args.argc * sizeof (char **));
+	if (size_overflow_p (xtimes (find_args.argc, sizeof (char **))))
+	{
+	    find_args.argc = 0;
+	    return 0;
+	}
+	find_args.argv = xmalloc (xtimes (find_args.argc, sizeof (char **)));
 	find_args.argc = 0;
 	walklist (find_args.ulist, copy_ulist, &find_args);
 
Index: gnu/usr.bin/cvs/src/cvs.h
===================================================================
RCS file: /home/cvs/openbsd/src/gnu/usr.bin/cvs/src/cvs.h,v
retrieving revision 1.24
diff -u -r1.24 cvs.h
--- gnu/usr.bin/cvs/src/cvs.h	28 Sep 2001 23:26:33 -0000	1.24
+++ gnu/usr.bin/cvs/src/cvs.h	9 Jun 2004 18:30:14 -0000
@@ -41,6 +41,10 @@
 #include "popen.h"
 #endif
 
+/* Begin GNULIB headers.  */
+#include "xsize.h"
+/* End GNULIB headers.  */
+
 #ifdef STDC_HEADERS
 #include <stdlib.h>
 #else
Index: gnu/usr.bin/cvs/src/filesubr.c
===================================================================
RCS file: /home/cvs/openbsd/src/gnu/usr.bin/cvs/src/filesubr.c,v
retrieving revision 1.2
diff -u -r1.2 filesubr.c
--- gnu/usr.bin/cvs/src/filesubr.c	9 Dec 2002 00:45:34 -0000	1.2
+++ gnu/usr.bin/cvs/src/filesubr.c	9 Jun 2004 18:30:14 -0000
@@ -965,8 +965,14 @@
     char ***pargv;
 {
     int i;
+    if (size_overflow_p (xtimes (argc, sizeof (char *)))) {
+	*pargc = 0;
+	*pargv = NULL;
+	error (0, 0, "expand_wild: too many arguments");
+	return;
+    }
     *pargc = argc;
-    *pargv = (char **) xmalloc (argc * sizeof (char *));
+    *pargv = xmalloc (xtimes (argc, sizeof (char *)));
     for (i = 0; i < argc; ++i)
 	(*pargv)[i] = xstrdup (argv[i]);
 }
Index: gnu/usr.bin/cvs/src/history.c
===================================================================
RCS file: /home/cvs/openbsd/src/gnu/usr.bin/cvs/src/history.c,v
retrieving revision 1.1.1.14
diff -u -r1.1.1.14 history.c
--- gnu/usr.bin/cvs/src/history.c	28 Sep 2001 22:45:37 -0000	1.1.1.14
+++ gnu/usr.bin/cvs/src/history.c	9 Jun 2004 18:30:14 -0000
@@ -414,8 +414,11 @@
 		working = 1;
 		break;
 	    case 'X':			/* Undocumented debugging flag */
+#ifdef DEBUG
 		histfile = optarg;
+#endif
 		break;
+
 	    case 'D':			/* Since specified date */
 		if (*since_rev || *since_tag || *backto)
 		{
@@ -891,9 +894,13 @@
 {
     if (user_count == user_max)
     {
-	user_max += USER_INCREMENT;
-	user_list = (char **) xrealloc ((char *) user_list,
-					(int) user_max * sizeof (char *));
+	user_max = xsum (user_max, USER_INCREMENT);
+	if (size_overflow_p (xtimes (user_max, sizeof (char *))))
+	{
+	    error (0, 0, "save_user: too many users");
+	    return;
+	}
+	user_list = xrealloc (user_list, xtimes (user_max, sizeof (char *)));
     }
     user_list[user_count++] = xstrdup (name);
 }
@@ -921,9 +928,13 @@
 
     if (file_count == file_max)
     {
-	file_max += FILE_INCREMENT;
-	file_list = (struct file_list_str *) xrealloc ((char *) file_list,
-						   file_max * sizeof (*fl));
+	file_max = xsum (file_max, FILE_INCREMENT);
+	if (size_overflow_p (xtimes (file_max, sizeof (*fl))))
+	{
+	    error (0, 0, "save_file: too many files");
+	    return;
+	}
+	file_list = xrealloc (file_list, xtimes (file_max, sizeof (*fl)));
     }
     fl = &file_list[file_count++];
     fl->l_file = cp = xmalloc (strlen (dir) + strlen (name) + 2);
@@ -962,9 +973,13 @@
 {
     if (mod_count == mod_max)
     {
-	mod_max += MODULE_INCREMENT;
-	mod_list = (char **) xrealloc ((char *) mod_list,
-				       mod_max * sizeof (char *));
+	mod_max = xsum (mod_max, MODULE_INCREMENT);
+	if (size_overflow_p (xtimes (mod_max, sizeof (char *))))
+	{
+	    error (0, 0, "save_module: too many modules");
+	    return;
+	}
+	mod_list = xrealloc (mod_list, xtimes (mod_max, sizeof (char *)));
     }
     mod_list[mod_count++] = xstrdup (module);
 }
Index: gnu/usr.bin/cvs/src/server.c
===================================================================
RCS file: /home/cvs/openbsd/src/gnu/usr.bin/cvs/src/server.c,v
retrieving revision 1.29.2.1
diff -u -r1.29.2.1 server.c
--- gnu/usr.bin/cvs/src/server.c	20 May 2004 19:23:02 -0000	1.29.2.1
+++ gnu/usr.bin/cvs/src/server.c	9 Jun 2004 18:30:14 -0000
@@ -930,7 +930,7 @@
     int i;
     char *p;
 
-    if (lim < 0)
+    if (lim < 0 || lim > 10000)
 	return;
     p = malloc (strlen (server_temp_dir) + 2 * lim + 10);
     if (p == NULL)
@@ -1635,8 +1635,7 @@
     char *cp;
     char *timefield;
 
-    if (error_pending ())
-	return;
+    if (error_pending ()) return;
 
     if (outside_dir (arg))
 	return;
@@ -1650,7 +1649,16 @@
 	    && strlen (arg) == cp - name
 	    && strncmp (arg, name, cp - name) == 0)
 	{
-	    timefield = strchr (cp + 1, '/') + 1;
+	    if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0')
+	    {
+		/* We didn't find the record separator or it is followed by
+		 * the end of the string, so just exit.
+		 */
+		if (alloc_pending (80))
+		    sprintf (pending_error_text,
+		             "E Malformed Entry encountered.");
+		return;
+	    }
 	    /* If the time field is not currently empty, then one of
 	     * serve_modified, serve_is_modified, & serve_unchanged were
 	     * already called for this file.  We would like to ignore the
@@ -1697,8 +1705,7 @@
     /* Have we found this file in "entries" yet.  */
     int found;
 
-    if (error_pending ())
-	return;
+    if (error_pending ()) return;
 
     if (outside_dir (arg))
 	return;
@@ -1713,7 +1720,16 @@
 	    && strlen (arg) == cp - name
 	    && strncmp (arg, name, cp - name) == 0)
 	{
-	    timefield = strchr (cp + 1, '/') + 1;
+	    if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0')
+	    {
+		/* We didn't find the record separator or it is followed by
+		 * the end of the string, so just exit.
+		 */
+		if (alloc_pending (80))
+		    sprintf (pending_error_text,
+		             "E Malformed Entry encountered.");
+		return;
+	    }
 	    /* If the time field is not currently empty, then one of
 	     * serve_modified, serve_is_modified, & serve_unchanged were
 	     * already called for this file.  We would like to ignore the
@@ -1798,8 +1814,29 @@
 {
     struct an_entry *p;
     char *cp;
+    int i = 0;
     if (error_pending()) return;
-    p = (struct an_entry *) malloc (sizeof (struct an_entry));
+
+    /* Verify that the entry is well-formed.  This can avoid problems later.
+     * At the moment we only check that the Entry contains five slashes in
+     * approximately the correct locations since some of the code makes
+     * assumptions about this.
+     */
+    cp = arg;
+    if (*cp == 'D') cp++;
+    while (i++ < 5)
+    {
+      if (!cp || *cp != '/')
+      {
+          if (alloc_pending (80))
+              sprintf (pending_error_text,
+                       "E protocol error: Malformed Entry");
+           return;
+      }
+    cp = strchr (cp + 1, '/');
+    }
+
+    p = xmalloc (sizeof (struct an_entry));
     if (p == NULL)
     {
 	pending_error = ENOMEM;
@@ -2031,6 +2068,9 @@
     {
 	char *cp;
 
+	if (!data[0])
+	    goto error;
+
 	if (strchr (data, '+'))
 	    goto error;
 
@@ -2162,6 +2202,15 @@
     char *p;
     
     if (error_pending()) return;
+
+    if (argument_count >= 10000)
+    {
+       if (alloc_pending (80))
+           sprintf (pending_error_text,
+                    "E Protocol error: too many arguments");
+       return;
+    }
+
     
     if (argument_vector_size <= argument_count)
     {
@@ -2192,6 +2241,15 @@
     char *p;
     
     if (error_pending()) return;
+
+    if (argument_count <= 1)
+    {
+        if (alloc_pending (80))
+            sprintf (pending_error_text,
+                     "E Protocol error: called argumentx without prior call to argument");
+        return;
+    }
+
     
     p = argument_vector[argument_count - 1];
     p = realloc (p, strlen (p) + 1 + strlen (arg) + 1);
@@ -2549,7 +2607,7 @@
                     save some code here...  -kff */
 
                  /* Chop newline by hand, for strcmp()'s sake. */
-                 if (linebuf[num_red - 1] == '\n')
+                 if (num_red > 0 && linebuf[num_red - 1] == '\n')
                      linebuf[num_red - 1] = '\0';
 
                  if (strcmp (linebuf, CVS_Username) == 0)
@@ -2604,7 +2662,7 @@
          while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
          {
              /* Chop newline by hand, for strcmp()'s sake. */
-             if (linebuf[num_red - 1] == '\n')
+             if (num_red > 0 && linebuf[num_red - 1] == '\n')
                  linebuf[num_red - 1] = '\0';
            
              if (strcmp (linebuf, CVS_Username) == 0)
Index: gnu/usr.bin/cvs/src/wrapper.c
===================================================================
RCS file: /home/cvs/openbsd/src/gnu/usr.bin/cvs/src/wrapper.c,v
retrieving revision 1.1.1.11
diff -u -r1.1.1.11 wrapper.c
--- gnu/usr.bin/cvs/src/wrapper.c	28 Sep 2001 22:45:39 -0000	1.1.1.11
+++ gnu/usr.bin/cvs/src/wrapper.c	9 Jun 2004 18:30:14 -0000
@@ -246,6 +246,30 @@
 #endif /* SERVER_SUPPORT || CLIENT_SUPPORT */
 
 /*
+ * Remove fmt str specifier other than %% or %s. And allow
+ * only max_s %s specifiers
+ */
+wrap_clean_fmt_str(char *fmt, int max_s)
+{
+    while (*fmt) {
+	if (fmt[0] == '%' && fmt[1])
+	{
+	    if (fmt[1] == '%') 
+		fmt++;
+	    else
+		if (fmt[1] == 's' && max_s > 0)
+		{
+		    max_s--;
+		    fmt++;
+		} else 
+		    *fmt = ' ';
+	}
+	fmt++;
+    }
+    return;
+}
+
+/*
  * Open a file and read lines, feeding each line to a line parser. Arrange
  * for keeping a temporary list of wrappers at the end, if the "temp"
  * argument is set.
@@ -569,9 +593,8 @@
     args = xmalloc (strlen (e->tocvsFilter)
 		    + strlen (fileName)
 		    + strlen (buf));
-    /* FIXME: sprintf will blow up if the format string contains items other
-       than %s, or contains too many %s's.  We should instead be parsing
-       e->tocvsFilter ourselves and giving a real error.  */
+
+    wrap_clean_fmt_str(e->tocvsFilter, 2);
     sprintf (args, e->tocvsFilter, fileName, buf);
     run_setup (args);
     run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY );
@@ -603,9 +626,8 @@
 
     args = xmalloc (strlen (e->fromcvsFilter)
 		    + strlen (fileName));
-    /* FIXME: sprintf will blow up if the format string contains items other
-       than %s, or contains too many %s's.  We should instead be parsing
-       e->fromcvsFilter ourselves and giving a real error.  */
+
+    wrap_clean_fmt_str(e->fromcvsFilter, 1);
     sprintf (args, e->fromcvsFilter, fileName);
     run_setup (args);
     run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL );