Handle escaped CR-LF in git config files

Canonical git treats CR-LF in config files as LF.[1][2] JGit does so,
too, except when escaped as a line continuation. Correct this and
treat the sequence \-CR-LF as a line continuation.

[1] https://github.com/git/git/commit/db2c075d9
[2] https://github.com/git/git/blob/v2.21.0/config.c#L485

Bug: 545850
Change-Id: I51e7378a22c21b3baa3701163c423d04c900af5a
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
This commit is contained in:
Thomas Wolf 2019-04-05 21:33:14 +02:00 committed by Matthias Sohn
parent 10ab407fa6
commit f24ad3da66
2 changed files with 56 additions and 4 deletions

View File

@ -1457,6 +1457,41 @@ public void testInvalidGroupHeader() throws ConfigInvalidException {
parse("[foo \"bar\" ]\nfoo=bar\n");
}
@Test
public void testCrLf() throws ConfigInvalidException {
assertEquals("true", parseEscapedValue("true\r\n"));
}
@Test
public void testLfContinuation() throws ConfigInvalidException {
assertEquals("true", parseEscapedValue("tr\\\nue"));
}
@Test
public void testCrCharContinuation() throws ConfigInvalidException {
expectedEx.expect(ConfigInvalidException.class);
expectedEx.expectMessage("Bad escape: \\u000d");
parseEscapedValue("tr\\\rue");
}
@Test
public void testCrEOFContinuation() throws ConfigInvalidException {
expectedEx.expect(ConfigInvalidException.class);
expectedEx.expectMessage("Bad escape: \\u000d");
parseEscapedValue("tr\\\r");
}
@Test
public void testCrLfContinuation() throws ConfigInvalidException {
assertEquals("true", parseEscapedValue("tr\\\r\nue"));
}
@Test
public void testWhitespaceContinuation() throws ConfigInvalidException {
assertEquals("tr ue", parseEscapedValue("tr \\\n ue"));
assertEquals("tr ue", parseEscapedValue("tr \\\r\n ue"));
}
private static void assertValueRoundTrip(String value)
throws ConfigInvalidException {
assertValueRoundTrip(value, value);

View File

@ -1413,11 +1413,23 @@ private static String readValue(StringReader in)
case '"':
value.append('"');
continue;
default:
throw new ConfigInvalidException(MessageFormat.format(
JGitText.get().badEscape,
Character.valueOf(((char) c))));
case '\r': {
int next = in.read();
if (next == '\n') {
continue; // CR-LF
} else if (next >= 0) {
in.reset();
}
break;
}
default:
break;
}
throw new ConfigInvalidException(
MessageFormat.format(JGitText.get().badEscape,
Character.isAlphabetic(c)
? Character.valueOf(((char) c))
: toUnicodeLiteral(c)));
}
if ('"' == c) {
@ -1430,6 +1442,11 @@ private static String readValue(StringReader in)
return value.length() > 0 ? value.toString() : null;
}
private static String toUnicodeLiteral(int c) {
return String.format("\\u%04x", //$NON-NLS-1$
Integer.valueOf(c));
}
/**
* Parses a section of the configuration into an application model object.
* <p>