Implemented enhancement request from issue 42 by supporting a new GsonBuilder setting generateNonExecutableJson() that prefixes the generated JSON with some special text that makes the output non-executable javascript. Gson now recognizes this special text in the input while parsing the JSON in fromJson and filters it out, if present.

This commit is contained in:
Inderjeet Singh 2009-03-17 21:15:10 +00:00
parent 1c5785be57
commit b2b2e5dc0a
7 changed files with 271 additions and 73 deletions

View File

@ -76,6 +76,8 @@ public final class Gson {
private static final String NULL_STRING = "null"; private static final String NULL_STRING = "null";
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
// Default instances of plug-ins // Default instances of plug-ins
static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY = static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY =
new ModifierBasedExclusionStrategy(true, new int[] { Modifier.TRANSIENT, Modifier.STATIC }); new ModifierBasedExclusionStrategy(true, new int[] { Modifier.TRANSIENT, Modifier.STATIC });
@ -83,6 +85,8 @@ public final class Gson {
static final FieldNamingStrategy DEFAULT_NAMING_POLICY = static final FieldNamingStrategy DEFAULT_NAMING_POLICY =
new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy()); new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy());
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n<data>";
private final ExclusionStrategy strategy; private final ExclusionStrategy strategy;
private final FieldNamingStrategy fieldNamingPolicy; private final FieldNamingStrategy fieldNamingPolicy;
private final MappedObjectConstructor objectConstructor; private final MappedObjectConstructor objectConstructor;
@ -96,6 +100,8 @@ public final class Gson {
private final JsonFormatter formatter; private final JsonFormatter formatter;
private final boolean serializeNulls; private final boolean serializeNulls;
private final boolean generateNonExecutableJson;
/** /**
* Constructs a Gson object with default configuration. The default configuration has the * Constructs a Gson object with default configuration. The default configuration has the
* following settings: * following settings:
@ -142,13 +148,14 @@ public final class Gson {
this(strategy, fieldNamingPolicy, this(strategy, fieldNamingPolicy,
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()), new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
DEFAULT_JSON_FORMATTER, false, DefaultTypeAdapters.getDefaultSerializers(), DEFAULT_JSON_FORMATTER, false, DefaultTypeAdapters.getDefaultSerializers(),
DefaultTypeAdapters.getDefaultDeserializers()); DefaultTypeAdapters.getDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE);
} }
Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy, Gson(ExclusionStrategy strategy, FieldNamingStrategy fieldNamingPolicy,
MappedObjectConstructor objectConstructor, JsonFormatter formatter, boolean serializeNulls, MappedObjectConstructor objectConstructor, JsonFormatter formatter, boolean serializeNulls,
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers, ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers) { ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
boolean generateNonExecutableGson) {
this.strategy = strategy; this.strategy = strategy;
this.fieldNamingPolicy = fieldNamingPolicy; this.fieldNamingPolicy = fieldNamingPolicy;
this.objectConstructor = objectConstructor; this.objectConstructor = objectConstructor;
@ -156,6 +163,7 @@ public final class Gson {
this.serializeNulls = serializeNulls; this.serializeNulls = serializeNulls;
this.serializers = serializers; this.serializers = serializers;
this.deserializers = deserializers; this.deserializers = deserializers;
this.generateNonExecutableJson = generateNonExecutableGson;
} }
private ObjectNavigatorFactory createDefaultObjectNavigatorFactory() { private ObjectNavigatorFactory createDefaultObjectNavigatorFactory() {
@ -260,6 +268,9 @@ public final class Gson {
createDefaultObjectNavigatorFactory(), serializeNulls, serializers); createDefaultObjectNavigatorFactory(), serializeNulls, serializers);
JsonElement jsonElement = context.serialize(src, typeOfSrc); JsonElement jsonElement = context.serialize(src, typeOfSrc);
if (generateNonExecutableJson) {
writer.append(JSON_NON_EXECUTABLE_PREFIX);
}
//TODO(Joel): instead of navigating the "JsonElement" inside the formatter, do it here. //TODO(Joel): instead of navigating the "JsonElement" inside the formatter, do it here.
formatter.format(jsonElement, writer, serializeNulls); formatter.format(jsonElement, writer, serializeNulls);
} else { } else {

View File

@ -73,6 +73,7 @@ public final class GsonBuilder {
private boolean serializeSpecialFloatingPointValues; private boolean serializeSpecialFloatingPointValues;
private boolean escapeHtmlChars; private boolean escapeHtmlChars;
private boolean prettyPrinting; private boolean prettyPrinting;
private boolean generateNonExecutableJson;
/** /**
* Creates a GsonBuilder instance that can be used to build Gson with various configuration * Creates a GsonBuilder instance that can be used to build Gson with various configuration
@ -97,6 +98,7 @@ public final class GsonBuilder {
dateStyle = DateFormat.DEFAULT; dateStyle = DateFormat.DEFAULT;
timeStyle = DateFormat.DEFAULT; timeStyle = DateFormat.DEFAULT;
serializeSpecialFloatingPointValues = false; serializeSpecialFloatingPointValues = false;
generateNonExecutableJson = false;
} }
/** /**
@ -128,6 +130,20 @@ public final class GsonBuilder {
return this; return this;
} }
/**
* Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
* special text. This prevents attacks from third-party sites through script sourcing. See
* <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
* for details.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder generateNonExecutableJson() {
this.generateNonExecutableJson = true;
return this;
}
/** /**
* Configures Gson to exclude all fields from consideration for serialization or deserialization * Configures Gson to exclude all fields from consideration for serialization or deserialization
* that do not have the {@link com.google.gson.annotations.Expose} annotation. * that do not have the {@link com.google.gson.annotations.Expose} annotation.
@ -430,7 +446,7 @@ public final class GsonBuilder {
JsonFormatter formatter = prettyPrinting ? JsonFormatter formatter = prettyPrinting ?
new JsonPrintFormatter(escapeHtmlChars) : new JsonCompactFormatter(escapeHtmlChars); new JsonPrintFormatter(escapeHtmlChars) : new JsonCompactFormatter(escapeHtmlChars);
Gson gson = new Gson(exclusionStrategy, fieldNamingPolicy, objConstructor, Gson gson = new Gson(exclusionStrategy, fieldNamingPolicy, objConstructor,
formatter, serializeNulls, customSerializers, customDeserializers); formatter, serializeNulls, customSerializers, customDeserializers, generateNonExecutableJson);
return gson; return gson;
} }

View File

@ -8,9 +8,17 @@ final class JsonParserImpl implements JsonParserImplConstants {
JsonElement json = null; JsonElement json = null;
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 26: case 26:
jj_consume_token(26);
break;
default:
jj_la1[0] = jj_gen;
;
}
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 27:
json = JsonObject(); json = JsonObject();
break; break;
case 30: case 31:
json = JsonArray(); json = JsonArray();
break; break;
case DIGITS: case DIGITS:
@ -19,14 +27,14 @@ final class JsonParserImpl implements JsonParserImplConstants {
case BOOLEAN: case BOOLEAN:
case SINGLE_QUOTE_LITERAL: case SINGLE_QUOTE_LITERAL:
case DOUBLE_QUOTE_LITERAL: case DOUBLE_QUOTE_LITERAL:
case 32: case 33:
json = JsonPrimitive(); json = JsonPrimitive();
break; break;
case NULL: case NULL:
json = JsonNull(); json = JsonNull();
break; break;
default: default:
jj_la1[0] = jj_gen; jj_la1[1] = jj_gen;
jj_consume_token(-1); jj_consume_token(-1);
throw new ParseException(); throw new ParseException();
} }
@ -36,7 +44,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
final private JsonObject JsonObject() throws ParseException { final private JsonObject JsonObject() throws ParseException {
JsonObject o = new JsonObject(); JsonObject o = new JsonObject();
jj_consume_token(26); jj_consume_token(27);
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case IDENTIFIER_SANS_EXPONENT: case IDENTIFIER_SANS_EXPONENT:
case IDENTIFIER_STARTS_WITH_EXPONENT: case IDENTIFIER_STARTS_WITH_EXPONENT:
@ -45,10 +53,10 @@ final class JsonParserImpl implements JsonParserImplConstants {
Members(o); Members(o);
break; break;
default: default:
jj_la1[1] = jj_gen; jj_la1[2] = jj_gen;
; ;
} }
jj_consume_token(27); jj_consume_token(28);
{if (true) return o;} {if (true) return o;}
throw new Error("Missing return statement in function"); throw new Error("Missing return statement in function");
} }
@ -63,12 +71,12 @@ final class JsonParserImpl implements JsonParserImplConstants {
final private void Members(JsonObject o) throws ParseException { final private void Members(JsonObject o) throws ParseException {
Pair(o); Pair(o);
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 28: case 29:
jj_consume_token(28); jj_consume_token(29);
Members(o); Members(o);
break; break;
default: default:
jj_la1[2] = jj_gen; jj_la1[3] = jj_gen;
; ;
} }
} }
@ -77,7 +85,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
JsonPrimitive property; JsonPrimitive property;
JsonElement value; JsonElement value;
property = JsonMemberName(); property = JsonMemberName();
jj_consume_token(29); jj_consume_token(30);
value = JsonValue(); value = JsonValue();
o.add(property.getAsString(), value); o.add(property.getAsString(), value);
} }
@ -96,7 +104,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
{if (true) return value;} {if (true) return value;}
break; break;
default: default:
jj_la1[3] = jj_gen; jj_la1[4] = jj_gen;
jj_consume_token(-1); jj_consume_token(-1);
throw new ParseException(); throw new ParseException();
} }
@ -105,7 +113,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
final private JsonArray JsonArray() throws ParseException { final private JsonArray JsonArray() throws ParseException {
JsonArray array = new JsonArray(); JsonArray array = new JsonArray();
jj_consume_token(30); jj_consume_token(31);
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case DIGITS: case DIGITS:
case NULL: case NULL:
@ -114,16 +122,16 @@ final class JsonParserImpl implements JsonParserImplConstants {
case BOOLEAN: case BOOLEAN:
case SINGLE_QUOTE_LITERAL: case SINGLE_QUOTE_LITERAL:
case DOUBLE_QUOTE_LITERAL: case DOUBLE_QUOTE_LITERAL:
case 26: case 27:
case 30: case 31:
case 32: case 33:
Elements(array); Elements(array);
break; break;
default: default:
jj_la1[4] = jj_gen; jj_la1[5] = jj_gen;
; ;
} }
jj_consume_token(31); jj_consume_token(32);
array.reverse(); array.reverse();
{if (true) return array;} {if (true) return array;}
throw new Error("Missing return statement in function"); throw new Error("Missing return statement in function");
@ -133,12 +141,12 @@ final class JsonParserImpl implements JsonParserImplConstants {
JsonElement element; JsonElement element;
element = JsonValue(); element = JsonValue();
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 28: case 29:
jj_consume_token(28); jj_consume_token(29);
Elements(array); Elements(array);
break; break;
default: default:
jj_la1[5] = jj_gen; jj_la1[6] = jj_gen;
; ;
} }
array.add(element); array.add(element);
@ -154,13 +162,13 @@ final class JsonParserImpl implements JsonParserImplConstants {
case DIGITS: case DIGITS:
case NAN: case NAN:
case INFINITY: case INFINITY:
case 32: case 33:
o = JsonNumber(); o = JsonNumber();
break; break;
case 26: case 27:
o = JsonObject(); o = JsonObject();
break; break;
case 30: case 31:
o = JsonArray(); o = JsonArray();
break; break;
case BOOLEAN: case BOOLEAN:
@ -170,7 +178,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
o = JsonNull(); o = JsonNull();
break; break;
default: default:
jj_la1[6] = jj_gen; jj_la1[7] = jj_gen;
jj_consume_token(-1); jj_consume_token(-1);
throw new ParseException(); throw new ParseException();
} }
@ -197,7 +205,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
case DIGITS: case DIGITS:
case NAN: case NAN:
case INFINITY: case INFINITY:
case 32: case 33:
value = JsonNumber(); value = JsonNumber();
{if (true) return value;} {if (true) return value;}
break; break;
@ -206,7 +214,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
{if (true) return value;} {if (true) return value;}
break; break;
default: default:
jj_la1[7] = jj_gen; jj_la1[8] = jj_gen;
jj_consume_token(-1); jj_consume_token(-1);
throw new ParseException(); throw new ParseException();
} }
@ -224,14 +232,14 @@ final class JsonParserImpl implements JsonParserImplConstants {
} else { } else {
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case DIGITS: case DIGITS:
case 32: case 33:
intpart = JsonInt(); intpart = JsonInt();
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 33: case 34:
fracpart = JsonFrac(); fracpart = JsonFrac();
break; break;
default: default:
jj_la1[8] = jj_gen; jj_la1[9] = jj_gen;
; ;
} }
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
@ -239,7 +247,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
exppart = JsonExp(); exppart = JsonExp();
break; break;
default: default:
jj_la1[9] = jj_gen; jj_la1[10] = jj_gen;
; ;
} }
Number n; Number n;
@ -253,7 +261,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
{if (true) return new JsonPrimitive(n);} {if (true) return new JsonPrimitive(n);}
break; break;
default: default:
jj_la1[10] = jj_gen; jj_la1[11] = jj_gen;
jj_consume_token(-1); jj_consume_token(-1);
throw new ParseException(); throw new ParseException();
} }
@ -269,21 +277,21 @@ final class JsonParserImpl implements JsonParserImplConstants {
{if (true) return new JsonPrimitive(Double.NaN);} {if (true) return new JsonPrimitive(Double.NaN);}
break; break;
case INFINITY: case INFINITY:
case 32: case 33:
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 32: case 33:
jj_consume_token(32); jj_consume_token(33);
negative = true; negative = true;
break; break;
default: default:
jj_la1[11] = jj_gen; jj_la1[12] = jj_gen;
; ;
} }
jj_consume_token(INFINITY); jj_consume_token(INFINITY);
{if (true) return new JsonPrimitive(negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);} {if (true) return new JsonPrimitive(negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY);}
break; break;
default: default:
jj_la1[12] = jj_gen; jj_la1[13] = jj_gen;
jj_consume_token(-1); jj_consume_token(-1);
throw new ParseException(); throw new ParseException();
} }
@ -294,12 +302,12 @@ final class JsonParserImpl implements JsonParserImplConstants {
String digits; String digits;
boolean negative = false; boolean negative = false;
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 32: case 33:
jj_consume_token(32); jj_consume_token(33);
negative = true; negative = true;
break; break;
default: default:
jj_la1[13] = jj_gen; jj_la1[14] = jj_gen;
; ;
} }
digits = Digits(); digits = Digits();
@ -311,7 +319,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
final private String JsonFrac() throws ParseException { final private String JsonFrac() throws ParseException {
String digits; String digits;
jj_consume_token(33); jj_consume_token(34);
digits = Digits(); digits = Digits();
{if (true) return "." + digits;} {if (true) return "." + digits;}
throw new Error("Missing return statement in function"); throw new Error("Missing return statement in function");
@ -334,7 +342,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
t = jj_consume_token(IDENTIFIER_SANS_EXPONENT); t = jj_consume_token(IDENTIFIER_SANS_EXPONENT);
break; break;
default: default:
jj_la1[14] = jj_gen; jj_la1[15] = jj_gen;
jj_consume_token(-1); jj_consume_token(-1);
throw new ParseException(); throw new ParseException();
} }
@ -359,7 +367,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
t = jj_consume_token(DOUBLE_QUOTE_LITERAL); t = jj_consume_token(DOUBLE_QUOTE_LITERAL);
break; break;
default: default:
jj_la1[15] = jj_gen; jj_la1[16] = jj_gen;
jj_consume_token(-1); jj_consume_token(-1);
throw new ParseException(); throw new ParseException();
} }
@ -376,7 +384,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
} }
private boolean jj_3R_4() { private boolean jj_3R_4() {
if (jj_scan_token(32)) return true; if (jj_scan_token(33)) return true;
return false; return false;
} }
@ -419,7 +427,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
private Token jj_scanpos, jj_lastpos; private Token jj_scanpos, jj_lastpos;
private int jj_la; private int jj_la;
private int jj_gen; private int jj_gen;
final private int[] jj_la1 = new int[16]; final private int[] jj_la1 = new int[17];
static private int[] jj_la1_0; static private int[] jj_la1_0;
static private int[] jj_la1_1; static private int[] jj_la1_1;
static { static {
@ -427,10 +435,10 @@ final class JsonParserImpl implements JsonParserImplConstants {
jj_la1_init_1(); jj_la1_init_1();
} }
private static void jj_la1_init_0() { private static void jj_la1_init_0() {
jj_la1_0 = new int[] {0x440307c0,0x31800,0x10000000,0x31800,0x440307c0,0x10000000,0x440307c0,0x30740,0x0,0x20,0x40,0x0,0x300,0x0,0x1800,0x30000,}; jj_la1_0 = new int[] {0x4000000,0x880307c0,0x31800,0x20000000,0x31800,0x880307c0,0x20000000,0x880307c0,0x30740,0x0,0x20,0x40,0x0,0x300,0x0,0x1800,0x30000,};
} }
private static void jj_la1_init_1() { private static void jj_la1_init_1() {
jj_la1_1 = new int[] {0x1,0x0,0x0,0x0,0x1,0x0,0x1,0x1,0x2,0x0,0x1,0x1,0x1,0x1,0x0,0x0,}; jj_la1_1 = new int[] {0x0,0x2,0x0,0x0,0x0,0x2,0x0,0x2,0x2,0x4,0x0,0x2,0x2,0x2,0x2,0x0,0x0,};
} }
final private JJCalls[] jj_2_rtns = new JJCalls[1]; final private JJCalls[] jj_2_rtns = new JJCalls[1];
private boolean jj_rescan = false; private boolean jj_rescan = false;
@ -447,7 +455,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 16; i++) jj_la1[i] = -1; for (int i = 0; i < 17; i++) jj_la1[i] = -1;
for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
} }
@ -462,7 +470,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 16; i++) jj_la1[i] = -1; for (int i = 0; i < 17; i++) jj_la1[i] = -1;
for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
} }
@ -473,7 +481,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 16; i++) jj_la1[i] = -1; for (int i = 0; i < 17; i++) jj_la1[i] = -1;
for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
} }
@ -484,7 +492,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 16; i++) jj_la1[i] = -1; for (int i = 0; i < 17; i++) jj_la1[i] = -1;
for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
} }
@ -494,7 +502,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 16; i++) jj_la1[i] = -1; for (int i = 0; i < 17; i++) jj_la1[i] = -1;
for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
} }
@ -504,7 +512,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
token = new Token(); token = new Token();
jj_ntk = -1; jj_ntk = -1;
jj_gen = 0; jj_gen = 0;
for (int i = 0; i < 16; i++) jj_la1[i] = -1; for (int i = 0; i < 17; i++) jj_la1[i] = -1;
for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
} }
@ -616,12 +624,12 @@ final class JsonParserImpl implements JsonParserImplConstants {
/** Generate ParseException. */ /** Generate ParseException. */
public ParseException generateParseException() { public ParseException generateParseException() {
jj_expentries.clear(); jj_expentries.clear();
boolean[] la1tokens = new boolean[34]; boolean[] la1tokens = new boolean[35];
if (jj_kind >= 0) { if (jj_kind >= 0) {
la1tokens[jj_kind] = true; la1tokens[jj_kind] = true;
jj_kind = -1; jj_kind = -1;
} }
for (int i = 0; i < 16; i++) { for (int i = 0; i < 17; i++) {
if (jj_la1[i] == jj_gen) { if (jj_la1[i] == jj_gen) {
for (int j = 0; j < 32; j++) { for (int j = 0; j < 32; j++) {
if ((jj_la1_0[i] & (1<<j)) != 0) { if ((jj_la1_0[i] & (1<<j)) != 0) {
@ -633,7 +641,7 @@ final class JsonParserImpl implements JsonParserImplConstants {
} }
} }
} }
for (int i = 0; i < 34; i++) { for (int i = 0; i < 35; i++) {
if (la1tokens[i]) { if (la1tokens[i]) {
jj_expentry = new int[1]; jj_expentry = new int[1];
jj_expentry[0] = i; jj_expentry[0] = i;

View File

@ -1,7 +1,6 @@
/* Generated By:JavaCC: Do not edit this line. JsonParserImplConstants.java */ /* Generated By:JavaCC: Do not edit this line. JsonParserImplConstants.java */
package com.google.gson; package com.google.gson;
/** /**
* Token literal values and constants. * Token literal values and constants.
* Generated by org.javacc.parser.OtherFilesGen#start() * Generated by org.javacc.parser.OtherFilesGen#start()
@ -87,6 +86,7 @@ interface JsonParserImplConstants {
"\"u\"", "\"u\"",
"<HEX>", "<HEX>",
"<HEX_ESC>", "<HEX_ESC>",
"\")]}\\\'\\n<data>\"",
"\"{\"", "\"{\"",
"\"}\"", "\"}\"",
"\",\"", "\",\"",

View File

@ -172,6 +172,10 @@ private final int jjStopStringLiteralDfa_0(int pos, long active0)
return 10; return 10;
} }
return -1; return -1;
case 7:
if ((active0 & 0x200L) != 0L)
return 10;
return -1;
default : default :
return -1; return -1;
} }
@ -192,28 +196,30 @@ private int jjMoveStringLiteralDfa0_0()
{ {
case 34: case 34:
return jjStartNfaWithStates_0(0, 18, 43); return jjStartNfaWithStates_0(0, 18, 43);
case 41:
return jjMoveStringLiteralDfa1_0(0x4000000L);
case 44: case 44:
return jjStopAtPos(0, 28);
case 45:
return jjStopAtPos(0, 32);
case 46:
return jjStopAtPos(0, 33);
case 58:
return jjStopAtPos(0, 29); return jjStopAtPos(0, 29);
case 45:
return jjStopAtPos(0, 33);
case 46:
return jjStopAtPos(0, 34);
case 58:
return jjStopAtPos(0, 30);
case 73: case 73:
return jjMoveStringLiteralDfa1_0(0x200L); return jjMoveStringLiteralDfa1_0(0x200L);
case 78: case 78:
return jjMoveStringLiteralDfa1_0(0x100L); return jjMoveStringLiteralDfa1_0(0x100L);
case 91: case 91:
return jjStopAtPos(0, 30);
case 93:
return jjStopAtPos(0, 31); return jjStopAtPos(0, 31);
case 93:
return jjStopAtPos(0, 32);
case 110: case 110:
return jjMoveStringLiteralDfa1_0(0x80L); return jjMoveStringLiteralDfa1_0(0x80L);
case 123: case 123:
return jjStopAtPos(0, 26);
case 125:
return jjStopAtPos(0, 27); return jjStopAtPos(0, 27);
case 125:
return jjStopAtPos(0, 28);
default : default :
return jjMoveNfa_0(4, 0); return jjMoveNfa_0(4, 0);
} }
@ -227,6 +233,8 @@ private int jjMoveStringLiteralDfa1_0(long active0)
} }
switch(curChar) switch(curChar)
{ {
case 93:
return jjMoveStringLiteralDfa2_0(active0, 0x4000000L);
case 97: case 97:
return jjMoveStringLiteralDfa2_0(active0, 0x100L); return jjMoveStringLiteralDfa2_0(active0, 0x100L);
case 110: case 110:
@ -257,6 +265,8 @@ private int jjMoveStringLiteralDfa2_0(long old0, long active0)
return jjMoveStringLiteralDfa3_0(active0, 0x200L); return jjMoveStringLiteralDfa3_0(active0, 0x200L);
case 108: case 108:
return jjMoveStringLiteralDfa3_0(active0, 0x80L); return jjMoveStringLiteralDfa3_0(active0, 0x80L);
case 125:
return jjMoveStringLiteralDfa3_0(active0, 0x4000000L);
default : default :
break; break;
} }
@ -273,6 +283,8 @@ private int jjMoveStringLiteralDfa3_0(long old0, long active0)
} }
switch(curChar) switch(curChar)
{ {
case 39:
return jjMoveStringLiteralDfa4_0(active0, 0x4000000L);
case 105: case 105:
return jjMoveStringLiteralDfa4_0(active0, 0x200L); return jjMoveStringLiteralDfa4_0(active0, 0x200L);
case 108: case 108:
@ -295,6 +307,8 @@ private int jjMoveStringLiteralDfa4_0(long old0, long active0)
} }
switch(curChar) switch(curChar)
{ {
case 10:
return jjMoveStringLiteralDfa5_0(active0, 0x4000000L);
case 110: case 110:
return jjMoveStringLiteralDfa5_0(active0, 0x200L); return jjMoveStringLiteralDfa5_0(active0, 0x200L);
default : default :
@ -313,6 +327,8 @@ private int jjMoveStringLiteralDfa5_0(long old0, long active0)
} }
switch(curChar) switch(curChar)
{ {
case 60:
return jjMoveStringLiteralDfa6_0(active0, 0x4000000L);
case 105: case 105:
return jjMoveStringLiteralDfa6_0(active0, 0x200L); return jjMoveStringLiteralDfa6_0(active0, 0x200L);
default : default :
@ -331,6 +347,8 @@ private int jjMoveStringLiteralDfa6_0(long old0, long active0)
} }
switch(curChar) switch(curChar)
{ {
case 100:
return jjMoveStringLiteralDfa7_0(active0, 0x4000000L);
case 116: case 116:
return jjMoveStringLiteralDfa7_0(active0, 0x200L); return jjMoveStringLiteralDfa7_0(active0, 0x200L);
default : default :
@ -349,6 +367,8 @@ private int jjMoveStringLiteralDfa7_0(long old0, long active0)
} }
switch(curChar) switch(curChar)
{ {
case 97:
return jjMoveStringLiteralDfa8_0(active0, 0x4000000L);
case 121: case 121:
if ((active0 & 0x200L) != 0L) if ((active0 & 0x200L) != 0L)
return jjStartNfaWithStates_0(7, 9, 10); return jjStartNfaWithStates_0(7, 9, 10);
@ -358,6 +378,62 @@ private int jjMoveStringLiteralDfa7_0(long old0, long active0)
} }
return jjStartNfa_0(6, active0); return jjStartNfa_0(6, active0);
} }
private int jjMoveStringLiteralDfa8_0(long old0, long active0)
{
if (((active0 &= old0)) == 0L)
return jjStartNfa_0(6, old0);
try { curChar = input_stream.readChar(); }
catch(java.io.IOException e) {
jjStopStringLiteralDfa_0(7, active0);
return 8;
}
switch(curChar)
{
case 116:
return jjMoveStringLiteralDfa9_0(active0, 0x4000000L);
default :
break;
}
return jjStartNfa_0(7, active0);
}
private int jjMoveStringLiteralDfa9_0(long old0, long active0)
{
if (((active0 &= old0)) == 0L)
return jjStartNfa_0(7, old0);
try { curChar = input_stream.readChar(); }
catch(java.io.IOException e) {
jjStopStringLiteralDfa_0(8, active0);
return 9;
}
switch(curChar)
{
case 97:
return jjMoveStringLiteralDfa10_0(active0, 0x4000000L);
default :
break;
}
return jjStartNfa_0(8, active0);
}
private int jjMoveStringLiteralDfa10_0(long old0, long active0)
{
if (((active0 &= old0)) == 0L)
return jjStartNfa_0(8, old0);
try { curChar = input_stream.readChar(); }
catch(java.io.IOException e) {
jjStopStringLiteralDfa_0(9, active0);
return 10;
}
switch(curChar)
{
case 62:
if ((active0 & 0x4000000L) != 0L)
return jjStopAtPos(10, 26);
break;
default :
break;
}
return jjStartNfa_0(9, active0);
}
private int jjStartNfaWithStates_0(int pos, int kind, int state) private int jjStartNfaWithStates_0(int pos, int kind, int state)
{ {
jjmatchedKind = kind; jjmatchedKind = kind;
@ -976,7 +1052,8 @@ private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, lo
public static final String[] jjstrLiteralImages = { public static final String[] jjstrLiteralImages = {
"", null, null, null, null, null, null, "\156\165\154\154", "\116\141\116", "", null, null, null, null, null, null, "\156\165\154\154", "\116\141\116",
"\111\156\146\151\156\151\164\171", null, null, null, null, null, null, null, null, "\42", null, null, null, null, "\111\156\146\151\156\151\164\171", null, null, null, null, null, null, null, null, "\42", null, null, null, null,
null, null, null, "\173", "\175", "\54", "\72", "\133", "\135", "\55", "\56", }; null, null, null, "\51\135\175\47\12\74\144\141\164\141\76", "\173", "\175", "\54",
"\72", "\133", "\135", "\55", "\56", };
/** Lexer state names. */ /** Lexer state names. */
public static final String[] lexStateNames = { public static final String[] lexStateNames = {
@ -989,10 +1066,10 @@ public static final String[] lexStateNames = {
/** Lex State array. */ /** Lex State array. */
public static final int[] jjnewLexState = { public static final int[] jjnewLexState = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 0, -1, 1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 0, -1, 1, 3, -1,
1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
}; };
static final long[] jjtoToken = { static final long[] jjtoToken = {
0x3fe775fe1L, 0x7fe775fe1L,
}; };
static final long[] jjtoSkip = { static final long[] jjtoSkip = {
0x1eL, 0x1eL,

View File

@ -60,7 +60,7 @@ public JsonElement parse() :
JsonElement json = null; JsonElement json = null;
} }
{ {
( json=JsonObject() | [")]}'\n<data>"]( json=JsonObject() |
json=JsonArray() | json=JsonArray() |
json=JsonPrimitive() | json=JsonPrimitive() |
json=JsonNull()) json=JsonNull())

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson.functional;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.common.TestTypes.BagOfPrimitives;
import junit.framework.TestCase;
/**
* Tests for security-related aspects of Gson
*
* @author Inderjeet Singh
*/
public class SecurityTest extends TestCase {
/**
* Keep this in sync with Gson.JSON_NON_EXECUTABLE_PREFIX
*/
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n<data>";
private GsonBuilder gsonBuilder;
@Override
protected void setUp() throws Exception {
super.setUp();
gsonBuilder = new GsonBuilder();
}
public void testNonExecutableJsonSerialization() {
Gson gson = gsonBuilder.generateNonExecutableJson().create();
String json = gson.toJson(new BagOfPrimitives());
assertTrue(json.startsWith(JSON_NON_EXECUTABLE_PREFIX));
}
public void testNonExecutableJsonDeserialization() {
String json = JSON_NON_EXECUTABLE_PREFIX + "{longValue:1}";
Gson gson = gsonBuilder.create();
BagOfPrimitives target = gson.fromJson(json, BagOfPrimitives.class);
assertEquals(1, target.longValue);
}
public void testJsonWithNonExectuableTokenSerialization() {
Gson gson = gsonBuilder.generateNonExecutableJson().create();
String json = gson.toJson(JSON_NON_EXECUTABLE_PREFIX);
assertTrue(json.contains(")]}'\n\u003cdata\u003e"));
}
/**
* Gson should be able to deserialize a stream with non-exectuable token even if it is created
* without {@link GsonBuilder#generateNonExecutableJson()}.
*/
public void testJsonWithNonExectuableTokenWithRegularGsonDeserialization() {
Gson gson = gsonBuilder.create();
String json = JSON_NON_EXECUTABLE_PREFIX + "{stringValue:')]}\\u0027\\n<data>'}";
BagOfPrimitives target = gson.fromJson(json, BagOfPrimitives.class);
assertEquals(")]}'\n<data>", target.stringValue);
}
/**
* Gson should be able to deserialize a stream with non-exectuable token if it is created
* with {@link GsonBuilder#generateNonExecutableJson()}.
*/
public void testJsonWithNonExectuableTokenWithConfiguredGsonDeserialization() {
// Gson should be able to deserialize a stream with non-exectuable token even if it is created
Gson gson = gsonBuilder.generateNonExecutableJson().create();
String json = JSON_NON_EXECUTABLE_PREFIX + "{intValue:2,stringValue:')]}\\u0027\\n<data>'}";
BagOfPrimitives target = gson.fromJson(json, BagOfPrimitives.class);
assertEquals(")]}'\n<data>", target.stringValue);
assertEquals(2, target.intValue);
}
}