From 125a8959d2b639dbb8f4665335f369f67c455d74 Mon Sep 17 00:00:00 2001 From: Dave Borowitz Date: Fri, 29 Apr 2016 11:10:36 -0400 Subject: [PATCH] PersonIdent: Strip some special chars from external strings The special characters <> and '\n' interfere with parsing of identities. C git strips these special characters, so we should too. Rather than allocating extra strings by calling String#trim(), add a few lines to our sanitization method to perform the same trimming as described in String's Javadoc. Change-Id: I96edcb93a2fc194ee354d60566d352299742a52f --- .../jgit/lib/T0001_PersonIdentTest.java | 41 +++++++++++++++++-- .../src/org/eclipse/jgit/lib/PersonIdent.java | 41 ++++++++++++++++++- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java index 48d2c480a..86d8206b3 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdentTest.java @@ -89,14 +89,47 @@ public void nullForEmailShouldThrowIllegalArgumentException() { @Test public void testToExternalStringTrimsNameAndEmail() throws Exception { - PersonIdent personIdent = new PersonIdent(" A U Thor ", - " author@example.com "); + PersonIdent personIdent = new PersonIdent(" \u0010A U Thor ", + " author@example.com \u0009"); - assertEquals(" A U Thor ", personIdent.getName()); - assertEquals(" author@example.com ", personIdent.getEmailAddress()); + assertEquals(" \u0010A U Thor ", personIdent.getName()); + assertEquals(" author@example.com \u0009", personIdent.getEmailAddress()); String externalString = personIdent.toExternalString(); assertTrue(externalString.startsWith("A U Thor ")); } + @Test + public void testToExternalStringTrimsAllWhitespace() { + String ws = " \u0001 \n "; + PersonIdent personIdent = new PersonIdent(ws, ws); + assertEquals(ws, personIdent.getName()); + assertEquals(ws, personIdent.getEmailAddress()); + + String externalString = personIdent.toExternalString(); + assertTrue(externalString.startsWith(" <>")); + } + + @Test + public void testToExternalStringTrimsOtherBadCharacters() { + String name = " Foo\r\n "; + String email = " Baz>\n\u1234")); + } + + @Test + public void testEmptyNameAndEmail() { + PersonIdent personIdent = new PersonIdent("", ""); + assertEquals("", personIdent.getName()); + assertEquals("", personIdent.getEmailAddress()); + + String externalString = personIdent.toExternalString(); + assertTrue(externalString.startsWith(" <>")); + } + } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java index aa304634b..f352f3996 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PersonIdent.java @@ -111,6 +111,43 @@ public static void appendTimezone(StringBuilder r, int offset) { r.append(offsetMins); } + /** + * Sanitize the given string for use in an identity and append to output. + *

+ * Trims whitespace from both ends and special characters {@code \n < >} that + * interfere with parsing; appends all other characters to the output. + * Analogous to the C git function {@code strbuf_addstr_without_crud}. + * + * @param r + * string builder to append to. + * @param str + * input string. + */ + private static void appendSanitized(StringBuilder r, String str) { + // Trim any whitespace less than \u0020 as in String#trim(). + int i = 0; + while (i < str.length() && str.charAt(i) <= ' ') { + i++; + } + int end = str.length(); + while (end > i && str.charAt(end - 1) <= ' ') { + end--; + } + + for (; i < end; i++) { + char c = str.charAt(i); + switch (c) { + case '\n': + case '<': + case '>': + continue; + default: + r.append(c); + break; + } + } + } + private final String name; private final String emailAddress; @@ -305,9 +342,9 @@ && getEmailAddress().equals(p.getEmailAddress()) */ public String toExternalString() { final StringBuilder r = new StringBuilder(); - r.append(getName().trim()); + appendSanitized(r, getName()); r.append(" <"); //$NON-NLS-1$ - r.append(getEmailAddress().trim()); + appendSanitized(r, getEmailAddress()); r.append("> "); //$NON-NLS-1$ r.append(when / 1000); r.append(' ');