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

View File

@ -73,6 +73,7 @@ public final class GsonBuilder {
private boolean serializeSpecialFloatingPointValues;
private boolean escapeHtmlChars;
private boolean prettyPrinting;
private boolean generateNonExecutableJson;
/**
* 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;
timeStyle = DateFormat.DEFAULT;
serializeSpecialFloatingPointValues = false;
generateNonExecutableJson = false;
}
/**
@ -128,6 +130,20 @@ public final class GsonBuilder {
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
* that do not have the {@link com.google.gson.annotations.Expose} annotation.
@ -430,7 +446,7 @@ public final class GsonBuilder {
JsonFormatter formatter = prettyPrinting ?
new JsonPrintFormatter(escapeHtmlChars) : new JsonCompactFormatter(escapeHtmlChars);
Gson gson = new Gson(exclusionStrategy, fieldNamingPolicy, objConstructor,
formatter, serializeNulls, customSerializers, customDeserializers);
formatter, serializeNulls, customSerializers, customDeserializers, generateNonExecutableJson);
return gson;
}

View File

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

View File

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

View File

@ -172,6 +172,10 @@ private final int jjStopStringLiteralDfa_0(int pos, long active0)
return 10;
}
return -1;
case 7:
if ((active0 & 0x200L) != 0L)
return 10;
return -1;
default :
return -1;
}
@ -192,28 +196,30 @@ private int jjMoveStringLiteralDfa0_0()
{
case 34:
return jjStartNfaWithStates_0(0, 18, 43);
case 41:
return jjMoveStringLiteralDfa1_0(0x4000000L);
case 44:
return jjStopAtPos(0, 28);
case 45:
return jjStopAtPos(0, 32);
case 46:
return jjStopAtPos(0, 33);
case 58:
return jjStopAtPos(0, 29);
case 45:
return jjStopAtPos(0, 33);
case 46:
return jjStopAtPos(0, 34);
case 58:
return jjStopAtPos(0, 30);
case 73:
return jjMoveStringLiteralDfa1_0(0x200L);
case 78:
return jjMoveStringLiteralDfa1_0(0x100L);
case 91:
return jjStopAtPos(0, 30);
case 93:
return jjStopAtPos(0, 31);
case 93:
return jjStopAtPos(0, 32);
case 110:
return jjMoveStringLiteralDfa1_0(0x80L);
case 123:
return jjStopAtPos(0, 26);
case 125:
return jjStopAtPos(0, 27);
case 125:
return jjStopAtPos(0, 28);
default :
return jjMoveNfa_0(4, 0);
}
@ -227,6 +233,8 @@ private int jjMoveStringLiteralDfa1_0(long active0)
}
switch(curChar)
{
case 93:
return jjMoveStringLiteralDfa2_0(active0, 0x4000000L);
case 97:
return jjMoveStringLiteralDfa2_0(active0, 0x100L);
case 110:
@ -257,6 +265,8 @@ private int jjMoveStringLiteralDfa2_0(long old0, long active0)
return jjMoveStringLiteralDfa3_0(active0, 0x200L);
case 108:
return jjMoveStringLiteralDfa3_0(active0, 0x80L);
case 125:
return jjMoveStringLiteralDfa3_0(active0, 0x4000000L);
default :
break;
}
@ -273,6 +283,8 @@ private int jjMoveStringLiteralDfa3_0(long old0, long active0)
}
switch(curChar)
{
case 39:
return jjMoveStringLiteralDfa4_0(active0, 0x4000000L);
case 105:
return jjMoveStringLiteralDfa4_0(active0, 0x200L);
case 108:
@ -295,6 +307,8 @@ private int jjMoveStringLiteralDfa4_0(long old0, long active0)
}
switch(curChar)
{
case 10:
return jjMoveStringLiteralDfa5_0(active0, 0x4000000L);
case 110:
return jjMoveStringLiteralDfa5_0(active0, 0x200L);
default :
@ -313,6 +327,8 @@ private int jjMoveStringLiteralDfa5_0(long old0, long active0)
}
switch(curChar)
{
case 60:
return jjMoveStringLiteralDfa6_0(active0, 0x4000000L);
case 105:
return jjMoveStringLiteralDfa6_0(active0, 0x200L);
default :
@ -331,6 +347,8 @@ private int jjMoveStringLiteralDfa6_0(long old0, long active0)
}
switch(curChar)
{
case 100:
return jjMoveStringLiteralDfa7_0(active0, 0x4000000L);
case 116:
return jjMoveStringLiteralDfa7_0(active0, 0x200L);
default :
@ -349,6 +367,8 @@ private int jjMoveStringLiteralDfa7_0(long old0, long active0)
}
switch(curChar)
{
case 97:
return jjMoveStringLiteralDfa8_0(active0, 0x4000000L);
case 121:
if ((active0 & 0x200L) != 0L)
return jjStartNfaWithStates_0(7, 9, 10);
@ -358,6 +378,62 @@ private int jjMoveStringLiteralDfa7_0(long old0, long 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)
{
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 = {
"", 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,
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. */
public static final String[] lexStateNames = {
@ -989,10 +1066,10 @@ public static final String[] lexStateNames = {
/** Lex State array. */
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,
};
static final long[] jjtoToken = {
0x3fe775fe1L,
0x7fe775fe1L,
};
static final long[] jjtoSkip = {
0x1eL,

View File

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