Kaynağa Gözat

Ban dangerous ref names in Windows

Bug: 423551 
Change-Id: I3e71ef1b4a8181f46d2902c9169859f150cd6ad0
Also-By: Robin Stocker <robin@nibor.org>
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
tags/v3.3.0.201402191814-rc1
Robin Rosenberg 10 yıl önce
ebeveyn
işleme
e03f18941f

+ 23
- 0
org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ValidRefNameTest.java Dosyayı Görüntüle



import static org.eclipse.jgit.junit.Assert.assertEquals; import static org.eclipse.jgit.junit.Assert.assertEquals;


import org.eclipse.jgit.junit.MockSystemReader;
import org.eclipse.jgit.util.SystemReader;
import org.junit.Test; import org.junit.Test;


public class ValidRefNameTest { public class ValidRefNameTest {
assertValid(false, "refs/heads/master@{1}"); assertValid(false, "refs/heads/master@{1}");
assertValid(false, "refs/heads/master@{1.hour.ago}"); assertValid(false, "refs/heads/master@{1.hour.ago}");
} }

@Test
public void testWindowsReservedNames() {
SystemReader original = SystemReader.getInstance();
try {
SystemReader.setInstance(new MockSystemReader() {
public boolean isWindows() {
return true;
}
});
// re-using code from DirCacheCheckoutTest, hence
// only testing for one of the special names.
assertValid(false, "refs/heads/con");
assertValid(false, "refs/con/x");
assertValid(false, "con/heads/x");
assertValid(true, "refs/heads/conx");
assertValid(true, "refs/heads/xcon");
} finally {
SystemReader.setInstance(original);
}
}
} }

+ 50
- 17
org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheCheckout.java Dosyayı Görüntüle



private static byte[][] forbidden; private static byte[][] forbidden;
static { static {
String[] list = getSortedForbiddenFileNames();
forbidden = new byte[list.length][];
for (int i = 0; i < list.length; ++i)
forbidden[i] = Constants.encodeASCII(list[i]);
}

static String[] getSortedForbiddenFileNames() {
String[] list = new String[] { "AUX", "COM1", "COM2", "COM3", "COM4", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ String[] list = new String[] { "AUX", "COM1", "COM2", "COM3", "COM4", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
"COM5", "COM6", "COM7", "COM8", "COM9", "CON", "LPT1", "LPT2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ "COM5", "COM6", "COM7", "COM8", "COM9", "CON", "LPT1", "LPT2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", "NUL", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", "NUL", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"PRN" }; //$NON-NLS-1$ "PRN" }; //$NON-NLS-1$
forbidden = new byte[list.length][];
for (int i = 0; i < list.length; ++i)
forbidden[i] = Constants.encodeASCII(list[i]);
return list;
} }


private static void checkValidPath(CanonicalTreeParser t) private static void checkValidPath(CanonicalTreeParser t)
checkValidPathSegment(i); checkValidPathSegment(i);
} }


/**
* Check if path is a valid path for a checked out file name or ref name.
*
* @param path
* @throws InvalidPathException
* if the path is invalid
* @since 3.3
*/
public static void checkValidPath(String path) throws InvalidPathException {
boolean isWindows = SystemReader.getInstance().isWindows();
boolean isOSX = SystemReader.getInstance().isMacOS();
boolean ignCase = isOSX || isWindows;

byte[] bytes = Constants.encode(path);
int segmentStart = 0;
for (int i = 0; i < bytes.length; i++) {
if (bytes[i] == '/') {
checkValidPathSegment(isWindows, ignCase, bytes, segmentStart,
i, path);
segmentStart = i + 1;
}
}
if (segmentStart < bytes.length)
checkValidPathSegment(isWindows, ignCase, bytes, segmentStart,
bytes.length, path);
}

private static void checkValidPathSegment(CanonicalTreeParser t) private static void checkValidPathSegment(CanonicalTreeParser t)
throws InvalidPathException { throws InvalidPathException {
boolean isWindows = SystemReader.getInstance().isWindows(); boolean isWindows = SystemReader.getInstance().isWindows();
byte[] raw = t.getEntryPathBuffer(); byte[] raw = t.getEntryPathBuffer();
int end = ptr + t.getNameLength(); int end = ptr + t.getNameLength();


checkValidPathSegment(isWindows, ignCase, raw, ptr, end,
t.getEntryPathString());
}

private static void checkValidPathSegment(boolean isWindows,
boolean ignCase, byte[] raw, int ptr, int end, String path) {
// Validate path component at this level of the tree // Validate path component at this level of the tree
int start = ptr; int start = ptr;
while (ptr < end) { while (ptr < end) {
if (raw[ptr] == '/') if (raw[ptr] == '/')
throw new InvalidPathException( throw new InvalidPathException(
JGitText.get().invalidPathContainsSeparator,
"/", t.getEntryPathString()); //$NON-NLS-1$
JGitText.get().invalidPathContainsSeparator, "/", path); //$NON-NLS-1$
if (isWindows) { if (isWindows) {
if (raw[ptr] == '\\') if (raw[ptr] == '\\')
throw new InvalidPathException( throw new InvalidPathException(
JGitText.get().invalidPathContainsSeparator, JGitText.get().invalidPathContainsSeparator,
"\\", t.getEntryPathString()); //$NON-NLS-1$
"\\", path); //$NON-NLS-1$
if (raw[ptr] == ':') if (raw[ptr] == ':')
throw new InvalidPathException( throw new InvalidPathException(
JGitText.get().invalidPathContainsSeparator, JGitText.get().invalidPathContainsSeparator,
":", t.getEntryPathString()); //$NON-NLS-1$
":", path); //$NON-NLS-1$
} }
ptr++; ptr++;
} }
// '.' and '..' are invalid here // '.' and '..' are invalid here
if (ptr - start == 1) { if (ptr - start == 1) {
if (raw[start] == '.') if (raw[start] == '.')
throw new InvalidPathException(t.getEntryPathString());
throw new InvalidPathException(path);
} else if (ptr - start == 2) { } else if (ptr - start == 2) {
if (raw[start] == '.') if (raw[start] == '.')
if (raw[start + 1] == '.') if (raw[start + 1] == '.')
throw new InvalidPathException(t.getEntryPathString());
throw new InvalidPathException(path);
} else if (ptr - start == 4) { } else if (ptr - start == 4) {
// .git (possibly case insensitive) is disallowed // .git (possibly case insensitive) is disallowed
if (raw[start] == '.') if (raw[start] == '.')
|| (ignCase && raw[start + 2] == 'I')) || (ignCase && raw[start + 2] == 'I'))
if (raw[start + 3] == 't' if (raw[start + 3] == 't'
|| (ignCase && raw[start + 3] == 'T')) || (ignCase && raw[start + 3] == 'T'))
throw new InvalidPathException(
t.getEntryPathString());
throw new InvalidPathException(path);
} }
if (isWindows) { if (isWindows) {
// Space or period at end of file name is ignored by Windows. // Space or period at end of file name is ignored by Windows.
if (ptr > 0) { if (ptr > 0) {
if (raw[ptr - 1] == '.') if (raw[ptr - 1] == '.')
throw new InvalidPathException( throw new InvalidPathException(
JGitText.get().invalidPathPeriodAtEndWindows,
t.getEntryPathString());
JGitText.get().invalidPathPeriodAtEndWindows, path);
if (raw[ptr - 1] == ' ') if (raw[ptr - 1] == ' ')
throw new InvalidPathException( throw new InvalidPathException(
JGitText.get().invalidPathSpaceAtEndWindows,
t.getEntryPathString());
JGitText.get().invalidPathSpaceAtEndWindows, path);
} }


int i; int i;
if (k == len) if (k == len)
throw new InvalidPathException( throw new InvalidPathException(
JGitText.get().invalidPathReservedOnWindows, JGitText.get().invalidPathReservedOnWindows,
RawParseUtils.decode(forbidden[j]), t
.getEntryPathString());
RawParseUtils.decode(forbidden[j]), path);
} }
} }
} }

+ 10
- 0
org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java Dosyayı Görüntüle

import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;


import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.dircache.InvalidPathException;
import org.eclipse.jgit.errors.AmbiguousObjectException; import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.IncorrectObjectTypeException;
if (refName.endsWith(".lock")) //$NON-NLS-1$ if (refName.endsWith(".lock")) //$NON-NLS-1$
return false; return false;


// Borrow logic for filterig out invalid paths. These
// are also invalid ref
try {
DirCacheCheckout.checkValidPath(refName);
} catch (InvalidPathException e) {
return false;
}

int components = 1; int components = 1;
char p = '\0'; char p = '\0';
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {

Loading…
İptal
Kaydet