Commit 464ed9a8 authored by Mikael Ståldal's avatar Mikael Ståldal
Browse files

LOG4J2-2120 Properly escape all control characters in JSON

parent d563cb30
Showing with 45 additions and 16 deletions
+45 -16
......@@ -171,19 +171,47 @@ public final class StringBuilders {
public static void escapeJson(final StringBuilder toAppendTo, final int start) {
for (int i = toAppendTo.length() - 1; i >= start; i--) { // backwards: length may change
final char c = toAppendTo.charAt(i);
if (c == '\n') {
// Json string newline character must be encoded as literal "\n"
toAppendTo.setCharAt(i, '\\');
toAppendTo.insert(i + 1, 'n');
} else if (Character.isISOControl(c)) {
// all iso control characters are in U+00xx
toAppendTo.setCharAt(i, '\\');
toAppendTo.insert(i + 1, "u0000");
toAppendTo.setCharAt(i + 4, Chars.getUpperCaseHex((c & 0xF0) >> 4));
toAppendTo.setCharAt(i + 5, Chars.getUpperCaseHex(c & 0xF));
} else if (c == '"' || c == '\\') {
// only " and \ need to be escaped; other escapes are optional
toAppendTo.insert(i, '\\');
switch (c) {
case '\b':
toAppendTo.setCharAt(i, '\\');
toAppendTo.insert(i + 1, 'b');
break;
case '\t':
toAppendTo.setCharAt(i, '\\');
toAppendTo.insert(i + 1, 't');
break;
case '\f':
toAppendTo.setCharAt(i, '\\');
toAppendTo.insert(i + 1, 'f');
break;
case '\n':
// Json string newline character must be encoded as literal "\n"
toAppendTo.setCharAt(i, '\\');
toAppendTo.insert(i + 1, 'n');
break;
case '\r':
toAppendTo.setCharAt(i, '\\');
toAppendTo.insert(i + 1, 'r');
break;
case '"':
case '\\':
// only " and \ need to be escaped; other escapes are optional
toAppendTo.insert(i, '\\');
break;
default:
if (Character.isISOControl(c)) {
// all iso control characters are in U+00xx
toAppendTo.setCharAt(i, '\\');
toAppendTo.insert(i + 1, "u0000");
toAppendTo.setCharAt(i + 4, Chars.getUpperCaseHex((c & 0xF0) >> 4));
toAppendTo.setCharAt(i + 5, Chars.getUpperCaseHex(c & 0xF));
}
}
}
}
......
......@@ -94,12 +94,13 @@ public class MapMessageTest {
}
@Test
public void testJSONEscapeNewline() {
final String testMsg = "hello\nworld";
public void testJSONEscapeNewlineAndOtherControlCharacters() {
final String testMsg = "hello\tworld\r\nhh\bere is it\f";
final StringMapMessage msg = new StringMapMessage();
msg.put("one\ntwo", testMsg);
final String result = msg.getFormattedMessage(new String[]{"JSON"});
final String expected = "{\"one\\ntwo\":\"hello\\nworld\"}";
final String expected =
"{\"one\\ntwo\":\"hello\\tworld\\r\\nhh\\bere is it\\f\"}";
assertEquals(expected, result);
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment