git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: "Érico Rolim" <erico.erc@gmail.com>, git@vger.kernel.org
Subject: Re: Re* [BUG] segmentation fault in git-diff
Date: Thu, 9 Apr 2020 23:04:11 -0400	[thread overview]
Message-ID: <20200410030411.GA48173@coredump.intra.peff.net> (raw)
In-Reply-To: <xmqqv9m8kxzy.fsf_-_@gitster.c.googlers.com>

On Thu, Apr 09, 2020 at 05:03:45PM -0700, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> > But there are a bunch of other commits around the same time replacing
> > the_repository, and it seems like an easy mistake to make. Perhaps we
> > should rename the "refs" member of "struct repository" to something more
> > clearly private, which would force callers to use the access method.
> 
> Here is the final version that I am going to apply and merge to
> 'jch' branch.  This is an ancient regression in Git timescale, so
> its fix is not all that urgent, though.

Agreed. The patch looks good to me.

I prepared the patch below on top. I mostly wanted it as an auditing
tool to find similar cases, but there were none. It may still be worth
applying to protect ourselves in the future.

-- >8 --
Subject: [PATCH] repository: mark the "refs" pointer as private

The "refs" pointer in a struct repository starts life as NULL, but then
is lazily initialized when it is accessed via get_main_ref_store().
However, it's easy for calling code to forget this and access it
directly, leading to code which works _some_ of the time, but fails if
it is called before anybody else accesses the refs.

This was the cause of the bug fixed by 5ff4b920eb (sha1-name: do not
assume that the ref store is initialized, 2020-04-09). In order to
prevent similar bugs, let's more clearly mark the "refs" field as
private.

In addition to helping future code, the name change will help us audit
any existing direct uses. Besides get_main_ref_store() itself, it turns
out there is only one. But we know it's OK as it is on the line directly
after the fix from 5ff4b920eb, which will have initialized the pointer.
However it's still a good idea for it to model the proper use of the
accessing function, so we'll convert it.

Signed-off-by: Jeff King <peff@peff.net>
---
 refs.c       | 8 ++++----
 repository.h | 8 ++++++--
 sha1-name.c  | 2 +-
 3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/refs.c b/refs.c
index 1ab0bb54d3..b8759116cd 100644
--- a/refs.c
+++ b/refs.c
@@ -1852,14 +1852,14 @@ static struct ref_store *ref_store_init(const char *gitdir,
 
 struct ref_store *get_main_ref_store(struct repository *r)
 {
-	if (r->refs)
-		return r->refs;
+	if (r->refs_private)
+		return r->refs_private;
 
 	if (!r->gitdir)
 		BUG("attempting to get main_ref_store outside of repository");
 
-	r->refs = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS);
-	return r->refs;
+	r->refs_private = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS);
+	return r->refs_private;
 }
 
 /*
diff --git a/repository.h b/repository.h
index 040057dea6..6534fbb7b3 100644
--- a/repository.h
+++ b/repository.h
@@ -67,8 +67,12 @@ struct repository {
 	 */
 	struct parsed_object_pool *parsed_objects;
 
-	/* The store in which the refs are held. */
-	struct ref_store *refs;
+	/*
+	 * The store in which the refs are held. This should generally only be
+	 * accessed via get_main_ref_store(), as that will lazily initialize
+	 * the ref object.
+	 */
+	struct ref_store *refs_private;
 
 	/*
 	 * Contains path to often used file names.
diff --git a/sha1-name.c b/sha1-name.c
index 878553b132..fccc97fa7a 100644
--- a/sha1-name.c
+++ b/sha1-name.c
@@ -1816,7 +1816,7 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo,
 			cb.repo = repo;
 			cb.list = &list;
 			refs_for_each_ref(get_main_ref_store(repo), handle_one_ref, &cb);
-			refs_head_ref(repo->refs, handle_one_ref, &cb);
+			refs_head_ref(get_main_ref_store(repo), handle_one_ref, &cb);
 			commit_list_sort_by_date(&list);
 			return get_oid_oneline(repo, name + 2, oid, list);
 		}
-- 
2.26.0.414.ge3a6455e3d


  parent reply	other threads:[~2020-04-10  3:04 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-09 22:22 [BUG] segmentation fault in git-diff Érico Rolim
2020-04-09 22:45 ` Junio C Hamano
2020-04-09 22:47   ` Junio C Hamano
2020-04-09 22:57     ` Junio C Hamano
2020-04-09 23:37       ` Junio C Hamano
2020-04-09 23:41       ` Jeff King
2020-04-10  0:03         ` Re* " Junio C Hamano
2020-04-10  1:42           ` Érico Rolim
2020-04-10  3:04           ` Jeff King [this message]
2020-04-10  5:39             ` Junio C Hamano

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=20200410030411.GA48173@coredump.intra.peff.net \
    --to=peff@peff.net \
    --cc=erico.erc@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /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).