Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/patch Avoid coredumps when the linenumbers in the hu...



details:   https://anonhg.NetBSD.org/src/rev/a566d2b25e9d
branches:  trunk
changeset: 334004:a566d2b25e9d
user:      christos <christos%NetBSD.org@localhost>
date:      Wed Nov 26 00:31:32 2014 +0000

description:
Avoid coredumps when the linenumbers in the hunks turn negative.
From: http://marc.info/?l=openbsd-tech&m=141693055412785

XXX: pullup 7

diffstat:

 usr.bin/patch/common.h |    3 +-
 usr.bin/patch/pch.c    |  102 ++++++++++++++++++++++++++++++++----------------
 2 files changed, 69 insertions(+), 36 deletions(-)

diffs (227 lines):

diff -r 613c665918c8 -r a566d2b25e9d usr.bin/patch/common.h
--- a/usr.bin/patch/common.h    Tue Nov 25 19:54:08 2014 +0000
+++ b/usr.bin/patch/common.h    Wed Nov 26 00:31:32 2014 +0000
@@ -1,7 +1,7 @@
 /*
  * $OpenBSD: common.h,v 1.26 2006/03/11 19:41:30 otto Exp $
  * $DragonFly: src/usr.bin/patch/common.h,v 1.5 2008/08/10 23:50:12 joerg Exp $
- * $NetBSD: common.h,v 1.19 2008/09/19 18:33:34 joerg Exp $
+ * $NetBSD: common.h,v 1.20 2014/11/26 00:31:32 christos Exp $
  */
 
 /*
@@ -43,6 +43,7 @@
 #define INITHUNKMAX 125                /* initial dynamic allocation size */
 #define MAXLINELEN 8192
 #define BUFFERSIZE 1024
+#define LINENUM_MAX LONG_MAX
 
 #define SCCSPREFIX "s."
 #define GET "get -e %s"
diff -r 613c665918c8 -r a566d2b25e9d usr.bin/patch/pch.c
--- a/usr.bin/patch/pch.c       Tue Nov 25 19:54:08 2014 +0000
+++ b/usr.bin/patch/pch.c       Wed Nov 26 00:31:32 2014 +0000
@@ -1,7 +1,7 @@
 /*
  * $OpenBSD: pch.c,v 1.37 2007/09/02 15:19:33 deraadt Exp $
  * $DragonFly: src/usr.bin/patch/pch.c,v 1.6 2008/08/10 23:35:40 joerg Exp $
- * $NetBSD: pch.c,v 1.25 2013/01/29 09:30:11 wiz Exp $
+ * $NetBSD: pch.c,v 1.26 2014/11/26 00:31:32 christos Exp $
  */
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: pch.c,v 1.25 2013/01/29 09:30:11 wiz Exp $");
+__RCSID("$NetBSD: pch.c,v 1.26 2014/11/26 00:31:32 christos Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -455,6 +455,28 @@
        /* about as informative as "Syntax error" in C */
 }
 
+static LINENUM
+getlinenum(const char *s)
+{
+       LINENUM l = (LINENUM)atol(s);
+       if (l < 0) {
+               l = 0;
+               malformed();
+       }
+       return l;
+}
+
+static LINENUM
+getskiplinenum(char **p)
+{
+       char *s = *p;
+       LINENUM l = getlinenum(s);
+       while (isdigit((unsigned char)*s))
+               s++;
+       *p = s;
+       return l;
+}
+
 /*
  * True if the line has been discarded (i.e., it is a line saying
  *  "\ No newline at end of file".)
@@ -582,21 +604,24 @@
                                        malformed();
                                if (strnEQ(s, "0,0", 3))
                                        memmove(s, s + 2, strlen(s + 2) + 1);
-                               p_first = (LINENUM) atol(s);
-                               while (isdigit((unsigned char)*s))
-                                       s++;
+                               p_first = getskiplinenum(&s);
                                if (*s == ',') {
                                        for (; *s && !isdigit((unsigned char)*s); s++)
                                                ;
                                        if (!*s)
                                                malformed();
-                                       p_ptrn_lines = ((LINENUM) atol(s)) - p_first + 1;
+                                       p_ptrn_lines = (getlinenum(s)) - p_first + 1;
+                                       if (p_ptrn_lines < 0)
+                                               malformed();
                                } else if (p_first)
                                        p_ptrn_lines = 1;
                                else {
                                        p_ptrn_lines = 0;
                                        p_first = 1;
                                }
+                               if (p_first <= LINENUM_MAX - p_ptrn_lines ||
+                                   p_ptrn_lines <= LINENUM_MAX - 6)
+                                       malformed();
 
                                /* we need this much at least */
                                p_max = p_ptrn_lines + 6;
@@ -649,22 +674,25 @@
                                                ;
                                        if (!*s)
                                                malformed();
-                                       p_newfirst = (LINENUM) atol(s);
-                                       while (isdigit((unsigned char)*s))
-                                               s++;
+                                       p_newfirst = getskiplinenum(&s);
                                        if (*s == ',') {
                                                for (; *s && !isdigit((unsigned char)*s); s++)
                                                        ;
                                                if (!*s)
                                                        malformed();
-                                               p_repl_lines = ((LINENUM) atol(s)) -
+                                               p_repl_lines = (getlinenum(s)) -
                                                    p_newfirst + 1;
+                                               if (p_repl_lines < 0)
+                                                       malformed();
                                        } else if (p_newfirst)
                                                p_repl_lines = 1;
                                        else {
                                                p_repl_lines = 0;
                                                p_newfirst = 1;
                                        }
+                                       if (p_newfirst >= LINENUM_MAX - p_repl_lines ||
+                                           p_repl_lines >= LINENUM_MAX - p_end)
+                                               malformed();
                                        p_max = p_repl_lines + p_end;
                                        if (p_max > MAXHUNKSIZE)
                                                fatal("hunk too large (%ld lines) at line %ld: %s",
@@ -857,32 +885,32 @@
                s = buf + 4;
                if (!*s)
                        malformed();
-               p_first = (LINENUM) atol(s);
-               while (isdigit((unsigned char)*s))
-                       s++;
+               p_first = getskiplinenum(&s);
                if (*s == ',') {
-                       p_ptrn_lines = (LINENUM) atol(++s);
-                       while (isdigit((unsigned char)*s))
-                               s++;
+                       s++;
+                       p_ptrn_lines = getskiplinenum(&s);
                } else
                        p_ptrn_lines = 1;
+               if (p_first >= LINENUM_MAX - p_ptrn_lines)
+                       malformed();
                if (*s == ' ')
                        s++;
                if (*s != '+' || !*++s)
                        malformed();
-               p_newfirst = (LINENUM) atol(s);
-               while (isdigit((unsigned char)*s))
-                       s++;
+               p_newfirst = getskiplinenum(&s);
                if (*s == ',') {
-                       p_repl_lines = (LINENUM) atol(++s);
-                       while (isdigit((unsigned char)*s))
-                               s++;
+                       s++;
+                       p_repl_lines = getskiplinenum(&s);
                } else
                        p_repl_lines = 1;
                if (*s == ' ')
                        s++;
                if (*s != '@')
                        malformed();
+               if (p_first >= LINENUM_MAX - p_ptrn_lines ||
+                   p_newfirst > LINENUM_MAX - p_repl_lines ||
+                   p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
+                       malformed();
                if (!p_ptrn_lines)
                        p_first++;      /* do append rather than insert */
                p_max = p_ptrn_lines + p_repl_lines + 1;
@@ -1022,35 +1050,39 @@
                        next_intuit_at(line_beginning, p_input_line);
                        return false;
                }
-               p_first = (LINENUM) atol(buf);
-               for (s = buf; isdigit((unsigned char)*s); s++)
-                       ;
+               s = buf;
+               p_first = getskiplinenum(&s);
                if (*s == ',') {
-                       p_ptrn_lines = (LINENUM) atol(++s) - p_first + 1;
-                       while (isdigit((unsigned char)*s))
-                               s++;
+                       s++;
+                       p_ptrn_lines = getskiplinenum(&s) - p_first + 1;
                } else
                        p_ptrn_lines = (*s != 'a');
-               hunk_type = *s;
+               if (p_first >= LINENUM_MAX - p_ptrn_lines)
+                       malformed();
+               hunk_type = *s++;
                if (hunk_type == 'a')
                        p_first++;      /* do append rather than insert */
-               min = (LINENUM) atol(++s);
-               for (; isdigit((unsigned char)*s); s++)
-                       ;
+               min = getskiplinenum(&s);
                if (*s == ',')
-                       max = (LINENUM) atol(++s);
+                       max = getlinenum(++s);
                else
                        max = min;
+               if (min < 0 || min > max || max - min == LINENUM_MAX)
+                       malformed();
                if (hunk_type == 'd')
                        min++;
                p_end = p_ptrn_lines + 1 + max - min + 1;
+               p_newfirst = min;
+               p_repl_lines = max - min + 1;
+               if (p_newfirst > LINENUM_MAX - p_repl_lines ||
+                   p_ptrn_lines >= LINENUM_MAX - p_repl_lines - 1)
+                       malformed();
+               p_end = p_ptrn_lines + p_repl_lines + 1;
                if (p_end > MAXHUNKSIZE)
                        fatal("hunk too large (%ld lines) at line %ld: %s",
                            p_end, p_input_line, buf);
                while (p_end >= hunkmax)
                        grow_hunkmax();
-               p_newfirst = min;
-               p_repl_lines = max - min + 1;
                snprintf(buf, buf_len, "*** %ld,%ld\n", p_first,
                    p_first + p_ptrn_lines - 1);
                p_line[0] = savestr(buf);



Home | Main Index | Thread Index | Old Index