Escape current character output
ci/woodpecker/push/woodpecker Pipeline was successful
Details
ci/woodpecker/push/woodpecker Pipeline was successful
Details
This commit is contained in:
parent
ff4b1a7656
commit
57b2e54b5a
|
@ -22,6 +22,8 @@ import com.google.gson.Strictness;
|
||||||
import com.google.gson.internal.DefaultConfig;
|
import com.google.gson.internal.DefaultConfig;
|
||||||
import com.google.gson.internal.JsonReaderInternalAccess;
|
import com.google.gson.internal.JsonReaderInternalAccess;
|
||||||
import com.google.gson.internal.TroubleshootingGuide;
|
import com.google.gson.internal.TroubleshootingGuide;
|
||||||
|
import com.google.gson.util.StringEscapeUtil;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -1611,7 +1613,11 @@ public class JsonReader implements Closeable {
|
||||||
private String locationString() {
|
private String locationString() {
|
||||||
int line = lineNumber + 1;
|
int line = lineNumber + 1;
|
||||||
int column = pos - lineStart + 1;
|
int column = pos - lineStart + 1;
|
||||||
String charInterjection = pos < buffer.length ? " (char '" + buffer[pos] + "')" : "";
|
String replacement = StringEscapeUtil.getReplacement(buffer[pos]);
|
||||||
|
if (replacement == null) {
|
||||||
|
replacement = String.valueOf(buffer[pos]);
|
||||||
|
}
|
||||||
|
String charInterjection = pos < buffer.length ? " (char '" + replacement + "')" : "";
|
||||||
return " at line " + line + " column " + column + charInterjection + " path " + getPath();
|
return " at line " + line + " column " + column + charInterjection + " path " + getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ import com.google.gson.FormattingStyle;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.Strictness;
|
import com.google.gson.Strictness;
|
||||||
|
import com.google.gson.util.StringEscapeUtil;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.Flushable;
|
import java.io.Flushable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -166,39 +168,6 @@ public class JsonWriter implements Closeable, Flushable {
|
||||||
private static final Pattern VALID_JSON_NUMBER_PATTERN =
|
private static final Pattern VALID_JSON_NUMBER_PATTERN =
|
||||||
Pattern.compile("-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][-+]?[0-9]+)?");
|
Pattern.compile("-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][-+]?[0-9]+)?");
|
||||||
|
|
||||||
/*
|
|
||||||
* From RFC 8259, "All Unicode characters may be placed within the
|
|
||||||
* quotation marks except for the characters that must be escaped:
|
|
||||||
* quotation mark, reverse solidus, and the control characters
|
|
||||||
* (U+0000 through U+001F)."
|
|
||||||
*
|
|
||||||
* We also escape '\u2028' and '\u2029', which JavaScript interprets as
|
|
||||||
* newline characters. This prevents eval() from failing with a syntax
|
|
||||||
* error. http://code.google.com/p/google-gson/issues/detail?id=341
|
|
||||||
*/
|
|
||||||
private static final String[] REPLACEMENT_CHARS;
|
|
||||||
private static final String[] HTML_SAFE_REPLACEMENT_CHARS;
|
|
||||||
|
|
||||||
static {
|
|
||||||
REPLACEMENT_CHARS = new String[128];
|
|
||||||
for (int i = 0; i <= 0x1f; i++) {
|
|
||||||
REPLACEMENT_CHARS[i] = String.format("\\u%04x", i);
|
|
||||||
}
|
|
||||||
REPLACEMENT_CHARS['"'] = "\\\"";
|
|
||||||
REPLACEMENT_CHARS['\\'] = "\\\\";
|
|
||||||
REPLACEMENT_CHARS['\t'] = "\\t";
|
|
||||||
REPLACEMENT_CHARS['\b'] = "\\b";
|
|
||||||
REPLACEMENT_CHARS['\n'] = "\\n";
|
|
||||||
REPLACEMENT_CHARS['\r'] = "\\r";
|
|
||||||
REPLACEMENT_CHARS['\f'] = "\\f";
|
|
||||||
HTML_SAFE_REPLACEMENT_CHARS = REPLACEMENT_CHARS.clone();
|
|
||||||
HTML_SAFE_REPLACEMENT_CHARS['<'] = "\\u003c";
|
|
||||||
HTML_SAFE_REPLACEMENT_CHARS['>'] = "\\u003e";
|
|
||||||
HTML_SAFE_REPLACEMENT_CHARS['&'] = "\\u0026";
|
|
||||||
HTML_SAFE_REPLACEMENT_CHARS['='] = "\\u003d";
|
|
||||||
HTML_SAFE_REPLACEMENT_CHARS['\''] = "\\u0027";
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The JSON output destination */
|
/** The JSON output destination */
|
||||||
private final Writer out;
|
private final Writer out;
|
||||||
|
|
||||||
|
@ -794,23 +763,13 @@ public class JsonWriter implements Closeable, Flushable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void string(String value) throws IOException {
|
private void string(String value) throws IOException {
|
||||||
String[] replacements = htmlSafe ? HTML_SAFE_REPLACEMENT_CHARS : REPLACEMENT_CHARS;
|
|
||||||
out.write('\"');
|
out.write('\"');
|
||||||
int last = 0;
|
int last = 0;
|
||||||
int length = value.length();
|
int length = value.length();
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
char c = value.charAt(i);
|
char c = value.charAt(i);
|
||||||
String replacement;
|
String replacement = htmlSafe ? StringEscapeUtil.getHtmlSafeReplacement(c) : StringEscapeUtil.getReplacement(c);
|
||||||
if (c < 128) {
|
if (replacement == null) {
|
||||||
replacement = replacements[c];
|
|
||||||
if (replacement == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (c == '\u2028') {
|
|
||||||
replacement = "\\u2028";
|
|
||||||
} else if (c == '\u2029') {
|
|
||||||
replacement = "\\u2029";
|
|
||||||
} else {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (last < i) {
|
if (last < i) {
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
package com.google.gson.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities methods for escaping strings, extracted from gsons JsonWriter.
|
||||||
|
* @author JFronny
|
||||||
|
*/
|
||||||
|
public class StringEscapeUtil {
|
||||||
|
private StringEscapeUtil() {}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* From RFC 8259, "All Unicode characters may be placed within the
|
||||||
|
* quotation marks except for the characters that must be escaped:
|
||||||
|
* quotation mark, reverse solidus, and the control characters
|
||||||
|
* (U+0000 through U+001F)."
|
||||||
|
*
|
||||||
|
* We also escape '\u2028' and '\u2029', which JavaScript interprets as
|
||||||
|
* newline characters. This prevents eval() from failing with a syntax
|
||||||
|
* error. http://code.google.com/p/google-gson/issues/detail?id=341
|
||||||
|
*/
|
||||||
|
private static final String[] REPLACEMENT_CHARS;
|
||||||
|
private static final String[] HTML_SAFE_REPLACEMENT_CHARS;
|
||||||
|
|
||||||
|
static {
|
||||||
|
REPLACEMENT_CHARS = new String[128];
|
||||||
|
for (int i = 0; i <= 0x1f; i++) {
|
||||||
|
REPLACEMENT_CHARS[i] = String.format("\\u%04x", i);
|
||||||
|
}
|
||||||
|
REPLACEMENT_CHARS['"'] = "\\\"";
|
||||||
|
REPLACEMENT_CHARS['\\'] = "\\\\";
|
||||||
|
REPLACEMENT_CHARS['\t'] = "\\t";
|
||||||
|
REPLACEMENT_CHARS['\b'] = "\\b";
|
||||||
|
REPLACEMENT_CHARS['\n'] = "\\n";
|
||||||
|
REPLACEMENT_CHARS['\r'] = "\\r";
|
||||||
|
REPLACEMENT_CHARS['\f'] = "\\f";
|
||||||
|
REPLACEMENT_CHARS['\0'] = "\\0";
|
||||||
|
HTML_SAFE_REPLACEMENT_CHARS = REPLACEMENT_CHARS.clone();
|
||||||
|
HTML_SAFE_REPLACEMENT_CHARS['<'] = "\\u003c";
|
||||||
|
HTML_SAFE_REPLACEMENT_CHARS['>'] = "\\u003e";
|
||||||
|
HTML_SAFE_REPLACEMENT_CHARS['&'] = "\\u0026";
|
||||||
|
HTML_SAFE_REPLACEMENT_CHARS['='] = "\\u003d";
|
||||||
|
HTML_SAFE_REPLACEMENT_CHARS['\''] = "\\u0027";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getReplacement(char c, String[] replacements) {
|
||||||
|
String replacement;
|
||||||
|
if (c < 128) {
|
||||||
|
replacement = replacements[c];
|
||||||
|
if (replacement == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else if (c == '\u2028') {
|
||||||
|
replacement = "\\u2028";
|
||||||
|
} else if (c == '\u2029') {
|
||||||
|
replacement = "\\u2029";
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the replacement for the character, or null if the character does not need to be escaped.
|
||||||
|
* @param c the character to escape
|
||||||
|
* @return the replacement for the character, or null if the character does not need to be escaped
|
||||||
|
* @see #getHtmlSafeReplacement(char)
|
||||||
|
*/
|
||||||
|
public static String getReplacement(char c) {
|
||||||
|
return getReplacement(c, REPLACEMENT_CHARS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the replacement for the character, or null if the character does not need to be escaped.
|
||||||
|
* @param c the character to escape
|
||||||
|
* @return the replacement for the character, or null if the character does not need to be escaped
|
||||||
|
* @see #getReplacement(char)
|
||||||
|
*/
|
||||||
|
public static String getHtmlSafeReplacement(char c) {
|
||||||
|
return getReplacement(c, HTML_SAFE_REPLACEMENT_CHARS);
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,7 +40,7 @@ public class ToNumberPolicyTest {
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"JSON forbids NaN and infinities: Infinity at line 1 column 6 (char '\0') path $\n"
|
"JSON forbids NaN and infinities: Infinity at line 1 column 6 (char '\\0') path $\n"
|
||||||
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json");
|
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json");
|
||||||
|
|
||||||
assertThrows(
|
assertThrows(
|
||||||
|
@ -133,7 +133,7 @@ public class ToNumberPolicyTest {
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"Expected a double but was NULL at line 1 column 5 (char '\0') path $\n"
|
"Expected a double but was NULL at line 1 column 5 (char '\\0') path $\n"
|
||||||
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#adapter-not-null-safe");
|
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#adapter-not-null-safe");
|
||||||
|
|
||||||
e =
|
e =
|
||||||
|
@ -143,7 +143,7 @@ public class ToNumberPolicyTest {
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"Expected a string but was NULL at line 1 column 5 (char '\0') path $\n"
|
"Expected a string but was NULL at line 1 column 5 (char '\\0') path $\n"
|
||||||
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#adapter-not-null-safe");
|
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#adapter-not-null-safe");
|
||||||
|
|
||||||
e =
|
e =
|
||||||
|
@ -153,7 +153,7 @@ public class ToNumberPolicyTest {
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"Expected a string but was NULL at line 1 column 5 (char '\0') path $\n"
|
"Expected a string but was NULL at line 1 column 5 (char '\\0') path $\n"
|
||||||
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#adapter-not-null-safe");
|
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#adapter-not-null-safe");
|
||||||
|
|
||||||
e =
|
e =
|
||||||
|
@ -163,7 +163,7 @@ public class ToNumberPolicyTest {
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"Expected a string but was NULL at line 1 column 5 (char '\0') path $\n"
|
"Expected a string but was NULL at line 1 column 5 (char '\\0') path $\n"
|
||||||
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#adapter-not-null-safe");
|
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#adapter-not-null-safe");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class PrimitiveTest {
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"java.lang.NumberFormatException: Expected an int but was 2147483648"
|
"java.lang.NumberFormatException: Expected an int but was 2147483648"
|
||||||
+ " at line 1 column 11 (char '\0') path $");
|
+ " at line 1 column 11 (char '\\0') path $");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -140,7 +140,7 @@ public class PrimitiveTest {
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"java.lang.NumberFormatException: Expected an int but was 2147483648"
|
"java.lang.NumberFormatException: Expected an int but was 2147483648"
|
||||||
+ " at line 1 column 11 (char '\0') path $");
|
+ " at line 1 column 11 (char '\\0') path $");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -915,7 +915,7 @@ public class PrimitiveTest {
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasCauseThat()
|
.hasCauseThat()
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo("Expected an int but was -122.08e-213 at line 1 column 13 (char '\0') path $");
|
.isEqualTo("Expected an int but was -122.08e-213 at line 1 column 13 (char '\\0') path $");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -926,7 +926,7 @@ public class PrimitiveTest {
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasCauseThat()
|
.hasCauseThat()
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo("Expected an int but was " + number + " at line 1 column 57 (char '\0') path $");
|
.isEqualTo("Expected an int but was " + number + " at line 1 column 57 (char '\\0') path $");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -937,7 +937,7 @@ public class PrimitiveTest {
|
||||||
assertThat(e)
|
assertThat(e)
|
||||||
.hasCauseThat()
|
.hasCauseThat()
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo("Expected a long but was " + number + " at line 1 column 57 (char '\0') path $");
|
.isEqualTo("Expected a long but was " + number + " at line 1 column 57 (char '\\0') path $");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1175,27 +1175,27 @@ public final class JsonReaderTest {
|
||||||
fail();
|
fail();
|
||||||
} catch (IllegalStateException expected) {
|
} catch (IllegalStateException expected) {
|
||||||
assertUnexpectedStructureError(
|
assertUnexpectedStructureError(
|
||||||
expected, "a string", "END_OBJECT", "line 1 column 11 (char '\0') path $.a");
|
expected, "a string", "END_OBJECT", "line 1 column 11 (char '\\0') path $.a");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
reader.nextName();
|
reader.nextName();
|
||||||
fail();
|
fail();
|
||||||
} catch (IllegalStateException expected) {
|
} catch (IllegalStateException expected) {
|
||||||
assertUnexpectedStructureError(expected, "a name", "END_OBJECT", "line 1 column 11 (char '\0') path $.a");
|
assertUnexpectedStructureError(expected, "a name", "END_OBJECT", "line 1 column 11 (char '\\0') path $.a");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
fail();
|
fail();
|
||||||
} catch (IllegalStateException expected) {
|
} catch (IllegalStateException expected) {
|
||||||
assertUnexpectedStructureError(
|
assertUnexpectedStructureError(
|
||||||
expected, "BEGIN_ARRAY", "END_OBJECT", "line 1 column 11 (char '\0') path $.a");
|
expected, "BEGIN_ARRAY", "END_OBJECT", "line 1 column 11 (char '\\0') path $.a");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
fail();
|
fail();
|
||||||
} catch (IllegalStateException expected) {
|
} catch (IllegalStateException expected) {
|
||||||
assertUnexpectedStructureError(
|
assertUnexpectedStructureError(
|
||||||
expected, "END_ARRAY", "END_OBJECT", "line 1 column 11 (char '\0') path $.a");
|
expected, "END_ARRAY", "END_OBJECT", "line 1 column 11 (char '\\0') path $.a");
|
||||||
}
|
}
|
||||||
reader.endObject();
|
reader.endObject();
|
||||||
assertThat(reader.peek()).isEqualTo(JsonToken.END_DOCUMENT);
|
assertThat(reader.peek()).isEqualTo(JsonToken.END_DOCUMENT);
|
||||||
|
@ -1623,7 +1623,7 @@ public final class JsonReaderTest {
|
||||||
reader.nextNull();
|
reader.nextNull();
|
||||||
fail();
|
fail();
|
||||||
} catch (IllegalStateException expected) {
|
} catch (IllegalStateException expected) {
|
||||||
assertThat(expected).hasMessageThat().startsWith("Expected null but was END_ARRAY at line 1 column 8 (char '\0') path $[1]");
|
assertThat(expected).hasMessageThat().startsWith("Expected null but was END_ARRAY at line 1 column 8 (char '\\0') path $[1]");
|
||||||
}
|
}
|
||||||
|
|
||||||
reader = new JsonReader(reader("[,]"));
|
reader = new JsonReader(reader("[,]"));
|
||||||
|
@ -2109,7 +2109,7 @@ public final class JsonReaderTest {
|
||||||
assertThat(expected)
|
assertThat(expected)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"Unterminated object at x at line 1 column 16 (char '\0') path $.a\n"
|
"Unterminated object at x at line 1 column 16 (char '\\0') path $.a\n"
|
||||||
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json");
|
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2241,7 +2241,7 @@ public final class JsonReaderTest {
|
||||||
assertThat(expected)
|
assertThat(expected)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"Expected name at line 1 column 11 (char '\0') path $.a\n"
|
"Expected name at line 1 column 11 (char '\\0') path $.a\n"
|
||||||
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json");
|
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2260,7 +2260,7 @@ public final class JsonReaderTest {
|
||||||
assertThat(expected)
|
assertThat(expected)
|
||||||
.hasMessageThat()
|
.hasMessageThat()
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
"Expected name at line 1 column 11 (char '\0') path $.a\n"
|
"Expected name at line 1 column 11 (char '\\0') path $.a\n"
|
||||||
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json");
|
+ "See https://github.com/google/gson/blob/main/Troubleshooting.md#malformed-json");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -698,7 +698,7 @@ public final class JsonWriterTest {
|
||||||
+ "\"}\","
|
+ "\"}\","
|
||||||
+ "\"[\","
|
+ "\"[\","
|
||||||
+ "\"]\","
|
+ "\"]\","
|
||||||
+ "\"\\u0000\","
|
+ "\"\\0\","
|
||||||
+ "\"\\u0019\"]");
|
+ "\"\\u0019\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue