Module Name: src Committed By: martin Date: Fri Nov 28 09:09:19 UTC 2014
Modified Files: src/usr.bin/patch [netbsd-7]: common.h pch.c Log Message: Pull up following revision(s) (requested by christos in ticket #270): usr.bin/patch/common.h: revision 1.20 usr.bin/patch/pch.c: revision 1.26 usr.bin/patch/pch.c: revision 1.27 Avoid coredumps when the linenumbers in the hunks turn negative. >From OpenBSD. PR/49422: Ryo ONODERA: patch(1) cannot handle context diffs To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.19.38.1 src/usr.bin/patch/common.h cvs rdiff -u -r1.25 -r1.25.8.1 src/usr.bin/patch/pch.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/patch/common.h diff -u src/usr.bin/patch/common.h:1.19 src/usr.bin/patch/common.h:1.19.38.1 --- src/usr.bin/patch/common.h:1.19 Fri Sep 19 18:33:34 2008 +++ src/usr.bin/patch/common.h Fri Nov 28 09:09:19 2014 @@ -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.19.38.1 2014/11/28 09:09:19 martin 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" Index: src/usr.bin/patch/pch.c diff -u src/usr.bin/patch/pch.c:1.25 src/usr.bin/patch/pch.c:1.25.8.1 --- src/usr.bin/patch/pch.c:1.25 Tue Jan 29 09:30:11 2013 +++ src/usr.bin/patch/pch.c Fri Nov 28 09:09:19 2014 @@ -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.25.8.1 2014/11/28 09:09:19 martin 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.25.8.1 2014/11/28 09:09:19 martin Exp $"); #include <sys/types.h> #include <sys/stat.h> @@ -455,6 +455,28 @@ malformed(void) /* 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 @@ another_hunk(void) 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 @@ another_hunk(void) ; 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 @@ hunk_done: 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 @@ hunk_done: 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);