git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
To: Jeff King <peff@peff.net>
Cc: Junio C Hamano <gitster@pobox.com>, Taylor Blau <me@ttaylorr.com>,
	Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com>,
	git@vger.kernel.org, Paul Ganssle <paul@ganssle.io>
Subject: Re: [PATCH] rebase --autosquash: fix a potential segfault
Date: Sat, 9 May 2020 01:45:03 +0200 (CEST)	[thread overview]
Message-ID: <nycvar.QRO.7.76.6.2005090112530.56@tvgsbejvaqbjf.bet> (raw)
In-Reply-To: <20200507191714.GA25306@coredump.intra.peff.net>

Hi Peff,


On Thu, 7 May 2020, Jeff King wrote:

> On Wed, May 06, 2020 at 11:35:48PM +0200, Johannes Schindelin wrote:
>
> > > >> > +				next[i] = next[i2];
> > > >> > +				next[i2] = i;
> > > >> > +				continue;
> > > >> > +			}
> > > >>
> > > >> I do have one question, though. What happens if we add a second
> > > >> fixup-of-a-fixup?
> > > >
> > > > Thanks for asking this question, I was a little curious about it, too.
> > >
> > > Interesting that three people looked at the same patch and asked the
> > > same question in different ways ;-)
> >
> > Indeed!
> >
> > I am very grateful, as I had missed that, and it helped me figure out a
> > better way to do it, and v2 looks a lot nicer, too.
>
> OK, so your v2 addresses that. Does that mean it was broken in v1?

Yes.

> If so, then why didn't my test reveal it?

Let's disect this:

 i  hash oneline
#0  1234 foo
#1  5678 !fixup foo
#2  abcd !fixup 5678
#3  dbaf !fixup 5678

Let's follow the original code, i.e. before my v1:

When #1 is processed, i.e. when `i == 1`, it finds `i2 == 0` as target. So
it sets `next[0]` as well as `tail[0]` to 1.

Then #2 is processed, i.e. `i == 2`, and it finds `i2 == 1` as target. It
sets `next[1]` as well as `tail[1]` to 2.

Now #3 is processed, i.e. it also finds `i2 == 1` as target, so it looks
at next[1], sees that it is already non-negative, so it sets
`next[tail[1]]`, i.e. `next[2]` to 3. It also sets `tail[1]` to 3, but
nobody cares about that because there is no further todo command.

Now, let's follow the code with my v1:

It actually does the same as before! Why, you ask? Because at no stage is
there any non-negative `next[j]` whose corresponding `tail[j]` is
negative. (Except after #3 was processed, at that stage, `next[2]` is
non-negative but `tail[2]` still is negative, but as I said, noone cares
because there are no remaining todo commands.)

So the crucial part to trigger this bug is to have a regular `fixup!
<oneline>` _between_ the `fixup! <oneline>` and the `fixup! <hash>`
targeting the latter. So I think I can modify your example accordingly:

	1234 foo
	5678 fixup! foo
	90ab fixup! foo
	abcd fixup! 5678
	dbaf fixup! 5678

Or using your actual shell commands:

  git commit -m base --allow-empty
  git commit --squash HEAD -m 'this is the first squash' --allow-empty
  s=$(git rev-parse HEAD)
  git commit --fixup HEAD^ --allow-empty # This is the crucial command
  git commit -m "squash! $s" -m 'this is the second squash' --allow-empty
  git commit -m "squash! $s" -m 'this is the third squash' --allow-empty
  git rebase -ki --autosquash --root

Note the cricual command `git commit --fixup HEAD^`. When processing that,
`i == 2` and `i2 == 0` (as for `i == 1`), and before v1, this would have
set `next[1]` but `tail[0]`! With v1, this would have led to #4 and #5
being exchanged. With v2, the role of `tail` would have been extended to
not only talk about the beginning of a fixup/squash chain, but about _any_
target of a fixup/squash, even if it is in the middle of a chain.

So why does this work? Why does it still do the right thing _even after_
inserting a fixup in the middle of a chain?

That's the beauty: if I insert anything in the middle of it, the `tail` of
the actual beginning of the fixup/squash chain won't need to be changed.
It still points to the end of that chain.

All I need to ensure is that item `i` is not just appended to the "chain"
starting at `i2`, but that it is _inserted_ at the end of that chain in
case that it is actually part of a larger chain, i.e. that its `next[i]`
is set correctly before making it the immediate successor of the target
commit. Since all of the elements in `next` and `tail` are initialized to
`-1` (i.e. "no next fixup/squash item after this"), it will even do the
right thing when it should actually append: it will set `next[i]` to `-1`
in that case.

> I'm not really doubting that your v2 works so much as trying to
> un-confuse myself about the whole situation (which in turn might lead to
> a more intelligent review).

I wish I was quicker in my responses because I think that this is really
helpful a conversation. By "forcing my hand" on a thorough explanation,
you really help me get clarity for myself about the actual underlying
issues. So even if I still think that v2 is correct after writing up the
above explanation, the degree of my confidence increased substantially.

Thanks,
Dscho

  reply	other threads:[~2020-05-08 23:45 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-04 20:40 [PATCH] rebase --autosquash: fix a potential segfault Johannes Schindelin via GitGitGadget
2020-05-04 21:19 ` Junio C Hamano
2020-05-04 21:33 ` Jeff King
2020-05-04 22:09   ` Taylor Blau
2020-05-05 20:30     ` Junio C Hamano
2020-05-06 21:35       ` Johannes Schindelin
2020-05-07 19:17         ` Jeff King
2020-05-08 23:45           ` Johannes Schindelin [this message]
2020-05-05 22:33 ` [PATCH v2] " Johannes Schindelin via GitGitGadget
2020-05-09 19:23   ` [PATCH v3] " Johannes Schindelin via GitGitGadget
2020-05-06 15:12 ` [PATCH] " Andrei Rybak
2020-05-07 14:27   ` Johannes Schindelin
2020-05-08 16:43     ` Philip Oakley
2020-05-08 16:57       ` Andrei Rybak
2020-05-08 17:21         ` Philip Oakley
2020-05-18 16:47         ` Philip Oakley
2020-05-18  3:27           ` Johannes Schindelin
2020-05-25 17:29             ` Philip Oakley
2020-05-25 21:36               ` [PATCH 0/2] Clarify some of the fixup! documenation Philip Oakley
2020-05-25 21:36                 ` [PATCH 1/2] doc: fixup/squash: clarify use of <oid-hash> in subject line Philip Oakley
2020-05-27 17:35                   ` Junio C Hamano
2020-05-29 11:41                     ` Philip Oakley
2020-05-25 21:36                 ` [PATCH 2/2] doc: fixup/squash: remove ellipsis marks, use <line> for clarify Philip Oakley

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=nycvar.QRO.7.76.6.2005090112530.56@tvgsbejvaqbjf.bet \
    --to=johannes.schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=gitgitgadget@gmail.com \
    --cc=gitster@pobox.com \
    --cc=me@ttaylorr.com \
    --cc=paul@ganssle.io \
    --cc=peff@peff.net \
    /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.
Code repositories for project(s) associated with this public 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).