summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Pearce <sop@google.com>2014-12-01 15:01:07 -0800
committerMatthias Sohn <matthias.sohn@sap.com>2014-12-18 14:49:03 +0100
commit10310bf8ef2ad1af16fbd2c406d813c17ea33793 (patch)
treec1388922ed33445f6d1dc2284e5e8881c0069a8e
parent07612a610f99ce32b8409a854c74d7761e8f38eb (diff)
downloadjgit-10310bf8ef2ad1af16fbd2c406d813c17ea33793.tar.gz
jgit-10310bf8ef2ad1af16fbd2c406d813c17ea33793.zip
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
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java10
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java96
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java28
3 files changed, 124 insertions, 10 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java
index d29a75ef71..ca3e0666ea 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/DirCacheCheckoutMaliciousPathTest.java
@@ -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
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java
index f3db2f65da..aa17ac32cf 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java
@@ -1308,6 +1308,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();
b.append("100644 b");
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
index 92b4e39d5b..1e4163e97b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
@@ -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'));