diff options
author | Andreas Gruenbacher <agruen@linbit.com> | 2014-11-30 20:56:46 +0100 |
---|---|---|
committer | Andreas Gruenbacher <agruen@linbit.com> | 2014-11-30 20:56:46 +0100 |
commit | 44a987e02f04b9d81a0db4a611145cad1093a2d3 (patch) | |
tree | f0a3ee6da4bdebe0bb54305e2dcfa94f66b3a487 | |
parent | f22e47d873ac6b7abbc31fdedc51019766ee7c86 (diff) | |
download | patch-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.conf | 1 | ||||
-rw-r--r-- | src/common.h | 4 | ||||
-rw-r--r-- | src/pch.c | 30 |
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 */ @@ -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)); |