From a09b1b6c3d90713ab5e3473bd7aa32387dc294c3 Mon Sep 17 00:00:00 2001 From: Christian Halstrick Date: Wed, 17 Dec 2014 14:36:52 +0100 Subject: [PATCH] ObjectChecker: Disallow Windows shortname "GIT~1" 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 Signed-off-by: Matthias Sohn --- .../eclipse/jgit/lib/ObjectCheckerTest.java | 34 +++++++++++++++++++ .../org/eclipse/jgit/lib/ObjectChecker.java | 11 ++++++ 2 files changed, 45 insertions(+) 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 aa17ac32c..8a782b7ff 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 @@ -1403,6 +1403,40 @@ public void testInvalidTreeNameIsDotGitSpaceDot() { } } + @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(); 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 1e4163e97..4913c4437 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java @@ -464,6 +464,9 @@ private void checkPathSegment2(byte[] raw, int ptr, int end) "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 @@ && toLower(buf[p + 1]) == 'i' && 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;