git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
	"Han-Wen Nienhuys" <hanwen@google.com>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Subject: [PATCH 1/3] refs API: use "failure_errno", not "errno"
Date: Thu,  9 Dec 2021 06:02:26 +0100	[thread overview]
Message-ID: <patch-1.3-b983d3b6033-20211209T045735Z-avarab@gmail.com> (raw)
In-Reply-To: <cover-0.3-00000000000-20211209T045735Z-avarab@gmail.com>

Fix a logic error in refs_resolve_ref_unsafe() introduced in a recent
series of mine to abstract the refs API away from errno. See
96f6623ada0 (Merge branch 'ab/refs-errno-cleanup', 2021-11-29)for that
series.

In that series introduction of "failure_errno" to
refs_resolve_ref_unsafe came in ef18119dec8 (refs API: add a version
of refs_resolve_ref_unsafe() with "errno", 2021-10-16). There we'd set
"errno = 0" immediately before refs_read_raw_ref(), and then set
"failure_errno" to "errno" if errno was non-zero afterwards.

Then in the next commit 8b72fea7e91 (refs API: make
refs_read_raw_ref() not set errno, 2021-10-16) we started expecting
"refs_read_raw_ref()" to set "failure_errno". It would do that if
refs_read_raw_ref() failed, but it wouldn't be the same errno.

So we might set the "errno" here to any arbitrary bad value, and end
up e.g. returning NULL when we meant to return the refname from
refs_resolve_ref_unsafe(), or the other way around. Instrumenting this
code will reveal cases where refs_read_raw_ref() will fail, and
"errno" and "failure_errno" will be set to different values.

In practice I haven't found a case where this scary bug changed
anything in practice. The reason for that is that we'll not care about
the actual value of "errno" here per-se, but only whether:

 1. We have an errno
 2. If it's one of ENOENT, EISDIR or ENOTDIR. See the adjacent code
    added in a1c1d8170db (refs_resolve_ref_unsafe: handle d/f
    conflicts for writes, 2017-10-06)

I.e. if we clobber "failure_errno" with "errno", but it happened to be
one of those three, and we'll clobber it with another one of the three
we were OK.

Perhaps there are cases where the difference ended up mattering, but I
haven't found them. Instrumenting the test suite to fail if "errno"
and "failure_errno" are different shows a lot of failures, checking if
they're different *and* one is but not the other is outside that list
of three "errno" values yields no failures.

But let's fix the obvious bug. We should just stop paying attention to
"errno" in refs_resolve_ref_unsafe(). In addition let's change the
partial resetting of "errno" in files_read_raw_ref() to happen just
before the "return", to ensure that any such bug will be more easily
spotted in the future.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 refs.c               | 2 --
 refs/files-backend.c | 3 +--
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index 996ac271641..533cf5a2b2e 100644
--- a/refs.c
+++ b/refs.c
@@ -1714,8 +1714,6 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
 		if (refs_read_raw_ref(refs, refname, oid, &sb_refname,
 				      &read_flags, failure_errno)) {
 			*flags |= read_flags;
-			if (errno)
-				*failure_errno = errno;
 
 			/* In reading mode, refs must eventually resolve */
 			if (resolve_flags & RESOLVE_REF_READING)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 4b14f30d48f..85e195a2573 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -387,7 +387,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 	if (lstat(path, &st) < 0) {
 		int ignore_errno;
 		myerr = errno;
-		errno = 0;
 		if (myerr != ENOENT)
 			goto out;
 		if (refs_read_raw_ref(refs->packed_ref_store, refname, oid,
@@ -404,7 +403,6 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 		strbuf_reset(&sb_contents);
 		if (strbuf_readlink(&sb_contents, path, st.st_size) < 0) {
 			myerr = errno;
-			errno = 0;
 			if (myerr == ENOENT || myerr == EINVAL)
 				/* inconsistent with lstat; retry */
 				goto stat_ref;
@@ -474,6 +472,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, const char *refname,
 
 	strbuf_release(&sb_path);
 	strbuf_release(&sb_contents);
+	errno = 0;
 	return ret;
 }
 
-- 
2.34.1.930.g218b4aae189


  reply	other threads:[~2021-12-09  5:03 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-08 11:38 errno oversight Han-Wen Nienhuys
2021-12-08 12:47 ` Ævar Arnfjörð Bjarmason
2021-12-08 13:00   ` Ævar Arnfjörð Bjarmason
2021-12-08 19:02     ` Junio C Hamano
2021-12-09  5:02       ` [PATCH 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
2021-12-09  5:02         ` Ævar Arnfjörð Bjarmason [this message]
2021-12-09  5:02         ` [PATCH 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
2021-12-09  5:02         ` [PATCH 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
2021-12-12 19:53         ` [PATCH v2 0/3] refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
2021-12-12 19:53           ` [PATCH v2 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
2021-12-12 19:53           ` [PATCH v2 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
2021-12-12 19:53           ` [PATCH v2 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
2022-01-12 12:36           ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Ævar Arnfjörð Bjarmason
2022-01-12 12:36             ` [PATCH v3 1/3] refs API: use "failure_errno", not "errno" Ævar Arnfjörð Bjarmason
2022-01-12 19:59               ` Junio C Hamano
2022-01-13 12:14                 ` Ævar Arnfjörð Bjarmason
2022-01-12 12:36             ` [PATCH v3 2/3] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
2022-01-12 20:02               ` Junio C Hamano
2022-01-12 12:36             ` [PATCH v3 3/3] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
2022-01-12 19:34             ` [PATCH v3 0/3] For v2.35.0: refs: ab/refs-errno-cleanup fixup + remove "failure_errno" Junio C Hamano
2022-01-13 12:22               ` Ævar Arnfjörð Bjarmason
2022-01-13 18:54                 ` Junio C Hamano
2022-01-14 12:21                   ` Ævar Arnfjörð Bjarmason
2022-01-26 14:36               ` [PATCH v4 0/2] refs: remove the last use of "errno" from the public API Ævar Arnfjörð Bjarmason
2022-01-26 14:37                 ` [PATCH v4 1/2] sequencer: don't use die_errno() on refs_resolve_ref_unsafe() failure Ævar Arnfjörð Bjarmason
2022-01-26 23:57                   ` Junio C Hamano
2022-01-26 14:37                 ` [PATCH v4 2/2] refs API: remove "failure_errno" from refs_resolve_ref_unsafe() Ævar Arnfjörð Bjarmason
2021-12-08 13:05   ` errno oversight Han-Wen Nienhuys

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=patch-1.3-b983d3b6033-20211209T045735Z-avarab@gmail.com \
    --to=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=hanwen@google.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).