looks reasonable. OK florian
On 2023-07-11 21:13 +02, Theo Buehler <t...@theobuehler.org> wrote: > On Tue, Jul 11, 2023 at 08:35:31PM +0200, Theo Buehler wrote: >> On Tue, Jul 11, 2023 at 02:32:48PM +0200, Theo Buehler wrote: >> > On Tue, Jul 11, 2023 at 11:48:57AM +0100, Stuart Henderson wrote: >> > > I ran into a segfault with patch(1) in a port, here's a test case with a >> > > minimal reproducer. >> > > >> > > $ echo foo > test >> > > $ perl -e 'print "--- test.orig\n+++ test\n@@ -1,1 +1,2 @@\n foo\n+" . >> > > 'x' x 32768 . "\n\\ No newline at end of file\n"' > test.patch >> > >> > patch maintains the line lengths in an array of shorts p_len[] and >> > doesn't check for overflows. This long line overflows the length, so >> > you get a bad buffer underrun when doing 's[p_len[filldst - 1]] = 0;' >> >> The below appears to fix this and passes regress. It won't be able to >> apply the binary patch, but it should no longer segfault. > > More complete diff, thanks otto > > Index: patch.c > =================================================================== > RCS file: /cvs/src/usr.bin/patch/patch.c,v > retrieving revision 1.71 > diff -u -p -r1.71 patch.c > --- patch.c 3 Aug 2022 07:30:37 -0000 1.71 > +++ patch.c 11 Jul 2023 19:10:55 -0000 > @@ -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 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 > * 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: pch.c > =================================================================== > RCS file: /cvs/src/usr.bin/patch/pch.c,v > retrieving revision 1.63 > diff -u -p -r1.63 pch.c > --- pch.c 26 Dec 2022 19:16:02 -0000 1.63 > +++ pch.c 11 Jul 2023 19:08:06 -0000 > @@ -56,7 +56,7 @@ static LINENUM p_end = -1; /* last line > 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: pch.h > =================================================================== > RCS file: /cvs/src/usr.bin/patch/pch.h,v > retrieving revision 1.13 > diff -u -p -r1.13 pch.h > --- pch.h 11 Dec 2019 20:10:17 -0000 1.13 > +++ pch.h 11 Jul 2023 19:07:57 -0000 > @@ -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); > -- In my defence, I have been left unsupervised.