summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@linbit.com>2014-11-30 20:56:46 +0100
committerAndreas Gruenbacher <agruen@linbit.com>2014-11-30 20:56:46 +0100
commit44a987e02f04b9d81a0db4a611145cad1093a2d3 (patch)
treef0a3ee6da4bdebe0bb54305e2dcfa94f66b3a487
parentf22e47d873ac6b7abbc31fdedc51019766ee7c86 (diff)
downloadpatch-44a987e02f04b9d81a0db4a611145cad1093a2d3.tar.gz
Add line number overflow checking
* bootstrap.conf: use intprops module. * src/common.h: Define LINENUM_MIN and LINENUM_MAX macros. * src/pch.c (another_hunk): Add line number overflow checking. Based on Robert C. Seacord's INT32-C document for integer overflow checking and Tobias Stoeckmann's "integer overflows and oob memory access" patch for FreeBSD.
-rw-r--r--bootstrap.conf1
-rw-r--r--src/common.h4
-rw-r--r--src/pch.c30
3 files changed, 32 insertions, 3 deletions
diff --git a/bootstrap.conf b/bootstrap.conf
index d6074b3..783f98a 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -36,6 +36,7 @@ gitlog-to-changelog
git-version-gen
hash
ignore-value
+intprops
largefile
lchmod
linked-list
diff --git a/src/common.h b/src/common.h
index a66e55f..9e355fe 100644
--- a/src/common.h
+++ b/src/common.h
@@ -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 --git a/src/pch.c b/src/pch.c
index abfe87a..55e1504 100644
--- a/src/pch.c
+++ b/src/pch.c
@@ -1319,6 +1319,8 @@ another_hunk (enum diff difftype, bool rev)
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;
@@ -1326,6 +1328,9 @@ another_hunk (enum diff difftype, bool rev)
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 ())
@@ -1395,6 +1400,8 @@ another_hunk (enum diff difftype, bool rev)
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;
@@ -1403,6 +1410,9 @@ another_hunk (enum diff difftype, bool rev)
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 ())
@@ -1642,6 +1652,8 @@ another_hunk (enum diff difftype, bool rev)
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 ();
@@ -1650,6 +1662,8 @@ another_hunk (enum diff difftype, bool rev)
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 ();
@@ -1667,6 +1681,8 @@ another_hunk (enum diff difftype, bool rev)
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 ())
@@ -1803,6 +1819,8 @@ another_hunk (enum diff difftype, bool rev)
}
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 */
@@ -1811,17 +1829,23 @@ another_hunk (enum diff difftype, bool rev)
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));