Blob Blame History Raw
diff -up patch-2.7.1/src/common.h.lineno-overflow patch-2.7.1/src/common.h
--- patch-2.7.1/src/common.h.lineno-overflow	2012-09-28 15:00:04.000000000 +0100
+++ patch-2.7.1/src/common.h	2015-01-20 14:47:37.262280623 +0000
@@ -39,6 +39,7 @@
 #elif HAVE_STDINT_H
 # include <stdint.h>
 #endif
+#include <intprops.h>
 
 #include <ctype.h>
 /* CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given
@@ -68,6 +69,9 @@
 
 typedef off_t lin;			/* must be signed */
 
+#define LINENUM_MIN TYPE_MINIMUM (lin)
+#define LINENUM_MAX TYPE_MAXIMUM (lin)
+
 /* globals */
 
 XTERN char *buf;			/* general purpose buffer */
diff -up patch-2.7.1/src/pch.c.lineno-overflow patch-2.7.1/src/pch.c
--- patch-2.7.1/src/pch.c.lineno-overflow	2015-01-20 14:46:49.533109967 +0000
+++ patch-2.7.1/src/pch.c	2015-01-20 14:47:37.264280630 +0000
@@ -1294,6 +1294,8 @@ another_hunk (enum diff difftype, bool r
 		      s++;
 		    scan_linenum (s, &p_ptrn_lines);
 		    p_ptrn_lines += 1 - p_first;
+		    if (p_ptrn_lines < 0)
+		      malformed ();
 		}
 		else if (p_first)
 		    p_ptrn_lines = 1;
@@ -1301,6 +1303,9 @@ another_hunk (enum diff difftype, bool r
 		    p_ptrn_lines = 0;
 		    p_first = 1;
 		}
+		if (p_first >= LINENUM_MAX - p_ptrn_lines ||
+		    p_ptrn_lines >= LINENUM_MAX - 6)
+		  malformed ();
 		p_max = p_ptrn_lines + 6;	/* we need this much at least */
 		while (p_max + 1 >= hunkmax)
 		    if (! grow_hunkmax ())
@@ -1370,6 +1375,8 @@ another_hunk (enum diff difftype, bool r
 		    while (! ISDIGIT (*s));
 		    scan_linenum (s, &p_repl_lines);
 		    p_repl_lines += 1 - p_newfirst;
+		    if (p_repl_lines < 0)
+		      malformed ();
 		  }
 		else if (p_newfirst)
 		  p_repl_lines = 1;
@@ -1378,6 +1385,9 @@ another_hunk (enum diff difftype, bool r
 		    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;
 		while (p_max + 1 >= hunkmax)
 		  if (! grow_hunkmax ())
@@ -1617,6 +1627,8 @@ another_hunk (enum diff difftype, bool r
 	    s = scan_linenum (s + 1, &p_ptrn_lines);
 	else
 	    p_ptrn_lines = 1;
+	if (p_first >= LINENUM_MAX - p_ptrn_lines)
+	  malformed ();
 	if (*s == ' ') s++;
 	if (*s != '+')
 	    malformed ();
@@ -1625,6 +1637,8 @@ another_hunk (enum diff difftype, bool r
 	    s = scan_linenum (s + 1, &p_repl_lines);
 	else
 	    p_repl_lines = 1;
+	if (p_newfirst >= LINENUM_MAX - p_repl_lines)
+	  malformed ();
 	if (*s == ' ') s++;
 	if (*s++ != '@')
 	    malformed ();
@@ -1640,6 +1654,8 @@ another_hunk (enum diff difftype, bool r
 	    p_first++;			/* do append rather than insert */
 	if (!p_repl_lines)
 	    p_newfirst++;
+	if (p_ptrn_lines >= LINENUM_MAX - (p_repl_lines + 1))
+	  malformed ();
 	p_max = p_ptrn_lines + p_repl_lines + 1;
 	while (p_max + 1 >= hunkmax)
 	    if (! grow_hunkmax ())
@@ -1776,6 +1792,8 @@ another_hunk (enum diff difftype, bool r
 	}
 	else
 	    p_ptrn_lines = (*s != 'a');
+	if (p_first >= LINENUM_MAX - p_ptrn_lines)
+	  malformed ();
 	hunk_type = *s;
 	if (hunk_type == 'a')
 	    p_first++;			/* do append rather than insert */
@@ -1784,17 +1802,23 @@ another_hunk (enum diff difftype, bool r
 	    scan_linenum (s + 1, &max);
 	else
 	    max = min;
+	if (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)
+	  malformed ();
+	if (p_ptrn_lines >= LINENUM_MAX - (p_repl_lines + 1))
+	  malformed ();
+	p_end = p_ptrn_lines + p_repl_lines + 1;
 	while (p_end + 1 >= hunkmax)
 	  if (! grow_hunkmax ())
 	    {
 	      p_end = -1;
 	      return -1;
 	    }
-	p_newfirst = min;
-	p_repl_lines = max - min + 1;
 	sprintf (buf, "*** %s,%s\n",
 		 format_linenum (numbuf0, p_first),
 		 format_linenum (numbuf1, p_first + p_ptrn_lines - 1));