git: 1f9f319919d7 - stable/13 - diff: Fix a use after free as well as a memory leak in change().
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 11 Nov 2022 18:36:53 UTC
The branch stable/13 has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=1f9f319919d7f8b76c8d8a7edb71ca2f39fb40e1 commit 1f9f319919d7f8b76c8d8a7edb71ca2f39fb40e1 Author: John Baldwin <jhb@FreeBSD.org> AuthorDate: 2022-10-03 23:10:43 +0000 Commit: John Baldwin <jhb@FreeBSD.org> CommitDate: 2022-11-11 18:18:53 +0000 diff: Fix a use after free as well as a memory leak in change(). When -B or -I are used, change() evaluates the lines in a hunk to determine if it is a hunk that should be ignored. It does this by reading each candidate line into a mallocated buffer via preadline() and then calling ignoreline(). Previously the buffer was freed as a side effect of ignoreline_pattern() called from ignoreline(). However, if only -B was specified, then ignoreline_pattern() was not called and the lines were leaked. If both options were specified, then ignoreline_pattern() was called before checking for a blank line so that the second check was a use after free. To fix, pull the free() out of ignoreline_pattern() and instead do it up in change() so that is paired with preadline(). While here, simplify ignoreline() by checking for the -B and -I cases individually without a separate clause for when both are set. Also, do the cheaper check (-B) first, and remove a false comment (this function is only called if at least one of -I or -B are specified). Reviewed by: emaste Reported by: GCC 12 -Wuse-after-free Differential Revision: https://reviews.freebsd.org/D36822 (cherry picked from commit 3736b2dd327050d2e6c925964b210eccbaac51ab) --- usr.bin/diff/diffreg.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/usr.bin/diff/diffreg.c b/usr.bin/diff/diffreg.c index e728441c2cb2..72a4d5f25b07 100644 --- a/usr.bin/diff/diffreg.c +++ b/usr.bin/diff/diffreg.c @@ -1035,7 +1035,6 @@ ignoreline_pattern(char *line) int ret; ret = regexec(&ignore_re, line, 0, NULL, 0); - free(line); return (ret == 0); /* if it matched, it should be ignored. */ } @@ -1043,13 +1042,10 @@ static bool ignoreline(char *line, bool skip_blanks) { - if (ignore_pats != NULL && skip_blanks) - return (ignoreline_pattern(line) || *line == '\0'); - if (ignore_pats != NULL) - return (ignoreline_pattern(line)); - if (skip_blanks) - return (*line == '\0'); - /* No ignore criteria specified */ + if (skip_blanks && *line == '\0') + return (true); + if (ignore_pats != NULL && ignoreline_pattern(line)) + return (true); return (false); } @@ -1068,7 +1064,7 @@ change(char *file1, FILE *f1, char *file2, FILE *f2, int a, int b, int c, int d, long curpos; int i, nc; const char *walk; - bool skip_blanks; + bool skip_blanks, ignore; skip_blanks = (*pflags & D_SKIPBLANKLINES); restart: @@ -1086,7 +1082,9 @@ restart: for (i = a; i <= b; i++) { line = preadline(fileno(f1), ixold[i] - ixold[i - 1], ixold[i - 1]); - if (!ignoreline(line, skip_blanks)) + ignore = ignoreline(line, skip_blanks); + free(line); + if (!ignore) goto proceed; } } @@ -1094,7 +1092,9 @@ restart: for (i = c; i <= d; i++) { line = preadline(fileno(f2), ixnew[i] - ixnew[i - 1], ixnew[i - 1]); - if (!ignoreline(line, skip_blanks)) + ignore = ignoreline(line, skip_blanks); + free(line); + if (!ignore) goto proceed; } }