Skip to content

Commit 68f95b2

Browse files
committed
Sync with Git 2.16.4
* maint-2.16: Git 2.16.4 Git 2.15.2 Git 2.14.4 Git 2.13.7 verify_path: disallow symlinks in .gitmodules update-index: stat updated files earlier verify_dotfile: mention case-insensitivity in comment verify_path: drop clever fallthrough skip_prefix: add case-insensitive variant is_{hfs,ntfs}_dotgitmodules: add tests is_ntfs_dotgit: match other .git files is_hfs_dotgit: match other .git files is_ntfs_dotgit: use a size_t for traversing string submodule-config: verify submodule names as paths
2 parents 468165c + a42a58d commit 68f95b2

20 files changed

+507
-42
lines changed

Documentation/RelNotes/2.13.7.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Git v2.13.7 Release Notes
2+
=========================
3+
4+
Fixes since v2.13.6
5+
-------------------
6+
7+
* Submodule "names" come from the untrusted .gitmodules file, but we
8+
blindly append them to $GIT_DIR/modules to create our on-disk repo
9+
paths. This means you can do bad things by putting "../" into the
10+
name. We now enforce some rules for submodule names which will cause
11+
Git to ignore these malicious names (CVE-2018-11235).
12+
13+
Credit for finding this vulnerability and the proof of concept from
14+
which the test script was adapted goes to Etienne Stalmans.
15+
16+
* It was possible to trick the code that sanity-checks paths on NTFS
17+
into reading random piece of memory (CVE-2018-11233).
18+
19+
Credit for fixing for these bugs goes to Jeff King, Johannes
20+
Schindelin and others.

Documentation/RelNotes/2.14.4.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.14.4 Release Notes
2+
=========================
3+
4+
This release is to forward-port the fixes made in the v2.13.7 version
5+
of Git. See its release notes for details.

Documentation/RelNotes/2.15.2.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,8 @@ Fixes since v2.15.1
4343
* Clarify and enhance documentation for "merge-base --fork-point", as
4444
it was clear what it computed but not why/what for.
4545

46+
* This release also contains the fixes made in the v2.13.7 version of
47+
Git. See its release notes for details.
48+
4649

4750
Also contains various documentation updates and code clean-ups.

Documentation/RelNotes/2.16.4.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.16.4 Release Notes
2+
=========================
3+
4+
This release is to forward-port the fixes made in the v2.13.7 version
5+
of Git. See its release notes for details.

apply.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3860,9 +3860,9 @@ static int check_unsafe_path(struct patch *patch)
38603860
if (!patch->is_delete)
38613861
new_name = patch->new_name;
38623862

3863-
if (old_name && !verify_path(old_name))
3863+
if (old_name && !verify_path(old_name, patch->old_mode))
38643864
return error(_("invalid path '%s'"), old_name);
3865-
if (new_name && !verify_path(new_name))
3865+
if (new_name && !verify_path(new_name, patch->new_mode))
38663866
return error(_("invalid path '%s'"), new_name);
38673867
return 0;
38683868
}

builtin/submodule--helper.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,6 +1817,29 @@ static int is_active(int argc, const char **argv, const char *prefix)
18171817
return !is_submodule_active(the_repository, argv[1]);
18181818
}
18191819

1820+
/*
1821+
* Exit non-zero if any of the submodule names given on the command line is
1822+
* invalid. If no names are given, filter stdin to print only valid names
1823+
* (which is primarily intended for testing).
1824+
*/
1825+
static int check_name(int argc, const char **argv, const char *prefix)
1826+
{
1827+
if (argc > 1) {
1828+
while (*++argv) {
1829+
if (check_submodule_name(*argv) < 0)
1830+
return 1;
1831+
}
1832+
} else {
1833+
struct strbuf buf = STRBUF_INIT;
1834+
while (strbuf_getline(&buf, stdin) != EOF) {
1835+
if (!check_submodule_name(buf.buf))
1836+
printf("%s\n", buf.buf);
1837+
}
1838+
strbuf_release(&buf);
1839+
}
1840+
return 0;
1841+
}
1842+
18201843
#define SUPPORT_SUPER_PREFIX (1<<0)
18211844

18221845
struct cmd_struct {
@@ -1842,6 +1865,7 @@ static struct cmd_struct commands[] = {
18421865
{"push-check", push_check, 0},
18431866
{"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
18441867
{"is-active", is_active, 0},
1868+
{"check-name", check_name, 0},
18451869
};
18461870

18471871
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)

builtin/update-index.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -364,10 +364,9 @@ static int process_directory(const char *path, int len, struct stat *st)
364364
return error("%s: is a directory - add files inside instead", path);
365365
}
366366

367-
static int process_path(const char *path)
367+
static int process_path(const char *path, struct stat *st, int stat_errno)
368368
{
369369
int pos, len;
370-
struct stat st;
371370
const struct cache_entry *ce;
372371

373372
len = strlen(path);
@@ -391,13 +390,13 @@ static int process_path(const char *path)
391390
* First things first: get the stat information, to decide
392391
* what to do about the pathname!
393392
*/
394-
if (lstat(path, &st) < 0)
395-
return process_lstat_error(path, errno);
393+
if (stat_errno)
394+
return process_lstat_error(path, stat_errno);
396395

397-
if (S_ISDIR(st.st_mode))
398-
return process_directory(path, len, &st);
396+
if (S_ISDIR(st->st_mode))
397+
return process_directory(path, len, st);
399398

400-
return add_one_path(ce, path, len, &st);
399+
return add_one_path(ce, path, len, st);
401400
}
402401

403402
static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
@@ -406,7 +405,7 @@ static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
406405
int size, len, option;
407406
struct cache_entry *ce;
408407

409-
if (!verify_path(path))
408+
if (!verify_path(path, mode))
410409
return error("Invalid path '%s'", path);
411410

412411
len = strlen(path);
@@ -449,7 +448,18 @@ static void chmod_path(char flip, const char *path)
449448

450449
static void update_one(const char *path)
451450
{
452-
if (!verify_path(path)) {
451+
int stat_errno = 0;
452+
struct stat st;
453+
454+
if (mark_valid_only || mark_skip_worktree_only || force_remove ||
455+
mark_fsmonitor_only)
456+
st.st_mode = 0;
457+
else if (lstat(path, &st) < 0) {
458+
st.st_mode = 0;
459+
stat_errno = errno;
460+
} /* else stat is valid */
461+
462+
if (!verify_path(path, st.st_mode)) {
453463
fprintf(stderr, "Ignoring path %s\n", path);
454464
return;
455465
}
@@ -475,7 +485,7 @@ static void update_one(const char *path)
475485
report("remove '%s'", path);
476486
return;
477487
}
478-
if (process_path(path))
488+
if (process_path(path, &st, stat_errno))
479489
die("Unable to process path %s", path);
480490
report("add '%s'", path);
481491
}
@@ -545,7 +555,7 @@ static void read_index_info(int nul_term_line)
545555
path_name = uq.buf;
546556
}
547557

548-
if (!verify_path(path_name)) {
558+
if (!verify_path(path_name, mode)) {
549559
fprintf(stderr, "Ignoring path %s\n", path_name);
550560
continue;
551561
}

cache.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ extern int unmerged_index(const struct index_state *);
634634
*/
635635
extern int index_has_changes(struct strbuf *sb);
636636

637-
extern int verify_path(const char *path);
637+
extern int verify_path(const char *path, unsigned mode);
638638
extern int strcmp_offset(const char *s1, const char *s2, size_t *first_change);
639639
extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
640640
extern void adjust_dirname_case(struct index_state *istate, char *name);
@@ -1165,7 +1165,15 @@ int normalize_path_copy(char *dst, const char *src);
11651165
int longest_ancestor_length(const char *path, struct string_list *prefixes);
11661166
char *strip_path_suffix(const char *path, const char *suffix);
11671167
int daemon_avoid_alias(const char *path);
1168-
extern int is_ntfs_dotgit(const char *name);
1168+
1169+
/*
1170+
* These functions match their is_hfs_dotgit() counterparts; see utf8.h for
1171+
* details.
1172+
*/
1173+
int is_ntfs_dotgit(const char *name);
1174+
int is_ntfs_dotgitmodules(const char *name);
1175+
int is_ntfs_dotgitignore(const char *name);
1176+
int is_ntfs_dotgitattributes(const char *name);
11691177

11701178
/*
11711179
* Returns true iff "str" could be confused as a command-line option when

dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2992,7 +2992,7 @@ void untracked_cache_invalidate_path(struct index_state *istate,
29922992
{
29932993
if (!istate->untracked || !istate->untracked->root)
29942994
return;
2995-
if (!safe_path && !verify_path(path))
2995+
if (!safe_path && !verify_path(path, 0))
29962996
return;
29972997
invalidate_one_component(istate->untracked, istate->untracked->root,
29982998
path, strlen(path));

git-compat-util.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,23 @@ static inline int sane_iscase(int x, int is_lower)
10011001
return (x & 0x20) == 0;
10021002
}
10031003

1004+
/*
1005+
* Like skip_prefix, but compare case-insensitively. Note that the comparison
1006+
* is done via tolower(), so it is strictly ASCII (no multi-byte characters or
1007+
* locale-specific conversions).
1008+
*/
1009+
static inline int skip_iprefix(const char *str, const char *prefix,
1010+
const char **out)
1011+
{
1012+
do {
1013+
if (!*prefix) {
1014+
*out = str;
1015+
return 1;
1016+
}
1017+
} while (tolower(*str++) == tolower(*prefix++));
1018+
return 0;
1019+
}
1020+
10041021
static inline int strtoul_ui(char const *s, int base, unsigned int *result)
10051022
{
10061023
unsigned long ul;

0 commit comments

Comments
 (0)