Skip to content

Commit 1702ab1

Browse files
committed
Sync with 2.40.3
* maint-2.40: Git 2.40.3 Git 2.39.5 Revert "Add a helper function to compare file contents" clone: drop the protections where hooks aren't run tests: verify that `clone -c core.hooksPath=/dev/null` works again Revert "core.hooksPath: add some protection while cloning" init: use the correct path of the templates directory again hook: plug a new memory leak ci: stop installing "gcc-13" for osx-gcc ci: avoid bare "gcc" for osx-gcc job ci: drop mention of BREW_INSTALL_PACKAGES variable
2 parents 0f15832 + 158f558 commit 1702ab1

File tree

16 files changed

+131
-227
lines changed

16 files changed

+131
-227
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,7 @@ jobs:
264264
cc: clang
265265
pool: macos-13
266266
- jobname: osx-gcc
267-
cc: gcc
268-
cc_package: gcc-13
267+
cc: gcc-13
269268
pool: macos-13
270269
- jobname: linux-gcc-default
271270
cc: gcc

Documentation/RelNotes/2.39.5.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Git 2.39.5 Release Notes
2+
========================
3+
4+
Relative to Git 2.39.5, this release has fixes for regressions that
5+
were introduced in 2.39.4, most notably the error message shown when
6+
cloning Git LFS-enabled repositories. It also contains a fix for the
7+
`osx-gcc` CI job.
8+
9+
Fixes since Git 2.39.4
10+
----------------------
11+
12+
* The clone protections introduced in v2.39.4 broke Git LFS-enabled
13+
clones and have therefore been dropped.
14+
15+
* The `core.hooksPath` setting is allowed in repository-local
16+
configs again; The benefits of making it protected were
17+
outweighed by the cost.
18+
19+
* Fix a memory leak.
20+
21+
* CI fix.

Documentation/RelNotes/2.40.3.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Git v2.40.3 Release Notes
2+
=========================
3+
4+
This release merges up the regression bug fixes in v2.39.5,
5+
most notably the bug where cloning Git LFS-enabled repositories
6+
failed; see the release notes for that version for details.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2743,7 +2743,7 @@ exec-cmd.sp exec-cmd.s exec-cmd.o: EXTRA_CPPFLAGS = \
27432743
'-DFALLBACK_RUNTIME_PREFIX="$(prefix_SQ)"'
27442744

27452745
builtin/init-db.sp builtin/init-db.s builtin/init-db.o: GIT-PREFIX
2746-
builtin/init-db.sp builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \
2746+
setup.sp setup.s setup.o: EXTRA_CPPFLAGS = \
27472747
-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"'
27482748

27492749
config.sp config.s config.o: GIT-PREFIX

builtin/clone.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -959,8 +959,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
959959
int submodule_progress;
960960
int filter_submodules = 0;
961961
int hash_algo;
962-
const char *template_dir;
963-
char *template_dir_dup = NULL;
964962

965963
struct transport_ls_refs_options transport_ls_refs_options =
966964
TRANSPORT_LS_REFS_OPTIONS_INIT;
@@ -980,13 +978,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
980978
usage_msg_opt(_("You must specify a repository to clone."),
981979
builtin_clone_usage, builtin_clone_options);
982980

983-
xsetenv("GIT_CLONE_PROTECTION_ACTIVE", "true", 0 /* allow user override */);
984-
template_dir = get_template_dir(option_template);
985-
if (*template_dir && !is_absolute_path(template_dir))
986-
template_dir = template_dir_dup =
987-
absolute_pathdup(template_dir);
988-
xsetenv("GIT_CLONE_TEMPLATE_DIR", template_dir, 1);
989-
990981
if (option_depth || option_since || option_not.nr)
991982
deepen = 1;
992983
if (option_single_branch == -1)
@@ -1134,7 +1125,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
11341125
}
11351126
}
11361127

1137-
init_db(git_dir, real_git_dir, template_dir, GIT_HASH_UNKNOWN, NULL,
1128+
init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
11381129
INIT_DB_QUIET);
11391130

11401131
if (real_git_dir) {
@@ -1478,7 +1469,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
14781469
free(dir);
14791470
free(path);
14801471
free(repo_to_free);
1481-
free(template_dir_dup);
1472+
UNLEAK(repo);
14821473
junk_mode = JUNK_LEAVE_ALL;
14831474

14841475
transport_ls_refs_options_release(&transport_ls_refs_options);

builtin/init-db.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
#include "setup.h"
1919
#include "worktree.h"
2020
#include "wrapper.h"
21+
<<<<<<< bc94ea4862010ae6f13d0ed7a91bffd56e600d63
22+
#include "run-command.h"
23+
#include "hook.h"
24+
=======
25+
>>>>>>> e60caf60d83cc4367306224e06d6ea8a38e7ad0c
2126

2227
#ifdef NO_TRUSTABLE_FILEMODE
2328
#define TEST_FILEMODE 0

ci/install-dependencies.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ macos-*)
3434
export HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1
3535
# Uncomment this if you want to run perf tests:
3636
# brew install gnu-time
37-
test -z "$BREW_INSTALL_PACKAGES" ||
38-
brew install $BREW_INSTALL_PACKAGES
3937
brew link --force gettext
4038
mkdir -p $HOME/bin
4139
(

config.c

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,19 +1596,8 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
15961596
if (!strcmp(var, "core.attributesfile"))
15971597
return git_config_pathname(&git_attributes_file, var, value);
15981598

1599-
if (!strcmp(var, "core.hookspath")) {
1600-
if (current_config_scope() == CONFIG_SCOPE_LOCAL &&
1601-
git_env_bool("GIT_CLONE_PROTECTION_ACTIVE", 0))
1602-
die(_("active `core.hooksPath` found in the local "
1603-
"repository config:\n\t%s\nFor security "
1604-
"reasons, this is disallowed by default.\nIf "
1605-
"this is intentional and the hook should "
1606-
"actually be run, please\nrun the command "
1607-
"again with "
1608-
"`GIT_CLONE_PROTECTION_ACTIVE=false`"),
1609-
value);
1599+
if (!strcmp(var, "core.hookspath"))
16101600
return git_config_pathname(&git_hooks_path, var, value);
1611-
}
16121601

16131602
if (!strcmp(var, "core.bare")) {
16141603
is_bare_repository_cfg = git_config_bool(var, value);

copy.c

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -71,61 +71,3 @@ int copy_file_with_time(const char *dst, const char *src, int mode)
7171
return copy_times(dst, src);
7272
return status;
7373
}
74-
75-
static int do_symlinks_match(const char *path1, const char *path2)
76-
{
77-
struct strbuf buf1 = STRBUF_INIT, buf2 = STRBUF_INIT;
78-
int ret = 0;
79-
80-
if (!strbuf_readlink(&buf1, path1, 0) &&
81-
!strbuf_readlink(&buf2, path2, 0))
82-
ret = !strcmp(buf1.buf, buf2.buf);
83-
84-
strbuf_release(&buf1);
85-
strbuf_release(&buf2);
86-
return ret;
87-
}
88-
89-
int do_files_match(const char *path1, const char *path2)
90-
{
91-
struct stat st1, st2;
92-
int fd1 = -1, fd2 = -1, ret = 1;
93-
char buf1[8192], buf2[8192];
94-
95-
if ((fd1 = open_nofollow(path1, O_RDONLY)) < 0 ||
96-
fstat(fd1, &st1) || !S_ISREG(st1.st_mode)) {
97-
if (fd1 < 0 && errno == ELOOP)
98-
/* maybe this is a symbolic link? */
99-
return do_symlinks_match(path1, path2);
100-
ret = 0;
101-
} else if ((fd2 = open_nofollow(path2, O_RDONLY)) < 0 ||
102-
fstat(fd2, &st2) || !S_ISREG(st2.st_mode)) {
103-
ret = 0;
104-
}
105-
106-
if (ret)
107-
/* to match, neither must be executable, or both */
108-
ret = !(st1.st_mode & 0111) == !(st2.st_mode & 0111);
109-
110-
if (ret)
111-
ret = st1.st_size == st2.st_size;
112-
113-
while (ret) {
114-
ssize_t len1 = read_in_full(fd1, buf1, sizeof(buf1));
115-
ssize_t len2 = read_in_full(fd2, buf2, sizeof(buf2));
116-
117-
if (len1 < 0 || len2 < 0 || len1 != len2)
118-
ret = 0; /* read error or different file size */
119-
else if (!len1) /* len2 is also 0; hit EOF on both */
120-
break; /* ret is still true */
121-
else
122-
ret = !memcmp(buf1, buf2, len1);
123-
}
124-
125-
if (fd1 >= 0)
126-
close(fd1);
127-
if (fd2 >= 0)
128-
close(fd2);
129-
130-
return ret;
131-
}

copy.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,4 @@ int copy_fd(int ifd, int ofd);
77
int copy_file(const char *dst, const char *src, int mode);
88
int copy_file_with_time(const char *dst, const char *src, int mode);
99

10-
/*
11-
* Compare the file mode and contents of two given files.
12-
*
13-
* If both files are actually symbolic links, the function returns 1 if the link
14-
* targets are identical or 0 if they are not.
15-
*
16-
* If any of the two files cannot be accessed or in case of read failures, this
17-
* function returns 0.
18-
*
19-
* If the file modes and contents are identical, the function returns 1,
20-
* otherwise it returns 0.
21-
*/
22-
int do_files_match(const char *path1, const char *path2);
23-
2410
#endif /* COPY_H */

hook.c

Lines changed: 78 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,92 @@
88
#include "strbuf.h"
99
#include "environment.h"
1010
#include "setup.h"
11-
#include "copy.h"
11+
<<<<<<< bc94ea4862010ae6f13d0ed7a91bffd56e600d63
12+
#include "hex.h"
13+
#include "strmap.h"
14+
15+
static struct strset safe_hook_sha256s = STRSET_INIT;
16+
static int safe_hook_sha256s_initialized;
1217

13-
static int identical_to_template_hook(const char *name, const char *path)
18+
static int get_sha256_of_file_contents(const char *path, char *sha256)
1419
{
15-
const char *env = getenv("GIT_CLONE_TEMPLATE_DIR");
16-
const char *template_dir = get_template_dir(env && *env ? env : NULL);
17-
struct strbuf template_path = STRBUF_INIT;
18-
int found_template_hook, ret;
20+
struct strbuf sb = STRBUF_INIT;
21+
int fd;
22+
ssize_t res;
1923

20-
strbuf_addf(&template_path, "%s/hooks/%s", template_dir, name);
21-
found_template_hook = access(template_path.buf, X_OK) >= 0;
22-
#ifdef STRIP_EXTENSION
23-
if (!found_template_hook) {
24-
strbuf_addstr(&template_path, STRIP_EXTENSION);
25-
found_template_hook = access(template_path.buf, X_OK) >= 0;
24+
git_hash_ctx ctx;
25+
const struct git_hash_algo *algo = &hash_algos[GIT_HASH_SHA256];
26+
unsigned char hash[GIT_MAX_RAWSZ];
27+
28+
if ((fd = open(path, O_RDONLY)) < 0)
29+
return -1;
30+
res = strbuf_read(&sb, fd, 400);
31+
close(fd);
32+
if (res < 0)
33+
return -1;
34+
35+
algo->init_fn(&ctx);
36+
algo->update_fn(&ctx, sb.buf, sb.len);
37+
strbuf_release(&sb);
38+
algo->final_fn(hash, &ctx);
39+
40+
hash_to_hex_algop_r(sha256, hash, algo);
41+
42+
return 0;
43+
}
44+
45+
void add_safe_hook(const char *path)
46+
{
47+
char sha256[GIT_SHA256_HEXSZ + 1] = { '\0' };
48+
49+
if (!get_sha256_of_file_contents(path, sha256)) {
50+
char *p;
51+
52+
strset_add(&safe_hook_sha256s, sha256);
53+
54+
/* support multi-process operations e.g. recursive clones */
55+
p = xstrfmt("safe.hook.sha256=%s", sha256);
56+
git_config_push_parameter(p);
57+
free(p);
2658
}
27-
#endif
28-
if (!found_template_hook)
59+
}
60+
61+
static int safe_hook_cb(const char *key, const char *value, void *d)
62+
{
63+
struct strset *set = d;
64+
65+
if (value && !strcmp(key, "safe.hook.sha256"))
66+
strset_add(set, value);
67+
68+
return 0;
69+
}
70+
71+
static int is_hook_safe_during_clone(const char *name, const char *path, char *sha256)
72+
{
73+
if (get_sha256_of_file_contents(path, sha256) < 0)
2974
return 0;
3075

31-
ret = do_files_match(template_path.buf, path);
76+
if (!safe_hook_sha256s_initialized) {
77+
safe_hook_sha256s_initialized = 1;
3278

33-
strbuf_release(&template_path);
34-
return ret;
79+
/* Hard-code known-safe values for Git LFS v3.4.0..v3.5.1 */
80+
/* pre-push */
81+
strset_add(&safe_hook_sha256s, "df5417b2daa3aa144c19681d1e997df7ebfe144fb7e3e05138bd80ae998008e4");
82+
/* post-checkout */
83+
strset_add(&safe_hook_sha256s, "791471b4ff472aab844a4fceaa48bbb0a12193616f971e8e940625498b4938a6");
84+
/* post-commit */
85+
strset_add(&safe_hook_sha256s, "21e961572bb3f43a5f2fbafc1cc764d86046cc2e5f0bbecebfe9684a0b73b664");
86+
/* post-merge */
87+
strset_add(&safe_hook_sha256s, "75da0da66a803b4b030ad50801ba57062c6196105eb1d2251590d100edb9390b");
88+
89+
git_protected_config(safe_hook_cb, &safe_hook_sha256s);
90+
}
91+
92+
return strset_contains(&safe_hook_sha256s, sha256);
3593
}
94+
=======
95+
#include "copy.h"
96+
>>>>>>> e60caf60d83cc4367306224e06d6ea8a38e7ad0c
3697

3798
const char *find_hook(const char *name)
3899
{
@@ -69,14 +130,6 @@ const char *find_hook(const char *name)
69130
}
70131
return NULL;
71132
}
72-
if (!git_hooks_path && git_env_bool("GIT_CLONE_PROTECTION_ACTIVE", 0) &&
73-
!identical_to_template_hook(name, path.buf))
74-
die(_("active `%s` hook found during `git clone`:\n\t%s\n"
75-
"For security reasons, this is disallowed by default.\n"
76-
"If this is intentional and the hook should actually "
77-
"be run, please\nrun the command again with "
78-
"`GIT_CLONE_PROTECTION_ACTIVE=false`"),
79-
name, path.buf);
80133
return path.buf;
81134
}
82135

t/helper/test-path-utils.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -501,16 +501,6 @@ int cmd__path_utils(int argc, const char **argv)
501501
return !!res;
502502
}
503503

504-
if (argc == 4 && !strcmp(argv[1], "do_files_match")) {
505-
int ret = do_files_match(argv[2], argv[3]);
506-
507-
if (ret)
508-
printf("equal\n");
509-
else
510-
printf("different\n");
511-
return !ret;
512-
}
513-
514504
fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
515505
argv[1] ? argv[1] : "(there was none)");
516506
return 1;

t/t0060-path-utils.sh

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -610,45 +610,4 @@ test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD '%(prefix)/ works'
610610
test_cmp expect actual
611611
'
612612

613-
test_expect_success 'do_files_match()' '
614-
test_seq 0 10 >0-10.txt &&
615-
test_seq -1 10 >-1-10.txt &&
616-
test_seq 1 10 >1-10.txt &&
617-
test_seq 1 9 >1-9.txt &&
618-
test_seq 0 8 >0-8.txt &&
619-
620-
test-tool path-utils do_files_match 0-10.txt 0-10.txt >out &&
621-
622-
assert_fails() {
623-
test_must_fail \
624-
test-tool path-utils do_files_match "$1" "$2" >out &&
625-
grep different out
626-
} &&
627-
628-
assert_fails 0-8.txt 1-9.txt &&
629-
assert_fails -1-10.txt 0-10.txt &&
630-
assert_fails 1-10.txt 1-9.txt &&
631-
assert_fails 1-10.txt .git &&
632-
assert_fails does-not-exist 1-10.txt &&
633-
634-
if test_have_prereq FILEMODE
635-
then
636-
cp 0-10.txt 0-10.x &&
637-
chmod a+x 0-10.x &&
638-
assert_fails 0-10.txt 0-10.x
639-
fi &&
640-
641-
if test_have_prereq SYMLINKS
642-
then
643-
ln -sf 0-10.txt symlink &&
644-
ln -s 0-10.txt another-symlink &&
645-
ln -s over-the-ocean yet-another-symlink &&
646-
ln -s "$PWD/0-10.txt" absolute-symlink &&
647-
assert_fails 0-10.txt symlink &&
648-
test-tool path-utils do_files_match symlink another-symlink &&
649-
assert_fails symlink yet-another-symlink &&
650-
assert_fails symlink absolute-symlink
651-
fi
652-
'
653-
654613
test_done

0 commit comments

Comments
 (0)