Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

14 control flow characters not in 0x0000 0x001f #2329

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 12 additions & 12 deletions gson/src/main/java/com/google/gson/Gson.java
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@
*/
public final class Gson {
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
static final boolean DEFAULT_LENIENT = false;
static final Strictness DEFAULT_STRICTNESS = Strictness.DEFAULT;
static final FormattingStyle DEFAULT_FORMATTING_STYLE = null;
static final boolean DEFAULT_ESCAPE_HTML = true;
static final boolean DEFAULT_SERIALIZE_NULLS = false;
Expand Down Expand Up @@ -184,7 +184,7 @@ public final class Gson {
final boolean generateNonExecutableJson;
final boolean htmlSafe;
final FormattingStyle formattingStyle;
final boolean lenient;
final Strictness strictness;
final boolean serializeSpecialFloatingPointValues;
final boolean useJdkUnsafe;
final String datePattern;
Expand Down Expand Up @@ -237,7 +237,7 @@ public Gson() {
this(Excluder.DEFAULT, DEFAULT_FIELD_NAMING_STRATEGY,
Collections.<Type, InstanceCreator<?>>emptyMap(), DEFAULT_SERIALIZE_NULLS,
DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML,
DEFAULT_FORMATTING_STYLE, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES,
DEFAULT_FORMATTING_STYLE, DEFAULT_STRICTNESS, DEFAULT_SPECIALIZE_FLOAT_VALUES,
DEFAULT_USE_JDK_UNSAFE,
LongSerializationPolicy.DEFAULT, DEFAULT_DATE_PATTERN, DateFormat.DEFAULT, DateFormat.DEFAULT,
Collections.<TypeAdapterFactory>emptyList(), Collections.<TypeAdapterFactory>emptyList(),
Expand All @@ -248,7 +248,7 @@ public Gson() {
Gson(Excluder excluder, FieldNamingStrategy fieldNamingStrategy,
Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
FormattingStyle formattingStyle, boolean lenient, boolean serializeSpecialFloatingPointValues,
FormattingStyle formattingStyle, Strictness strictness, boolean serializeSpecialFloatingPointValues,
boolean useJdkUnsafe,
LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
int timeStyle, List<TypeAdapterFactory> builderFactories,
Expand All @@ -265,7 +265,7 @@ public Gson() {
this.generateNonExecutableJson = generateNonExecutableGson;
this.htmlSafe = htmlSafe;
this.formattingStyle = formattingStyle;
this.lenient = lenient;
this.strictness = strictness;
this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
this.useJdkUnsafe = useJdkUnsafe;
this.longSerializationPolicy = longSerializationPolicy;
Expand Down Expand Up @@ -904,7 +904,7 @@ public JsonWriter newJsonWriter(Writer writer) throws IOException {
JsonWriter jsonWriter = new JsonWriter(writer);
jsonWriter.setFormattingStyle(formattingStyle);
jsonWriter.setHtmlSafe(htmlSafe);
jsonWriter.setLenient(lenient);
jsonWriter.setLenient(this.strictness == Strictness.LENIENT);
jsonWriter.setSerializeNulls(serializeNulls);
return jsonWriter;
}
Expand All @@ -919,7 +919,7 @@ public JsonWriter newJsonWriter(Writer writer) throws IOException {
*/
public JsonReader newJsonReader(Reader reader) {
JsonReader jsonReader = new JsonReader(reader);
jsonReader.setLenient(lenient);
jsonReader.setStrictness(strictness);
return jsonReader;
}

Expand Down Expand Up @@ -1169,7 +1169,7 @@ private static void assertFullConsumption(Object obj, JsonReader reader) {
* <p>Unlike the other {@code fromJson} methods, no exception is thrown if the JSON data has
* multiple top-level JSON elements, or if there is trailing data.
*
* <p>The JSON data is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode},
* <p>//todo: update javadoc The JSON data is parsed in {@linkplain JsonReader # setLenient(boolean) lenient mode},
* regardless of the lenient mode setting of the provided reader. The lenient mode setting
* of the reader is restored once this method returns.
*
Expand Down Expand Up @@ -1198,7 +1198,7 @@ public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, J
* <p>Unlike the other {@code fromJson} methods, no exception is thrown if the JSON data has
* multiple top-level JSON elements, or if there is trailing data.
*
* <p>The JSON data is parsed in {@linkplain JsonReader#setLenient(boolean) lenient mode},
* <p>//todo: update javadoc The JSON data is parsed in {@ linkplain JsonReader#setLenient(boolean) lenient mode},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build fails because there is a whitespace between @ and linkplain.

Should be: @linkplain ...

* regardless of the lenient mode setting of the provided reader. The lenient mode setting
* of the reader is restored once this method returns.
*
Expand All @@ -1220,8 +1220,8 @@ public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, J
*/
public <T> T fromJson(JsonReader reader, TypeToken<T> typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
boolean oldLenient = reader.isLenient();
reader.setLenient(true);
Strictness oldStrictness = reader.getStrictness();
reader.setStrictness(Strictness.LENIENT);
try {
reader.peek();
isEmpty = false;
Expand All @@ -1244,7 +1244,7 @@ public <T> T fromJson(JsonReader reader, TypeToken<T> typeOfT) throws JsonIOExce
} catch (AssertionError e) {
throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
} finally {
reader.setLenient(oldLenient);
reader.setStrictness(oldStrictness);
}
}

Expand Down
29 changes: 13 additions & 16 deletions gson/src/main/java/com/google/gson/GsonBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,6 @@

package com.google.gson;

import static com.google.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS;
import static com.google.gson.Gson.DEFAULT_DATE_PATTERN;
import static com.google.gson.Gson.DEFAULT_ESCAPE_HTML;
import static com.google.gson.Gson.DEFAULT_FORMATTING_STYLE;
import static com.google.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE;
import static com.google.gson.Gson.DEFAULT_LENIENT;
import static com.google.gson.Gson.DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
import static com.google.gson.Gson.DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS;
import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES;
import static com.google.gson.Gson.DEFAULT_USE_JDK_UNSAFE;

import com.google.gson.annotations.Since;
import com.google.gson.annotations.Until;
import com.google.gson.internal.$Gson$Preconditions;
Expand All @@ -50,6 +38,8 @@
import java.util.Map;
import java.util.Objects;

import static com.google.gson.Gson.*;

/**
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
* options other than the default. For {@link Gson} with default configuration, it is simpler to
Expand Down Expand Up @@ -100,7 +90,7 @@ public final class GsonBuilder {
private boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML;
private FormattingStyle formattingStyle = DEFAULT_FORMATTING_STYLE;
private boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE;
private boolean lenient = DEFAULT_LENIENT;
private Strictness strictness = Strictness.DEFAULT;
private boolean useJdkUnsafe = DEFAULT_USE_JDK_UNSAFE;
private ToNumberStrategy objectToNumberStrategy = DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
private ToNumberStrategy numberToNumberStrategy = DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
Expand Down Expand Up @@ -130,7 +120,7 @@ public GsonBuilder() {
this.generateNonExecutableJson = gson.generateNonExecutableJson;
this.escapeHtmlChars = gson.htmlSafe;
this.formattingStyle = gson.formattingStyle;
this.lenient = gson.lenient;
this.strictness = gson.strictness;
this.serializeSpecialFloatingPointValues = gson.serializeSpecialFloatingPointValues;
this.longSerializationPolicy = gson.longSerializationPolicy;
this.datePattern = gson.datePattern;
Expand Down Expand Up @@ -512,7 +502,14 @@ public GsonBuilder setPrettyPrinting(FormattingStyle formattingStyle) {
* @see JsonWriter#setLenient(boolean)
*/
public GsonBuilder setLenient() {
lenient = true;
strictness = Strictness.LENIENT;
return this;
}

// Todo: Add javadoc
public GsonBuilder setStrictness(Strictness strictness) {
Objects.requireNonNull(strictness);
this.strictness = strictness;
return this;
}

Expand Down Expand Up @@ -774,7 +771,7 @@ public Gson create() {

return new Gson(excluder, fieldNamingPolicy, new HashMap<>(instanceCreators),
serializeNulls, complexMapKeySerialization,
generateNonExecutableJson, escapeHtmlChars, formattingStyle, lenient,
generateNonExecutableJson, escapeHtmlChars, formattingStyle, strictness,
serializeSpecialFloatingPointValues, useJdkUnsafe, longSerializationPolicy,
datePattern, dateStyle, timeStyle, new ArrayList<>(this.factories),
new ArrayList<>(this.hierarchyFactories), factories,
Expand Down
7 changes: 7 additions & 0 deletions gson/src/main/java/com/google/gson/Strictness.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.google.gson;

public enum Strictness {
LENIENT,
DEFAULT,
STRICT
}
42 changes: 31 additions & 11 deletions gson/src/main/java/com/google/gson/stream/JsonReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.google.gson.stream;

import com.google.gson.Strictness;
import com.google.gson.internal.JsonReaderInternalAccess;
import com.google.gson.internal.bind.JsonTreeReader;
import java.io.Closeable;
Expand Down Expand Up @@ -227,7 +228,7 @@ public class JsonReader implements Closeable {
private final Reader in;

/** True to accept non-spec compliant JSON */
private boolean lenient = false;
private Strictness strictness = Strictness.DEFAULT;

static final int BUFFER_SIZE = 1024;
/**
Expand Down Expand Up @@ -331,16 +332,26 @@ public JsonReader(Reader in) {
* </ul>
*/
public final void setLenient(boolean lenient) {
this.lenient = lenient;
this.strictness = lenient ? Strictness.LENIENT : Strictness.DEFAULT;
}

/**
* Returns true if this parser is liberal in what it accepts.
*/
public final boolean isLenient() {
return lenient;
return strictness == Strictness.LENIENT;
}

// todo: add javadoc
public final void setStrictness(Strictness strictness) {
Objects.requireNonNull(strictness);
this.strictness = strictness;
}

// todo: add javadoc
public final Strictness getStrictness() {
return strictness;
}
/**
* Consumes the next token from the JSON stream and asserts that it is the
* beginning of a new array.
Expand Down Expand Up @@ -539,7 +550,7 @@ int doPeek() throws IOException {
throw syntaxError("Expected ':'");
}
} else if (peekStack == JsonScope.EMPTY_DOCUMENT) {
if (lenient) {
if (strictness == Strictness.LENIENT) {
consumeNonExecutePrefix();
}
stack[stackSize - 1] = JsonScope.NONEMPTY_DOCUMENT;
Expand Down Expand Up @@ -609,15 +620,17 @@ private int peekKeyword() throws IOException {
String keyword;
String keywordUpper;
int peeking;
if (c == 't' || c == 'T') {

// Uppercase letters are not recognized if strict mode is used.
if (c == 't' || (strictness != Strictness.STRICT && c == 'T')) {
keyword = "true";
keywordUpper = "TRUE";
peeking = PEEKED_TRUE;
} else if (c == 'f' || c == 'F') {
} else if (c == 'f' || (strictness != Strictness.STRICT && c == 'F')) {
keyword = "false";
keywordUpper = "FALSE";
peeking = PEEKED_FALSE;
} else if (c == 'n' || c == 'N') {
} else if (c == 'n' || (strictness != Strictness.STRICT && c == 'N')) {
keyword = "null";
keywordUpper = "NULL";
peeking = PEEKED_NULL;
Expand All @@ -632,7 +645,8 @@ private int peekKeyword() throws IOException {
return PEEKED_NONE;
}
c = buffer[pos + i];
if (c != keyword.charAt(i) && c != keywordUpper.charAt(i)) {
// Again, upper case letters are valid if the strict keyword is used.
if (c != keyword.charAt(i) && (strictness == Strictness.STRICT || c != keywordUpper.charAt(i))) {
return PEEKED_NONE;
}
}
Expand Down Expand Up @@ -920,7 +934,7 @@ public double nextDouble() throws IOException {

peeked = PEEKED_BUFFERED;
double result = Double.parseDouble(peekedString); // don't catch this NumberFormatException.
if (!lenient && (Double.isNaN(result) || Double.isInfinite(result))) {
if (strictness != Strictness.LENIENT && (Double.isNaN(result) || Double.isInfinite(result))) {
throw new MalformedJsonException(
"JSON forbids NaN and infinities: " + result + locationString());
}
Expand Down Expand Up @@ -1007,7 +1021,9 @@ private String nextQuotedValue(char quote) throws IOException {
while (p < l) {
int c = buffer[p++];

if (c == quote) {
if (strictness == Strictness.STRICT && c <= '\u001F') {
throw syntaxError("Unescaped control characters (\\u0000-\\u001F) are not allowed in strict mode.");
} else if (c == quote) {
pos = p;
int len = p - start - 1;
if (builder == null) {
Expand Down Expand Up @@ -1461,7 +1477,7 @@ private int nextNonWhitespace(boolean throwOnEof) throws IOException {
}

private void checkLenient() throws IOException {
if (!lenient) {
if (strictness != Strictness.LENIENT) {
throw syntaxError("Use JsonReader.setLenient(true) to accept malformed JSON");
}
}
Expand Down Expand Up @@ -1636,11 +1652,15 @@ private char readEscapeCharacter() throws IOException {
return '\f';

case '\n':
if (strictness == Strictness.STRICT) {
throw syntaxError("Cannot espace a newline character in strict mode!");
}
lineNumber++;
lineStart = pos;
// fall-through

case '\'':
if (strictness == Strictness.STRICT) throw syntaxError("Invalid escaped character \"'\" in strict mode");
case '"':
case '\\':
case '/':
Expand Down
4 changes: 2 additions & 2 deletions gson/src/test/java/com/google/gson/GsonTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public final class GsonTest {
public void testOverridesDefaultExcluder() {
Gson gson = new Gson(CUSTOM_EXCLUDER, CUSTOM_FIELD_NAMING_STRATEGY,
new HashMap<Type, InstanceCreator<?>>(), true, false, true, false,
FormattingStyle.DEFAULT, true, false, true,
FormattingStyle.DEFAULT, Strictness.LENIENT, false, true,
LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
DateFormat.DEFAULT, new ArrayList<TypeAdapterFactory>(),
new ArrayList<TypeAdapterFactory>(), new ArrayList<TypeAdapterFactory>(),
Expand All @@ -80,7 +80,7 @@ public void testOverridesDefaultExcluder() {
public void testClonedTypeAdapterFactoryListsAreIndependent() {
Gson original = new Gson(CUSTOM_EXCLUDER, CUSTOM_FIELD_NAMING_STRATEGY,
new HashMap<Type, InstanceCreator<?>>(), true, false, true, false,
FormattingStyle.DEFAULT, true, false, true,
FormattingStyle.DEFAULT, Strictness.LENIENT, false, true,
LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
DateFormat.DEFAULT, new ArrayList<TypeAdapterFactory>(),
new ArrayList<TypeAdapterFactory>(), new ArrayList<TypeAdapterFactory>(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public JsonElement deepCopy() {
*/
@Test
public void testOverrides() {
List<String> ignoredMethods = Arrays.asList("setLenient(boolean)", "isLenient()");
List<String> ignoredMethods = Arrays.asList("setLenient(boolean)", "isLenient()", "setStrictness(com.google.gson.Strictness)", "getStrictness()");
MoreAsserts.assertOverridesMethods(JsonReader.class, JsonTreeReader.class, ignoredMethods);
}
}