From f24ad3da66a0ea86f5674fac9442d3b4e4c78aa2 Mon Sep 17 00:00:00 2001 From: Thomas Wolf Date: Fri, 5 Apr 2019 21:33:14 +0200 Subject: [PATCH] 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 Signed-off-by: Matthias Sohn --- .../tst/org/eclipse/jgit/lib/ConfigTest.java | 35 +++++++++++++++++++ .../src/org/eclipse/jgit/lib/Config.java | 23 ++++++++++-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java index 5a4bd886ab..e3985cc970 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java @@ -1457,6 +1457,41 @@ public class ConfigTest { 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); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java index 4726975d07..2c01d60381 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java @@ -1413,11 +1413,23 @@ public class Config { case '"': value.append('"'); continue; + case '\r': { + int next = in.read(); + if (next == '\n') { + continue; // CR-LF + } else if (next >= 0) { + in.reset(); + } + break; + } default: - throw new ConfigInvalidException(MessageFormat.format( - JGitText.get().badEscape, - Character.valueOf(((char) c)))); + break; } + throw new ConfigInvalidException( + MessageFormat.format(JGitText.get().badEscape, + Character.isAlphabetic(c) + ? Character.valueOf(((char) c)) + : toUnicodeLiteral(c))); } if ('"' == c) { @@ -1430,6 +1442,11 @@ public class Config { 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. *

-- 2.39.5