Added checks to ensure that we do not serialize NaN or postiive or negative infinity for floats.
This commit is contained in:
parent
09720f28cf
commit
6dbdb272c0
236
gson/JsonParser.jj
Normal file
236
gson/JsonParser.jj
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/**
|
||||||
|
* Adapted from the Json parser grammar from http://code.google.com/p/jsonparser/
|
||||||
|
*
|
||||||
|
* Author: Inderjeet Singh
|
||||||
|
*/
|
||||||
|
|
||||||
|
options {
|
||||||
|
STATIC = false;
|
||||||
|
UNICODE_INPUT = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PARSER_BEGIN(JsonParser)
|
||||||
|
|
||||||
|
package com.google.gson;
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
final class JsonParser {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PARSER_END(JsonParser)
|
||||||
|
|
||||||
|
SKIP : { " " | "\t" | "\n" | "\r" }
|
||||||
|
/*
|
||||||
|
* Technically Json does not allow leading zeros in numbers, but we
|
||||||
|
* will allow that.
|
||||||
|
*/
|
||||||
|
TOKEN : {
|
||||||
|
<E : ["e","E"](["+","-"])?>
|
||||||
|
| <DIGITS : (["0"-"9"])+>
|
||||||
|
| <NULL : "null">
|
||||||
|
| <NAN : "NaN">
|
||||||
|
| <BOOLEAN : ("true" | "false")>
|
||||||
|
| <IDENTIFIER : ["a"-"z","A"-"Z", "_"] (["a"-"z","A"-"Z","0"-"9","_"])* >
|
||||||
|
| <#HEX_CHAR : ["a"-"f","A"-"F","0"-"9"]>
|
||||||
|
| <UNICODE_CHAR : "\\u" <HEX_CHAR><HEX_CHAR><HEX_CHAR><HEX_CHAR> >
|
||||||
|
| <#ESCAPE_CHAR: "\\" ["n","t","b","r","f","\\","'","\"", "/"] >
|
||||||
|
| <SINGLE_QUOTE_LITERAL: "\'" ( (~["\'","\\","\n","\r"]) | <ESCAPE_CHAR> | <UNICODE_CHAR>)* "\'" >
|
||||||
|
| <DOUBLE_QUOTE_LITERAL: "\"" ( (~["\"","\\","\n","\r"]) | <ESCAPE_CHAR> | <UNICODE_CHAR>)* "\"" >
|
||||||
|
| <QUOTE : "\""> : STRING_STATE
|
||||||
|
}
|
||||||
|
<STRING_STATE> MORE : { "\\" : ESC_STATE }
|
||||||
|
<STRING_STATE> TOKEN : {
|
||||||
|
<ENDQUOTE : <QUOTE> > : DEFAULT
|
||||||
|
| <CHAR : ~["\"","\\"]>
|
||||||
|
}
|
||||||
|
<ESC_STATE> TOKEN : {
|
||||||
|
<CNTRL_ESC : ["\"","\\","/","b","f","n","r","t"]> : STRING_STATE
|
||||||
|
}
|
||||||
|
<ESC_STATE> MORE : { "u" : HEX_STATE }
|
||||||
|
<HEX_STATE> TOKEN : {
|
||||||
|
<#HEX : ["a"-"f","A"-"F","0"-"9"]>
|
||||||
|
| <HEX_ESC : <HEX><HEX><HEX><HEX> > : STRING_STATE
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonElement parse() :
|
||||||
|
{
|
||||||
|
JsonElement json = null;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
( json=JsonObject() |
|
||||||
|
json=JsonArray() |
|
||||||
|
json=JsonPrimitive() |
|
||||||
|
json=JsonNull())
|
||||||
|
{ return json; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonObject JsonObject() :
|
||||||
|
{
|
||||||
|
JsonObject o = new JsonObject();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"{" [ Members(o) ] "}"
|
||||||
|
{ return o; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNull JsonNull() :
|
||||||
|
{
|
||||||
|
Token t;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
t = <NULL> { return new JsonNull(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Members(JsonObject o) :
|
||||||
|
{ }
|
||||||
|
{
|
||||||
|
Pair(o) [ "," Members(o) ]
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Pair(JsonObject o) :
|
||||||
|
{
|
||||||
|
JsonPrimitive property;
|
||||||
|
JsonElement value;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
property=JsonMemberName() ":" value=JsonValue()
|
||||||
|
{
|
||||||
|
o.add(property.getAsString(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonPrimitive JsonMemberName() :
|
||||||
|
{ Token t; JsonPrimitive value; }
|
||||||
|
{
|
||||||
|
t=<IDENTIFIER> { return new JsonPrimitive(t.image); } |
|
||||||
|
value=JsonString() { return value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonArray JsonArray() :
|
||||||
|
{ JsonArray array = new JsonArray(); }
|
||||||
|
{
|
||||||
|
"[" [ Elements(array) ] "]"
|
||||||
|
{
|
||||||
|
array.reverse();
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Elements(JsonArray array) :
|
||||||
|
{
|
||||||
|
JsonElement element;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
element=JsonValue() [ "," Elements(array) ]
|
||||||
|
{ array.add(element); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonElement JsonValue() :
|
||||||
|
{ JsonElement o = null; }
|
||||||
|
{
|
||||||
|
( o=JsonString() |
|
||||||
|
o=JsonNumber() |
|
||||||
|
o=JsonObject() |
|
||||||
|
o=JsonArray() |
|
||||||
|
o=JsonBoolean() |
|
||||||
|
o=JsonNull() )
|
||||||
|
{ return o; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonPrimitive JsonBoolean() :
|
||||||
|
{ Token t; }
|
||||||
|
{
|
||||||
|
t=<BOOLEAN> {
|
||||||
|
boolean value = Boolean.valueOf(t.image);
|
||||||
|
return new JsonPrimitive(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonPrimitive JsonPrimitive() :
|
||||||
|
{
|
||||||
|
JsonPrimitive value;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
( value=JsonString()) { return value; } |
|
||||||
|
( value=JsonNumber()) { return value; } |
|
||||||
|
( value=JsonBoolean()) { return value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonPrimitive JsonNumber() :
|
||||||
|
{
|
||||||
|
JsonPrimitive value;
|
||||||
|
String intpart = null,
|
||||||
|
fracpart = null,
|
||||||
|
exppart = null;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
(value=JsonNaN()) {return value; } |
|
||||||
|
(intpart=JsonInt() [ fracpart=JsonFrac() ] [ exppart=JsonExp() ])
|
||||||
|
{
|
||||||
|
Number n;
|
||||||
|
if (exppart != null || fracpart != null) {
|
||||||
|
fracpart = (fracpart == null) ? "" : fracpart;
|
||||||
|
exppart = (exppart == null) ? "" : exppart;
|
||||||
|
n = new java.math.BigDecimal(intpart + fracpart + exppart);
|
||||||
|
} else {
|
||||||
|
n = new java.math.BigInteger(intpart);
|
||||||
|
}
|
||||||
|
return new JsonPrimitive(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonPrimitive JsonNaN() :
|
||||||
|
{
|
||||||
|
Token t;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
t=<NAN> {return new JsonPrimitive(Double.NaN); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private String JsonInt() :
|
||||||
|
{
|
||||||
|
String digits;
|
||||||
|
boolean negative = false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
["-" { negative = true; } ] digits=Digits()
|
||||||
|
{
|
||||||
|
if(negative)
|
||||||
|
return "-" + digits;
|
||||||
|
return digits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String JsonFrac() :
|
||||||
|
{ String digits; }
|
||||||
|
{
|
||||||
|
"." digits=Digits()
|
||||||
|
{ return "." + digits; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private String JsonExp() :
|
||||||
|
{
|
||||||
|
Token t;
|
||||||
|
String digits;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
t=<E> digits=Digits()
|
||||||
|
{ return t.image + digits; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private String Digits() :
|
||||||
|
{ Token t; }
|
||||||
|
{
|
||||||
|
t=<DIGITS>
|
||||||
|
{ return t.image; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonPrimitive JsonString() :
|
||||||
|
{ Token t; }
|
||||||
|
{
|
||||||
|
(t=<SINGLE_QUOTE_LITERAL> | t=<DOUBLE_QUOTE_LITERAL>) {
|
||||||
|
String value = StringUnmarshaller.unmarshall(t.image);
|
||||||
|
return new JsonPrimitive(value);
|
||||||
|
}
|
||||||
|
}
|
@ -118,7 +118,7 @@
|
|||||||
</workspaceCodeStylesURL>
|
</workspaceCodeStylesURL>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<!-- plugin>
|
<plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>javacc-maven-plugin</artifactId>
|
<artifactId>javacc-maven-plugin</artifactId>
|
||||||
<executions>
|
<executions>
|
||||||
@ -141,7 +141,7 @@
|
|||||||
<version>4.0</version>
|
<version>4.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</plugin -->
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jxr-plugin</artifactId>
|
<artifactId>maven-jxr-plugin</artifactId>
|
||||||
|
@ -643,6 +643,9 @@ final class DefaultTypeAdapters {
|
|||||||
private static class FloatTypeAdapter
|
private static class FloatTypeAdapter
|
||||||
implements InstanceCreator<Float>, JsonSerializer<Float>, JsonDeserializer<Float> {
|
implements InstanceCreator<Float>, JsonSerializer<Float>, JsonDeserializer<Float> {
|
||||||
public JsonElement serialize(Float src, Type typeOfSrc, JsonSerializationContext context) {
|
public JsonElement serialize(Float src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
if (Float.isNaN(src) || Float.isInfinite(src)) {
|
||||||
|
throw new IllegalArgumentException(src + " is not a valid double value as per JavaScript specification.");
|
||||||
|
}
|
||||||
return new JsonPrimitive(src);
|
return new JsonPrimitive(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,44 +349,96 @@ public class PrimitiveTest extends TestCase {
|
|||||||
return json.substring(json.indexOf('[') + 1, json.indexOf(']'));
|
return json.substring(json.indexOf('[') + 1, json.indexOf(']'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNaNSerializationNotSupported() {
|
public void testDoubleNaNSerializationNotSupported() {
|
||||||
try {
|
try {
|
||||||
double d = Double.NaN;
|
double d = Double.NaN;
|
||||||
gson.toJson(d);
|
gson.toJson(d);
|
||||||
|
Double dw = Double.NaN;
|
||||||
|
gson.toJson(dw);
|
||||||
fail("Gson should not accept NaN for serialization");
|
fail("Gson should not accept NaN for serialization");
|
||||||
} catch (IllegalArgumentException expected) {
|
} catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNaNDeserializationNotSupported() {
|
public void testDoubleNaNDeserializationNotSupported() {
|
||||||
try {
|
try {
|
||||||
String json = "NaN";
|
String json = "NaN";
|
||||||
assertEquals(Double.NaN, gson.fromJson(json, Double.class));
|
assertEquals(Double.NaN, gson.fromJson(json, Double.class));
|
||||||
|
assertEquals(Double.NaN, gson.fromJson(json, double.class));
|
||||||
|
fail("Gson should not accept NaN for deserialization");
|
||||||
} catch (JsonParseException expected) {
|
} catch (JsonParseException expected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInfinitySerializationNotSupported() {
|
public void testFloatNaNSerializationNotSupported() {
|
||||||
|
try {
|
||||||
|
float f = Float.NaN;
|
||||||
|
gson.toJson(f);
|
||||||
|
Float fw = Float.NaN;
|
||||||
|
gson.toJson(fw);
|
||||||
|
fail("Gson should not accept NaN for serialization");
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFloatNaNDeserializationNotSupported() {
|
||||||
|
try {
|
||||||
|
String json = "NaN";
|
||||||
|
assertEquals(Float.NaN, gson.fromJson(json, Float.class));
|
||||||
|
assertEquals(Float.NaN, gson.fromJson(json, float.class));
|
||||||
|
fail("Gson should not accept NaN for deserialization");
|
||||||
|
} catch (JsonParseException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDoubleInfinitySerializationNotSupported() {
|
||||||
try {
|
try {
|
||||||
double d = Double.POSITIVE_INFINITY;
|
double d = Double.POSITIVE_INFINITY;
|
||||||
gson.toJson(d);
|
gson.toJson(d);
|
||||||
|
Double dw = Double.POSITIVE_INFINITY;
|
||||||
|
gson.toJson(dw);
|
||||||
fail("Gson should not accept positive infinity for serialization");
|
fail("Gson should not accept positive infinity for serialization");
|
||||||
} catch (IllegalArgumentException expected) {
|
} catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInfinityDeserializationNotSupported() {
|
public void testDoubleInfinityDeserializationNotSupported() {
|
||||||
try {
|
try {
|
||||||
String json = "Infinity";
|
String json = "Infinity";
|
||||||
assertEquals(Double.POSITIVE_INFINITY, gson.fromJson(json, Double.class));
|
assertEquals(Double.POSITIVE_INFINITY, gson.fromJson(json, Double.class));
|
||||||
|
assertEquals(Double.POSITIVE_INFINITY, gson.fromJson(json, double.class));
|
||||||
|
fail("Gson should not accept positive infinity for deserialization");
|
||||||
} catch (JsonParseException expected) {
|
} catch (JsonParseException expected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFloatInfinitySerializationNotSupported() {
|
||||||
|
try {
|
||||||
|
float f = Float.POSITIVE_INFINITY;
|
||||||
|
gson.toJson(f);
|
||||||
|
Float fw = Float.POSITIVE_INFINITY;
|
||||||
|
gson.toJson(fw);
|
||||||
|
fail("Gson should not accept positive infinity for serialization");
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFloatInfinityDeserializationNotSupported() {
|
||||||
|
try {
|
||||||
|
String json = "Infinity";
|
||||||
|
assertEquals(Float.POSITIVE_INFINITY, gson.fromJson(json, Float.class));
|
||||||
|
assertEquals(Float.POSITIVE_INFINITY, gson.fromJson(json, float.class));
|
||||||
|
fail("Gson should not accept positive infinity for deserialization");
|
||||||
|
} catch (JsonParseException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testNegativeInfinitySerializationNotSupported() {
|
public void testNegativeInfinitySerializationNotSupported() {
|
||||||
try {
|
try {
|
||||||
double d = Double.NEGATIVE_INFINITY;
|
double d = Double.NEGATIVE_INFINITY;
|
||||||
gson.toJson(d);
|
gson.toJson(d);
|
||||||
|
Double dw = Double.NEGATIVE_INFINITY;
|
||||||
|
gson.toJson(dw);
|
||||||
fail("Gson should not accept positive infinity for serialization");
|
fail("Gson should not accept positive infinity for serialization");
|
||||||
} catch (IllegalArgumentException expected) {
|
} catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
@ -395,7 +447,30 @@ public class PrimitiveTest extends TestCase {
|
|||||||
public void testNegativeInfinityDeserializationNotSupported() {
|
public void testNegativeInfinityDeserializationNotSupported() {
|
||||||
try {
|
try {
|
||||||
String json = "-Infinity";
|
String json = "-Infinity";
|
||||||
|
assertEquals(Double.NEGATIVE_INFINITY, gson.fromJson(json, double.class));
|
||||||
assertEquals(Double.NEGATIVE_INFINITY, gson.fromJson(json, Double.class));
|
assertEquals(Double.NEGATIVE_INFINITY, gson.fromJson(json, Double.class));
|
||||||
|
fail("Gson should not accept positive infinity for serialization");
|
||||||
|
} catch (JsonParseException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNegativeInfinityFloatSerializationNotSupported() {
|
||||||
|
try {
|
||||||
|
float f = Float.NEGATIVE_INFINITY;
|
||||||
|
gson.toJson(f);
|
||||||
|
Float fw = Float.NEGATIVE_INFINITY;
|
||||||
|
gson.toJson(fw);
|
||||||
|
fail("Gson should not accept positive infinity for serialization");
|
||||||
|
} catch (IllegalArgumentException expected) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNegativeInfinityFloatDeserializationNotSupported() {
|
||||||
|
try {
|
||||||
|
String json = "-Infinity";
|
||||||
|
assertEquals(Float.NEGATIVE_INFINITY, gson.fromJson(json, float.class));
|
||||||
|
assertEquals(Float.NEGATIVE_INFINITY, gson.fromJson(json, Float.class));
|
||||||
|
fail("Gson should not accept positive infinity for serialization");
|
||||||
} catch (JsonParseException expected) {
|
} catch (JsonParseException expected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user