Browse Source

ObjectChecker: Disallow ".git." and ".git<space>"

Windows treats "foo." and "foo " as "foo". The ".git" directory is
special, as it contains metadata for a local Git repository. Disallow
variations that Windows considers to be the same.

Change-Id: I28eb48859a95a89111b4987c91de97557e3bb539
tags/v3.4.2.201412180340-r
Shawn Pearce 9 years ago
parent
commit
10310bf8ef

+ 2
- 8
org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java View File

@@ -186,10 +186,7 @@ public class DirCacheCheckoutMaliciousPathTest extends RepositoryTestCase {

@Test
public void testMaliciousGitPathEndSpaceUnixOk() throws Exception {
if (File.separatorChar == '\\')
return; // cannot emulate Unix on Windows for this test
((MockSystemReader) SystemReader.getInstance()).setUnix();
testMaliciousPathGoodFirstCheckout(".git ", "konfig");
testMaliciousPathBadFirstCheckout(".git ", "konfig");
}

@Test
@@ -212,10 +209,7 @@ public class DirCacheCheckoutMaliciousPathTest extends RepositoryTestCase {

@Test
public void testMaliciousGitPathEndDotUnixOk() throws Exception {
if (File.separatorChar == '\\')
return; // cannot emulate Unix on Windows for this test
((MockSystemReader) SystemReader.getInstance()).setUnix();
testMaliciousPathGoodFirstCheckout(".git.", "konfig");
testMaliciousPathBadFirstCheckout(".git.", "konfig");
}

@Test

+ 96
- 0
org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java View File

@@ -1307,6 +1307,102 @@ public class ObjectCheckerTest {
}
}

@Test
public void testInvalidTreeNameIsDotGitDot() {
StringBuilder b = new StringBuilder();
entry(b, "100644 .git.");
byte[] data = Constants.encodeASCII(b.toString());
try {
checker.checkTree(data);
fail("incorrectly accepted an invalid tree");
} catch (CorruptObjectException e) {
assertEquals("invalid name '.git.'", e.getMessage());
}
}

@Test
public void testValidTreeNameIsDotGitDotDot()
throws CorruptObjectException {
StringBuilder b = new StringBuilder();
entry(b, "100644 .git..");
checker.checkTree(Constants.encodeASCII(b.toString()));
}

@Test
public void testInvalidTreeNameIsDotGitSpace() {
StringBuilder b = new StringBuilder();
entry(b, "100644 .git ");
byte[] data = Constants.encodeASCII(b.toString());
try {
checker.checkTree(data);
fail("incorrectly accepted an invalid tree");
} catch (CorruptObjectException e) {
assertEquals("invalid name '.git '", e.getMessage());
}
}

@Test
public void testInvalidTreeNameIsDotGitSomething()
throws CorruptObjectException {
StringBuilder b = new StringBuilder();
entry(b, "100644 .gitfoobar");
byte[] data = Constants.encodeASCII(b.toString());
checker.checkTree(data);
}

@Test
public void testInvalidTreeNameIsDotGitSomethingSpaceSomething()
throws CorruptObjectException {
StringBuilder b = new StringBuilder();
entry(b, "100644 .gitfoo bar");
byte[] data = Constants.encodeASCII(b.toString());
checker.checkTree(data);
}

@Test
public void testInvalidTreeNameIsDotGitSomethingDot()
throws CorruptObjectException {
StringBuilder b = new StringBuilder();
entry(b, "100644 .gitfoobar.");
byte[] data = Constants.encodeASCII(b.toString());
checker.checkTree(data);
}

@Test
public void testInvalidTreeNameIsDotGitSomethingDotDot()
throws CorruptObjectException {
StringBuilder b = new StringBuilder();
entry(b, "100644 .gitfoobar..");
byte[] data = Constants.encodeASCII(b.toString());
checker.checkTree(data);
}

@Test
public void testInvalidTreeNameIsDotGitDotSpace() {
StringBuilder b = new StringBuilder();
entry(b, "100644 .git. ");
byte[] data = Constants.encodeASCII(b.toString());
try {
checker.checkTree(data);
fail("incorrectly accepted an invalid tree");
} catch (CorruptObjectException e) {
assertEquals("invalid name '.git. '", e.getMessage());
}
}

@Test
public void testInvalidTreeNameIsDotGitSpaceDot() {
StringBuilder b = new StringBuilder();
entry(b, "100644 .git . ");
byte[] data = Constants.encodeASCII(b.toString());
try {
checker.checkTree(data);
fail("incorrectly accepted an invalid tree");
} catch (CorruptObjectException e) {
assertEquals("invalid name '.git . '", e.getMessage());
}
}

@Test
public void testInvalidTreeTruncatedInName() {
final StringBuilder b = new StringBuilder();

+ 26
- 2
org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java View File

@@ -453,7 +453,13 @@ public class ObjectChecker {
throw new CorruptObjectException("invalid name '..'");
break;
case 4:
if (isDotGit(raw, ptr + 1))
if (isGit(raw, ptr + 1))
throw new CorruptObjectException(String.format(
"invalid name '%s'",
RawParseUtils.decode(raw, ptr, end)));
break;
default:
if (end - ptr > 4 && isNormalizedGit(raw, ptr + 1, end))
throw new CorruptObjectException(String.format(
"invalid name '%s'",
RawParseUtils.decode(raw, ptr, end)));
@@ -540,12 +546,30 @@ public class ObjectChecker {
return 1 <= c && c <= 31;
}

private static boolean isDotGit(byte[] buf, int p) {
private static boolean isGit(byte[] buf, int p) {
return toLower(buf[p]) == 'g'
&& toLower(buf[p + 1]) == 'i'
&& toLower(buf[p + 2]) == 't';
}

private static boolean isNormalizedGit(byte[] raw, int ptr, int end) {
if (isGit(raw, ptr)) {
int dots = 0;
boolean space = false;
int p = end - 1;
for (; (ptr + 2) < p; p--) {
if (raw[p] == '.')
dots++;
else if (raw[p] == ' ')
space = true;
else
break;
}
return p == ptr + 2 && (dots == 1 || space);
}
return false;
}

private static char toLower(byte b) {
if ('A' <= b && b <= 'Z')
return (char) (b + ('a' - 'A'));

Loading…
Cancel
Save