All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Cc: git@vger.kernel.org, "René Scharfe" <l.s.r@web.de>,
	"Michał Kępień" <michal@isc.org>
Subject: Re: [PATCH] diff: fix a segfault in >2 tree -I<regex> and --output=<file>
Date: Mon, 23 May 2022 13:08:20 -0700	[thread overview]
Message-ID: <xmqqleusqaff.fsf@gitster.g> (raw)
In-Reply-To: <patch-1.1-f7fd645468c-20220523T182954Z-avarab@gmail.com> ("Ævar	Arnfjörð Bjarmason"'s message of "Mon, 23 May 2022 20:31:28 +0200")

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Fix a regression in c45dc9cf30 (diff: plug memory leak from regcomp()
> on {log,diff} -I, 2021-02-11), as noted in [1] there was a logic error
> where we'd free the regex too soon.
>
> Now we'll ensure that diff_free() can be called repeatedly
> instead. We'd ultimately like to do away with the "no_free" confusion
> surrounding it, and to attempt to free() things only once, as outlined
> in [2]. But in the meantime this will fix the segfault.

Hmph, repeated calls to diff_free_file() now closes the file upon
the first call.  I would have expected that such a resource would be
released when all the references go away, i.e. upon the last call.
The same thing for the ignore-regex array.

Clearing the "options->close_file" bit, and using FREE_AND_NULL(),
would hide a breakage that could be caused by this change, doesn't
it, because any use-after-release will say "ah, no need to close the
file" and "oh, there is no regex".  The former is not so worrisome,
but the latter may be---we may no longer have regex because the
first call to diff_free_ignore_regex() has cleared it and the code
that wants to use the regex, if exists, would happily say "oh, there
is no regex", instead of exposing the use-after-release breakage to
a segfault.

> Thus we're here testing that -I<regex> is ignored in this case, and
> likewise for --output=<file>, but since this is what we were doing
> before c45dc9cf30 let's accept it for now.

It is true that the result of applying this patch is equivalent to
c45dc9cf (diff: plug memory leak from regcomp() on {log,diff} -I,
2021-02-11), but doesn't that merely point at the commit as the
source of behaviour breakage?  With ignore-regex leaking before that
commit, wouldn't we have been using ignore-regex with combined diff
machinery?

Sorry, but I am failing to convince myself that this is not sweep
the issue under the rug.

> 1. https://lore.kernel.org/git/a6a14213-bc82-d6fb-43dd-5a423c40a4f8@web.de/
> 2. https://lore.kernel.org/git/220520.86pmk81a9z.gmgdl@evledraar.gmail.com/
>
> Reported-by: René Scharfe <l.s.r@web.de>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>
> On Sat, May 14 2022, René Scharfe wrote:
>
>> Hi all,
>>
>> git diff segfaults when it's asked to produce a combined diff and ignore
>> certain lines with --ignore-matching-lines/-I, e.g.:
>>
>>    $ git diff -I DEF_VER v2.33.3 v2.33.3^@
>>    zsh: segmentation fault  ./git-diff -I DEF_VER v2.33.3 v2.33.3^@
>
>  diff.c                  |  9 ++++++---
>  t/t4013-diff-various.sh | 15 +++++++++++++++
>  2 files changed, 21 insertions(+), 3 deletions(-)
>
> diff --git a/diff.c b/diff.c
> index e71cf758861..183c9f21305 100644
> --- a/diff.c
> +++ b/diff.c
> @@ -6432,8 +6432,10 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
>  
>  static void diff_free_file(struct diff_options *options)
>  {
> -	if (options->close_file)
> -		fclose(options->file);
> +	if (!options->close_file)
> +		return;
> +	options->close_file = 0;
> +	fclose(options->file);
>  }
>  
>  static void diff_free_ignore_regex(struct diff_options *options)
> @@ -6444,7 +6446,8 @@ static void diff_free_ignore_regex(struct diff_options *options)
>  		regfree(options->ignore_regex[i]);
>  		free(options->ignore_regex[i]);
>  	}
> -	free(options->ignore_regex);
> +	options->ignore_regex_nr = 0;
> +	FREE_AND_NULL(options->ignore_regex);
>  }
>  
>  void diff_free(struct diff_options *options)
> diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
> index 056e922164d..b556d185f53 100755
> --- a/t/t4013-diff-various.sh
> +++ b/t/t4013-diff-various.sh
> @@ -614,4 +614,19 @@ test_expect_success 'diff -I<regex>: detect malformed regex' '
>  	test_i18ngrep "invalid regex given to -I: " error
>  '
>  
> +test_expect_success 'diff -I<regex>: combined diff does not segfault' '
> +	revs="HEAD~2 HEAD~ HEAD" &&
> +	git diff $revs >expect &&
> +	git diff -I . $revs >actual &&
> +	test_cmp expect actual

And indeed this casts such a broken behaviour in stone.

> +'
> +
> +test_expect_success 'diff --output=<file>: combined diff does not segfault' '
> +	revs="HEAD~2 HEAD~ HEAD" &&
> +	git diff --output=expect.file $revs >expect.out &&
> +	git diff $revs >actual &&
> +	test_cmp expect.out actual &&
> +	test_must_be_empty expect.file

So is this one.

> +'
> +
>  test_done


  reply	other threads:[~2022-05-23 20:08 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-14  9:32 Bug: combined diff with --ignore-matching-lines René Scharfe
2022-05-23 18:31 ` [PATCH] diff: fix a segfault in >2 tree -I<regex> and --output=<file> Ævar Arnfjörð Bjarmason
2022-05-23 20:08   ` Junio C Hamano [this message]
2022-05-24 11:38     ` Ævar Arnfjörð Bjarmason
2022-05-24 19:38       ` Junio C Hamano
2022-05-24 20:17         ` Ævar Arnfjörð Bjarmason
2022-06-18 11:12           ` René Scharfe
2022-06-18 11:12           ` [PATCH 1/2] combine-diff: abort if --ignore-matching-lines is given René Scharfe
2022-06-21 15:35             ` Junio C Hamano
2022-06-21 15:58               ` René Scharfe
2022-06-21 16:55                 ` Junio C Hamano
2022-06-18 11:12           ` [PATCH 2/2] combine-diff: abort if --output " René Scharfe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=xmqqleusqaff.fsf@gitster.g \
    --to=gitster@pobox.com \
    --cc=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=l.s.r@web.de \
    --cc=michal@isc.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.