diff options
author | Jeff King <peff@peff.net> | 2020-07-08 00:38:19 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2020-07-08 13:57:18 -0700 |
commit | 5f46e610cb43496612d7ec030d142b6b8515399d (patch) | |
tree | c65e1d24b2a851e0d25485fc103e7cd136d466cd /builtin/diff.c | |
parent | Documentation: usage for diff combined commits (diff) | |
download | tgif-5f46e610cb43496612d7ec030d142b6b8515399d.tar.xz |
diff: check for merge bases before assigning sym->base
In symdiff_prepare(), we iterate over the set of parsed objects to pick
out any symmetric differences, including the left, right, and base
elements. We assign the results into pointers in a "struct symdiff", and
then complain if we didn't find a base, like so:
sym->left = rev->pending.objects[lpos].name;
sym->right = rev->pending.objects[rpos].name;
sym->base = rev->pending.objects[basepos].name;
if (basecount == 0)
die(_("%s...%s: no merge base"), sym->left, sym->right);
But the least lines are backwards. If basecount is 0, then basepos will
be -1, and we will access memory outside of the pending array. This
isn't usually that big a deal, since we don't do anything besides a
single pointer-sized read before exiting anyway, but it does violate the
C standard, and of course memory-checking tools like ASan complain.
Let's put the basecount check first. Note that we haveto split it from
the other assignments, since the die() relies on sym->left and
sym->right having been assigned (this isn't strictly necessary, but is
easier to read than dereferencing the pending array again).
Reported-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/diff.c')
-rw-r--r-- | builtin/diff.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/builtin/diff.c b/builtin/diff.c index 96ee2cbb2a..64ac8ae0af 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -355,9 +355,9 @@ static void symdiff_prepare(struct rev_info *rev, struct symdiff *sym) sym->left = rev->pending.objects[lpos].name; sym->right = rev->pending.objects[rpos].name; - sym->base = rev->pending.objects[basepos].name; if (basecount == 0) die(_("%s...%s: no merge base"), sym->left, sym->right); + sym->base = rev->pending.objects[basepos].name; bitmap_unset(map, basepos); /* unmark the base we want */ sym->warn = basecount > 1; sym->skip = map; |