summaryrefslogtreecommitdiffstats
path: root/setup.c
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2024-05-07 06:52:51 +0200
committerJunio C Hamano <gitster@pobox.com>2024-05-07 07:50:48 +0200
commit0c6bd2b81d1e18dfa1e143c354c554cca34b3685 (patch)
treed8f8a497b4f516d8a9310190e65a8691ed8586c7 /setup.c
parentpath: harden validation of HEAD with non-standard hashes (diff)
downloadgit-0c6bd2b81d1e18dfa1e143c354c554cca34b3685.tar.xz
git-0c6bd2b81d1e18dfa1e143c354c554cca34b3685.zip
path: move `validate_headref()` to its only user
While `validate_headref()` is only called from `is_git_directory()` in "setup.c", it is currently implemented in "path.c". Move it over such that it becomes clear that it is only really used during setup in order to discover repositories. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'setup.c')
-rw-r--r--setup.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/setup.c b/setup.c
index f4b32f76e3..7c996659bd 100644
--- a/setup.c
+++ b/setup.c
@@ -4,6 +4,7 @@
#include "environment.h"
#include "exec-cmd.h"
#include "gettext.h"
+#include "hex.h"
#include "object-name.h"
#include "refs.h"
#include "repository.h"
@@ -341,6 +342,58 @@ int get_common_dir_noenv(struct strbuf *sb, const char *gitdir)
return ret;
}
+static int validate_headref(const char *path)
+{
+ struct stat st;
+ char buffer[256];
+ const char *refname;
+ struct object_id oid;
+ int fd;
+ ssize_t len;
+
+ if (lstat(path, &st) < 0)
+ return -1;
+
+ /* Make sure it is a "refs/.." symlink */
+ if (S_ISLNK(st.st_mode)) {
+ len = readlink(path, buffer, sizeof(buffer)-1);
+ if (len >= 5 && !memcmp("refs/", buffer, 5))
+ return 0;
+ return -1;
+ }
+
+ /*
+ * Anything else, just open it and try to see if it is a symbolic ref.
+ */
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ len = read_in_full(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+
+ if (len < 0)
+ return -1;
+ buffer[len] = '\0';
+
+ /*
+ * Is it a symbolic ref?
+ */
+ if (skip_prefix(buffer, "ref:", &refname)) {
+ while (isspace(*refname))
+ refname++;
+ if (starts_with(refname, "refs/"))
+ return 0;
+ }
+
+ /*
+ * Is this a detached HEAD?
+ */
+ if (get_oid_hex_any(buffer, &oid) != GIT_HASH_UNKNOWN)
+ return 0;
+
+ return -1;
+}
+
/*
* Test if it looks like we're at a git directory.
* We want to see: