Use ssize_t instead of short for line lengths
authortb <tb@openbsd.org>
Wed, 12 Jul 2023 11:26:13 +0000 (11:26 +0000)
committertb <tb@openbsd.org>
Wed, 12 Jul 2023 11:26:13 +0000 (11:26 +0000)
sthen hit a binary patch containing a 'line' of length > 32kB. This made
the short used for storing the line length wrap and resulted in a buffer
underflow and segfault.  This uses a larger type, which doesn't actually
fix the problem, but makes it much less likely to be hit.

ok florian otto sthen

usr.bin/patch/patch.c
usr.bin/patch/pch.c
usr.bin/patch/pch.h

index a25cb0a..a9740f0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: patch.c,v 1.71 2022/08/03 07:30:37 op Exp $   */
+/*     $OpenBSD: patch.c,v 1.72 2023/07/12 11:26:13 tb Exp $   */
 
 /*
  * patch - a program to apply diffs to original files
@@ -99,7 +99,7 @@ static void   copy_till(LINENUM, bool);
 static void    spew_output(void);
 static void    dump_line(LINENUM, bool);
 static bool    patch_match(LINENUM, LINENUM, LINENUM);
-static bool    similar(const char *, const char *, int);
+static bool    similar(const char *, const char *, ssize_t);
 static __dead void usage(void);
 
 /* true if -E was specified on command line.  */
@@ -1012,7 +1012,7 @@ patch_match(LINENUM base, LINENUM offset, LINENUM fuzz)
        LINENUM         pat_lines = pch_ptrn_lines() - fuzz;
        const char      *ilineptr;
        const char      *plineptr;
-       short           plinelen;
+       ssize_t         plinelen;
 
        for (iline = base + offset + fuzz; pline <= pat_lines; pline++, iline++) {
                ilineptr = ifetch(iline, offset >= 0);
@@ -1048,7 +1048,7 @@ patch_match(LINENUM base, LINENUM offset, LINENUM fuzz)
  * Do two lines match with canonicalized white space?
  */
 static bool
-similar(const char *a, const char *b, int len)
+similar(const char *a, const char *b, ssize_t len)
 {
        while (len) {
                if (isspace((unsigned char)*b)) { /* whitespace (or \n) to match? */
index 23b0b57..af1af7a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pch.c,v 1.63 2022/12/26 19:16:02 jmc Exp $    */
+/*     $OpenBSD: pch.c,v 1.64 2023/07/12 11:26:13 tb Exp $     */
 
 /*
  * patch - a program to apply diffs to original files
@@ -56,7 +56,7 @@ static LINENUM        p_end = -1;     /* last line in hunk */
 static LINENUM p_max;          /* max allowed value of p_end */
 static LINENUM p_context = 3;  /* # of context lines */
 static char    **p_line = NULL;/* the text of the hunk */
-static short   *p_len = NULL;  /* length of each line */
+static ssize_t *p_len = NULL;  /* length of each line */
 static char    *p_char = NULL; /* +, -, and ! */
 static int     hunkmax = INITHUNKMAX;  /* size of above arrays to begin with */
 static int     p_indent;       /* indent to patch */
@@ -127,7 +127,7 @@ set_hunkmax(void)
        if (p_line == NULL)
                p_line = calloc((size_t) hunkmax, sizeof(char *));
        if (p_len == NULL)
-               p_len = calloc((size_t) hunkmax, sizeof(short));
+               p_len = calloc((size_t) hunkmax, sizeof(ssize_t));
        if (p_char == NULL)
                p_char = calloc((size_t) hunkmax, sizeof(char));
 }
@@ -140,7 +140,7 @@ grow_hunkmax(void)
 {
        int             new_hunkmax;
        char            **new_p_line;
-       short           *new_p_len;
+       ssize_t         *new_p_len;
        char            *new_p_char;
 
        new_hunkmax = hunkmax * 2;
@@ -152,7 +152,7 @@ grow_hunkmax(void)
        if (new_p_line == NULL)
                free(p_line);
 
-       new_p_len = reallocarray(p_len, new_hunkmax, sizeof(short));
+       new_p_len = reallocarray(p_len, new_hunkmax, sizeof(ssize_t));
        if (new_p_len == NULL)
                free(p_len);
 
@@ -1192,7 +1192,7 @@ bool
 pch_swap(void)
 {
        char    **tp_line;      /* the text of the hunk */
-       short   *tp_len;        /* length of each line */
+       ssize_t *tp_len;        /* length of each line */
        char    *tp_char;       /* +, -, and ! */
        LINENUM i;
        LINENUM n;
@@ -1349,7 +1349,7 @@ pch_context(void)
 /*
  * Return the length of a particular patch line.
  */
-short
+ssize_t
 pch_line_len(LINENUM line)
 {
        return p_len[line];
index 3367056..aff07b6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pch.h,v 1.13 2019/12/11 20:10:17 jca Exp $    */
+/*     $OpenBSD: pch.h,v 1.14 2023/07/12 11:26:13 tb Exp $     */
 
 /*
  * patch - a program to apply diffs to original files
@@ -53,7 +53,7 @@ LINENUM               pch_newfirst(void);
 LINENUM                pch_repl_lines(void);
 LINENUM                pch_end(void);
 LINENUM                pch_context(void);
-short          pch_line_len(LINENUM);
+ssize_t                pch_line_len(LINENUM);
 char           pch_char(LINENUM);
 char           *pfetch(LINENUM);
 LINENUM                pch_hunk_beg(void);