Windows creates shortnames for all non-8.3 files (see [1]). Hence we need to disallow all names which could potentially be a shortname for ".git". Example: in an empty directory create a folder "GIT~1". Now you can't create another folder ".git". The path "GIT~1" may map to ".git" on Windows. A potential victim to such an attack first has to initialize a git repository in order to receive any git commits. Hence the .git folder created by init will get the shortname "GIT~1". ".git" will only get a different shortname if the user has created a file "GIT~1" before initialization of the git repository. [1] http://en.wikipedia.org/wiki/8.3_filename Change-Id: I9978ab8f2d2951c46c1b9bbde57986d64d26b9b2 Signed-off-by: Christian Halstrick <christian.halstrick@sap.com> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>tags/v3.4.2.201412180340-r
@@ -1403,6 +1403,40 @@ public class ObjectCheckerTest { | |||
} | |||
} | |||
@Test | |||
public void testInvalidTreeNameIsGITTilde1() { | |||
StringBuilder b = new StringBuilder(); | |||
entry(b, "100644 GIT~1"); | |||
byte[] data = Constants.encodeASCII(b.toString()); | |||
try { | |||
checker.checkTree(data); | |||
fail("incorrectly accepted an invalid tree"); | |||
} catch (CorruptObjectException e) { | |||
assertEquals("invalid name 'GIT~1'", e.getMessage()); | |||
} | |||
} | |||
@Test | |||
public void testInvalidTreeNameIsGiTTilde1() { | |||
StringBuilder b = new StringBuilder(); | |||
entry(b, "100644 GiT~1"); | |||
byte[] data = Constants.encodeASCII(b.toString()); | |||
try { | |||
checker.checkTree(data); | |||
fail("incorrectly accepted an invalid tree"); | |||
} catch (CorruptObjectException e) { | |||
assertEquals("invalid name 'GiT~1'", e.getMessage()); | |||
} | |||
} | |||
@Test | |||
public void testValidTreeNameIsGitTilde11() throws CorruptObjectException { | |||
StringBuilder b = new StringBuilder(); | |||
entry(b, "100644 GIT~11"); | |||
byte[] data = Constants.encodeASCII(b.toString()); | |||
checker.checkTree(data); | |||
} | |||
@Test | |||
public void testInvalidTreeTruncatedInName() { | |||
final StringBuilder b = new StringBuilder(); |
@@ -464,6 +464,9 @@ public class ObjectChecker { | |||
"invalid name '%s'", | |||
RawParseUtils.decode(raw, ptr, end))); | |||
} | |||
} else if (isGitTilde1(raw, ptr, end)) { | |||
throw new CorruptObjectException(String.format("invalid name '%s'", | |||
RawParseUtils.decode(raw, ptr, end))); | |||
} | |||
if (windows) { | |||
@@ -552,6 +555,14 @@ public class ObjectChecker { | |||
&& toLower(buf[p + 2]) == 't'; | |||
} | |||
private static boolean isGitTilde1(byte[] buf, int p, int end) { | |||
if (end - p != 5) | |||
return false; | |||
return toLower(buf[p]) == 'g' && toLower(buf[p + 1]) == 'i' | |||
&& toLower(buf[p + 2]) == 't' && buf[p + 3] == '~' | |||
&& buf[p + 4] == '1'; | |||
} | |||
private static boolean isNormalizedGit(byte[] raw, int ptr, int end) { | |||
if (isGit(raw, ptr)) { | |||
int dots = 0; |