Skip to content

Commit 1f570a2

Browse files
committed
path: check for a symlinked .gitmodules in fs-agnostic code
We still compare case-insensitively to protect more thoroughly as we don't know what specifics we'll see on the system and it's the behaviour from git.
1 parent 3fbfae2 commit 1f570a2

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

src/path.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,24 @@ GIT_INLINE(bool) verify_char(unsigned char c, unsigned int flags)
16991699
return true;
17001700
}
17011701

1702+
/*
1703+
* Return the length of the common prefix between str and prefix, comparing them
1704+
* case-insensitively (must be ASCII to match).
1705+
*/
1706+
GIT_INLINE(size_t) common_prefix_icase(const char *str, size_t len, const char *prefix)
1707+
{
1708+
size_t count = 0;
1709+
1710+
while (len >0 && tolower(*str) == tolower(*prefix)) {
1711+
count++;
1712+
str++;
1713+
prefix++;
1714+
len--;
1715+
}
1716+
1717+
return count;
1718+
}
1719+
17021720
/*
17031721
* We fundamentally don't like some paths when dealing with user-inputted
17041722
* strings (in checkout or ref names): we don't want dot or dot-dot
@@ -1763,14 +1781,20 @@ static bool verify_component(
17631781
* specific tests, they would have already rejected `.git`.
17641782
*/
17651783
if ((flags & GIT_PATH_REJECT_DOT_GIT_HFS) == 0 &&
1766-
(flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
1767-
(flags & GIT_PATH_REJECT_DOT_GIT_LITERAL) &&
1768-
len == 4 &&
1769-
component[0] == '.' &&
1770-
(component[1] == 'g' || component[1] == 'G') &&
1771-
(component[2] == 'i' || component[2] == 'I') &&
1772-
(component[3] == 't' || component[3] == 'T'))
1773-
return false;
1784+
(flags & GIT_PATH_REJECT_DOT_GIT_NTFS) == 0 &&
1785+
(flags & GIT_PATH_REJECT_DOT_GIT_LITERAL)) {
1786+
if (len >= 4 &&
1787+
component[0] == '.' &&
1788+
(component[1] == 'g' || component[1] == 'G') &&
1789+
(component[2] == 'i' || component[2] == 'I') &&
1790+
(component[3] == 't' || component[3] == 'T')) {
1791+
if (len == 4)
1792+
return false;
1793+
1794+
if (S_ISLNK(mode) && common_prefix_icase(component, len, ".gitmodules") == len)
1795+
return false;
1796+
}
1797+
}
17741798

17751799
return true;
17761800
}

0 commit comments

Comments
 (0)