untrusted comment: signature from openbsd 5.7 base secret key
RWSvUZXnw9gUb3l+tgZZQKsklOraYkbvz4oSif9fVFwKeDSdfx9yR9X5UbXbtDJ1E8uXRoyfS6iI8evpmVFkDBGTNVwF+mu9QA4=

OpenBSD 5.7 errata 12, Jul 26, 2015:

The patch utility could be made to invoke arbitrary commands via
the obsolete RCS support when processing a crafted input file.
This patch deletes the RCS support.

Apply by doing:
   signify -Vep /etc/signify/openbsd-57-base.pub -x 012_patch.patch.sig \
       -m - | (cd /usr/src && patch -p0)

And then rebuild and install the patch utility:
   cd /usr/src/usr.bin/patch
   make obj
   make
   make install

Index: usr.bin/patch/common.h
===================================================================
RCS file: /cvs/src/usr.bin/patch/common.h,v
retrieving revision 1.28
diff -u -p -r1.28 common.h
--- usr.bin/patch/common.h      25 Nov 2014 10:26:07 -0000      1.28
+++ usr.bin/patch/common.h      27 Jul 2015 00:22:37 -0000
@@ -41,10 +41,6 @@
#define BUFFERSIZE 1024
#define LINENUM_MAX LONG_MAX

-#define RCSSUFFIX ",v"
-#define CHECKOUT "co -l %s"
-#define RCSDIFF "rcsdiff %s > /dev/null"
-
#define ORIGEXT ".orig"
#define REJEXT ".rej"

Index: usr.bin/patch/inp.c
===================================================================
RCS file: /cvs/src/usr.bin/patch/inp.c,v
retrieving revision 1.43
diff -u -p -r1.43 inp.c
--- usr.bin/patch/inp.c 5 Feb 2015 12:59:57 -0000       1.43
+++ usr.bin/patch/inp.c 27 Jul 2015 00:22:37 -0000
@@ -132,7 +132,7 @@ static bool
plan_a(const char *filename)
{
       int             ifd, statfailed;
-       char            *p, *s, lbuf[MAXLINELEN];
+       char            *p, *s;
       struct stat     filestat;
       off_t           i;
       ptrdiff_t       sz;
@@ -162,67 +162,8 @@ plan_a(const char *filename)
               close(creat(filename, 0666));
               statfailed = stat(filename, &filestat);
       }
-       if (statfailed && check_only)
-               fatal("%s not found, -C mode, can't probe further\n", filename);
-       /* For nonexistent or read-only files, look for RCS versions.  */
-       if (statfailed ||
-           /* No one can write to it.  */
-           (filestat.st_mode & 0222) == 0 ||
-           /* I can't write to it.  */
-           ((filestat.st_mode & 0022) == 0 && filestat.st_uid != getuid())) {
-               char    *cs = NULL, *filebase, *filedir;
-               struct stat     cstat;
-
-               filebase = basename(filename);
-               filedir = dirname(filename);
-
-               /* Leave room in lbuf for the diff command.  */
-               s = lbuf + 20;
-
-#define try(f, a1, a2, a3) \
-       (snprintf(s, sizeof lbuf - 20, f, a1, a2, a3), stat(s, &cstat) == 0)
-
-               if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
-                   try("%s/RCS/%s%s", filedir, filebase, "") ||
-                   try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
-                       snprintf(buf, sizeof buf, CHECKOUT, filename);
-                       snprintf(lbuf, sizeof lbuf, RCSDIFF, filename);
-                       cs = "RCS";
-               } else if (statfailed)
-                       fatal("can't find %s\n", filename);
-               /*
-                * else we can't write to it but it's not under a version
-                * control system, so just proceed.
-                */
-               if (cs) {
-                       if (!statfailed) {
-                               if ((filestat.st_mode & 0222) != 0)
-                                       /* The owner can write to it.  */
-                                       fatal("file %s seems to be locked "
-                                           "by somebody else under %s\n",
-                                           filename, cs);
-                               /*
-                                * It might be checked out unlocked.  See if
-                                * it's safe to check out the default version
-                                * locked.
-                                */
-                               if (verbose)
-                                       say("Comparing file %s to default "
-                                           "%s version...\n",
-                                           filename, cs);
-                               if (system(lbuf))
-                                       fatal("can't check out file %s: "
-                                           "differs from default %s version\n",
-                                           filename, cs);
-                       }
-                       if (verbose)
-                               say("Checking out file %s from %s...\n",
-                                   filename, cs);
-                       if (system(buf) || stat(filename, &filestat))
-                               fatal("can't check out file %s from %s\n",
-                                   filename, cs);
-               }
-       }
+       if (statfailed)
+               fatal("can't find %s\n", filename);
       filemode = filestat.st_mode;
       if (!S_ISREG(filemode))
               fatal("%s is not a normal file--can't patch\n", filename);
Index: usr.bin/patch/patch.1
===================================================================
RCS file: /cvs/src/usr.bin/patch/patch.1,v
retrieving revision 1.28
diff -u -p -r1.28 patch.1
--- usr.bin/patch/patch.1       22 Nov 2014 15:49:28 -0000      1.28
+++ usr.bin/patch/patch.1       27 Jul 2015 00:22:37 -0000
@@ -478,15 +478,6 @@ file names or, for a non-context diff, t
.Dq index
file name, and choose the file name with the fewest path components,
the shortest basename, and the shortest total file name length (in that order).
-.It
-If no file exists,
-.Nm
-checks for the existence of the files in an RCS directory
-(using the appropriate suffix) using the criteria specified
-above.
-If found,
-.Nm
-will attempt to get or check out the file.
.It
If no suitable file was found to patch, the patch file is a context or
unified diff, and the old file was zero length, the new file name is
Index: usr.bin/patch/pch.c
===================================================================
RCS file: /cvs/src/usr.bin/patch/pch.c,v
retrieving revision 1.51
diff -u -p -r1.51 pch.c
--- usr.bin/patch/pch.c 5 Feb 2015 12:59:57 -0000       1.51
+++ usr.bin/patch/pch.c 27 Jul 2015 00:22:37 -0000
@@ -1457,17 +1457,8 @@ posix_name(const struct file_name *names
       }
       if (path == NULL && !assume_exists) {
               /*
-                * No files found, look for something we can checkout from
-                * RCS dirs.  Same order as above.
-                */
-               for (i = 0; i < MAX_FILE; i++) {
-                       if (names[i].path != NULL &&
-                           (path = checked_in(names[i].path)) != NULL)
-                               break;
-               }
-               /*
-                * Still no match?  Check to see if the diff could be creating
-                * a new file.
+                * No files found, check to see if the diff could be
+                * creating a new file.
                */
               if (path == NULL && ok_to_create_file &&
                   names[NEW_FILE].path != NULL)
@@ -1478,7 +1469,7 @@ posix_name(const struct file_name *names
}

static char *
-compare_names(const struct file_name *names, bool assume_exists, int phase)
+compare_names(const struct file_name *names, bool assume_exists)
{
       size_t min_components, min_baselen, min_len, tmp;
       char *best = NULL;
@@ -1495,9 +1486,7 @@ compare_names(const struct file_name *na
       min_components = min_baselen = min_len = SIZE_MAX;
       for (i = INDEX_FILE; i >= OLD_FILE; i--) {
               path = names[i].path;
-               if (path == NULL ||
-                   (phase == 1 && !names[i].exists && !assume_exists) ||
-                   (phase == 2 && checked_in(path) == NULL))
+               if (path == NULL || (!names[i].exists && !assume_exists))
                       continue;
               if ((tmp = num_components(path)) > min_components)
                       continue;
@@ -1528,17 +1517,12 @@ best_name(const struct file_name *names,
{
       char *best;

-       best = compare_names(names, assume_exists, 1);
-       if (best == NULL) {
-               best = compare_names(names, assume_exists, 2);
-               /*
-                * Still no match?  Check to see if the diff could be creating
-                * a new file.
-                */
-               if (best == NULL && ok_to_create_file &&
-                   names[NEW_FILE].path != NULL)
-                       best = names[NEW_FILE].path;
-       }
+       best = compare_names(names, assume_exists);
+
+       /* No match?  Check to see if the diff could be creating a new file. */
+       if (best == NULL && ok_to_create_file)
+               best = names[NEW_FILE].path;
+
       return best ? xstrdup(best) : NULL;
}

Index: usr.bin/patch/util.c
===================================================================
RCS file: /cvs/src/usr.bin/patch/util.c,v
retrieving revision 1.39
diff -u -p -r1.39 util.c
--- usr.bin/patch/util.c        16 Jan 2015 06:40:10 -0000      1.39
+++ usr.bin/patch/util.c        27 Jul 2015 00:22:37 -0000
@@ -388,30 +388,6 @@ fetchname(const char *at, bool *exists,
       return name;
}

-/*
- * Takes the name returned by fetchname and looks in RCS directory
- * for a checked in version.
- */
-char *
-checked_in(char *file)
-{
-       char            *filebase, *filedir, tmpbuf[PATH_MAX];
-       struct stat     filestat;
-
-       filebase = basename(file);
-       filedir = dirname(file);
-
-#define try(f, a1, a2, a3) \
-(snprintf(tmpbuf, sizeof tmpbuf, f, a1, a2, a3), stat(tmpbuf, &filestat) == 0)
-
-       if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
-           try("%s/RCS/%s%s", filedir, filebase, "") ||
-           try("%s/%s%s", filedir, filebase, RCSSUFFIX))
-               return file;
-
-       return NULL;
-}
-
void
version(void)
{
Index: usr.bin/patch/util.h
===================================================================
RCS file: /cvs/src/usr.bin/patch/util.h,v
retrieving revision 1.16
diff -u -p -r1.16 util.h
--- usr.bin/patch/util.h        13 Dec 2014 10:31:07 -0000      1.16
+++ usr.bin/patch/util.h        27 Jul 2015 00:22:37 -0000
@@ -27,7 +27,6 @@
 */

char           *fetchname(const char *, bool *, int);
-char           *checked_in(char *);
int            backup_file(const char *);
int            move_file(const char *, const char *);
int            copy_file(const char *, const char *);