git@vger.kernel.org list mirror (unofficial, one of many)
 help / color / mirror / code / 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> (=?utf-8?B?IsOGdmFyCUFybmZqw7Zyw7A=?= 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

  List information: http://vger.kernel.org/majordomo-info.html

* 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 \
    --subject='Re: [PATCH] diff: fix a segfault in >2 tree -I<regex> and --output=<file>' \
    /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

Code repositories for project(s) associated with this inbox:

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).