You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by jw...@apache.org on 2015/12/21 18:37:35 UTC
groovy git commit: GROOVY-7630 - JsonSlurper LAX and INDEX_OVERLAY
parser with invalid number (closes #189)
Repository: groovy
Updated Branches:
refs/heads/master 738b5f669 -> 73f5979a4
GROOVY-7630 - JsonSlurper LAX and INDEX_OVERLAY parser with invalid number (closes #189)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/73f5979a
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/73f5979a
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/73f5979a
Branch: refs/heads/master
Commit: 73f5979a468f1508134eba20ce503630b0fe0cc7
Parents: 738b5f6
Author: John Wagenleitner <jo...@gmail.com>
Authored: Sat Nov 14 23:08:04 2015 -0800
Committer: John Wagenleitner <jw...@apache.org>
Committed: Mon Dec 21 09:34:21 2015 -0800
----------------------------------------------------------------------
.../groovy/json/internal/JsonFastParser.java | 37 ++++++++++++++++---
.../groovy/json/internal/JsonParserLax.java | 39 ++++++++++++++++++++
.../groovy/json/JsonSlurperLaxTest.groovy | 27 ++++++++++++++
.../groovy/groovy/json/JsonSlurperTest.groovy | 37 ++++++++++++++++++-
4 files changed, 133 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/73f5979a/subprojects/groovy-json/src/main/java/groovy/json/internal/JsonFastParser.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-json/src/main/java/groovy/json/internal/JsonFastParser.java b/subprojects/groovy-json/src/main/java/groovy/json/internal/JsonFastParser.java
index cb56a82..c088b4d 100644
--- a/subprojects/groovy-json/src/main/java/groovy/json/internal/JsonFastParser.java
+++ b/subprojects/groovy-json/src/main/java/groovy/json/internal/JsonFastParser.java
@@ -163,6 +163,8 @@ public class JsonFastParser extends JsonParserCharArray {
char currentChar;
boolean doubleFloat = false;
boolean foundDot = false;
+ boolean foundSign = false;
+ boolean foundExp = false;
if (minus && index + 1 < array.length) {
index++;
@@ -176,19 +178,42 @@ public class JsonFastParser extends JsonParserCharArray {
break;
} else if (isDelimiter(currentChar)) {
break;
- } else if (currentChar == '.') {
- if (foundDot) {
- complain("unexpected character " + currentChar);
- }
- foundDot = true;
- doubleFloat = true;
} else if (isDecimalChar(currentChar)) {
+ switch (currentChar) {
+ case DECIMAL_POINT:
+ if (foundDot || foundExp) { complain("unexpected character " + currentChar); }
+ foundDot = true;
+ break;
+ case LETTER_E:
+ case LETTER_BIG_E:
+ if (foundExp) { complain("unexpected character " + currentChar); }
+ foundExp = true;
+ break;
+ case MINUS:
+ case PLUS:
+ if (foundSign || !foundExp) { complain("unexpected character " + currentChar); }
+ if (foundExp && array[index - 1] != LETTER_E && array[index - 1] != LETTER_BIG_E) {
+ complain("unexpected character " + currentChar);
+ }
+ foundSign = true;
+ break;
+ }
doubleFloat = true;
+ } else {
+ complain("unexpected character " + currentChar);
}
index++;
if (index >= array.length) break;
}
+ // Handle the case where the exponential number ends without the actual exponent
+ if (foundExp) {
+ char prevChar = array[index - 1];
+ if (prevChar == LETTER_E || prevChar == LETTER_BIG_E || prevChar == MINUS || prevChar == PLUS) {
+ complain("unexpected character " + currentChar);
+ }
+ }
+
__index = index;
__currentChar = currentChar;
http://git-wip-us.apache.org/repos/asf/groovy/blob/73f5979a/subprojects/groovy-json/src/main/java/groovy/json/internal/JsonParserLax.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-json/src/main/java/groovy/json/internal/JsonParserLax.java b/subprojects/groovy-json/src/main/java/groovy/json/internal/JsonParserLax.java
index 1172fd4..0238b35 100644
--- a/subprojects/groovy-json/src/main/java/groovy/json/internal/JsonParserLax.java
+++ b/subprojects/groovy-json/src/main/java/groovy/json/internal/JsonParserLax.java
@@ -370,6 +370,13 @@ public class JsonParserLax extends JsonParserCharArray {
}
}
+ /**
+ * Decodes a number from a JSON value. If at any point it is determined that
+ * the value is not a valid number the value is treated as a {@code String}.
+ *
+ * @param minus indicate whether the number is negative
+ * @return a number, or {@code String} if not a valid number
+ */
protected final Value decodeNumberLax(boolean minus) {
char[] array = charArray;
@@ -377,6 +384,9 @@ public class JsonParserLax extends JsonParserCharArray {
int index = __index;
char currentChar;
boolean doubleFloat = false;
+ boolean foundDot = false;
+ boolean foundSign = false;
+ boolean foundExp = false;
if (minus && index + 1 < array.length) {
index++;
@@ -391,12 +401,41 @@ public class JsonParserLax extends JsonParserCharArray {
} else if (isDelimiter(currentChar)) {
break;
} else if (isDecimalChar(currentChar)) {
+ switch (currentChar) {
+ case DECIMAL_POINT:
+ if (foundDot || foundExp) { return decodeStringLax(); }
+ foundDot = true;
+ break;
+ case LETTER_E:
+ case LETTER_BIG_E:
+ if (foundExp) { return decodeStringLax(); }
+ foundExp = true;
+ break;
+ case MINUS:
+ case PLUS:
+ if (foundSign || !foundExp) { return decodeStringLax(); }
+ if (foundExp && array[index - 1] != LETTER_E && array[index - 1] != LETTER_BIG_E) {
+ return decodeStringLax();
+ }
+ foundSign = true;
+ break;
+ }
doubleFloat = true;
+ } else {
+ return decodeStringLax();
}
index++;
if (index >= array.length) break;
}
+ // Handle the case where the exponential number ends without the actual exponent
+ if (foundExp) {
+ char prevChar = array[index - 1];
+ if (prevChar == LETTER_E || prevChar == LETTER_BIG_E || prevChar == MINUS || prevChar == PLUS) {
+ return decodeStringLax();
+ }
+ }
+
__index = index;
__currentChar = currentChar;
http://git-wip-us.apache.org/repos/asf/groovy/blob/73f5979a/subprojects/groovy-json/src/test/groovy/groovy/json/JsonSlurperLaxTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-json/src/test/groovy/groovy/json/JsonSlurperLaxTest.groovy b/subprojects/groovy-json/src/test/groovy/groovy/json/JsonSlurperLaxTest.groovy
index 38c161f..e5524b6 100644
--- a/subprojects/groovy-json/src/test/groovy/groovy/json/JsonSlurperLaxTest.groovy
+++ b/subprojects/groovy-json/src/test/groovy/groovy/json/JsonSlurperLaxTest.groovy
@@ -121,4 +121,31 @@ class JsonSlurperLaxTest extends JsonSlurperTest {
assert map["he said"] == '"fire all your guns at once baby, and explode into the night"'
assert map.the == "end"
}
+
+ @Override
+ void testInvalidNumbers() {
+ // should be parsed as Strings
+ assert parser.parseText('{"num": 1a}').num == '1a'
+ assert parser.parseText('{"num": -1a}').num == '-1a'
+ assert parser.parseText('[98ab9]')[0] == '98ab9'
+ assert parser.parseText('[12/25/1980]')[0] == '12/25/1980'
+ assert parser.parseText('{"num": 1980-12-25}').num == '1980-12-25'
+ assert parser.parseText('{"num": 1.2ee5}').num == '1.2ee5'
+ assert parser.parseText('{"num": 1.2EE5}').num == '1.2EE5'
+ assert parser.parseText('{"num": 1.2Ee5}').num == '1.2Ee5'
+ assert parser.parseText('{"num": 1.2e++5}').num == '1.2e++5'
+ assert parser.parseText('{"num": 1.2e--5}').num == '1.2e--5'
+ assert parser.parseText('{"num": 1.2e+-5}').num == '1.2e+-5'
+ assert parser.parseText('{"num": 1.2+e5}').num == '1.2+e5'
+ assert parser.parseText('{"num": 1.2E5+}').num == '1.2E5+'
+ assert parser.parseText('{"num": 1.2e5+}').num == '1.2e5+'
+ assert parser.parseText('{"num": 37e-5.5}').num == '37e-5.5'
+ assert parser.parseText('{"num": 6.92e}').num == '6.92e'
+ assert parser.parseText('{"num": 6.92E}').num == '6.92E'
+ assert parser.parseText('{"num": 6.92e-}').num == '6.92e-'
+ assert parser.parseText('{"num": 6.92e+}').num == '6.92e+'
+ assert parser.parseText('{"num": 6+}').num == '6+'
+ assert parser.parseText('{"num": 6-}').num == '6-'
+ }
+
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/73f5979a/subprojects/groovy-json/src/test/groovy/groovy/json/JsonSlurperTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-json/src/test/groovy/groovy/json/JsonSlurperTest.groovy b/subprojects/groovy-json/src/test/groovy/groovy/json/JsonSlurperTest.groovy
index 95f52ca..b8068df 100644
--- a/subprojects/groovy-json/src/test/groovy/groovy/json/JsonSlurperTest.groovy
+++ b/subprojects/groovy-json/src/test/groovy/groovy/json/JsonSlurperTest.groovy
@@ -274,7 +274,6 @@ class JsonSlurperTest extends GroovyTestCase {
shouldFail(JsonException) { parser.parseText('["a"') }
shouldFail(JsonException) { parser.parseText('["a", ') }
shouldFail(JsonException) { parser.parseText('["a", true') }
- shouldFail(JsonException) { parser.parseText('[1.1.1]') }
}
void testBackSlashEscaping() {
@@ -317,4 +316,40 @@ class JsonSlurperTest extends GroovyTestCase {
assertEquals(Date.class, o.a.class)
}
+
+ void testInvalidNumbers() {
+ shouldFail(JsonException) { parser.parseText('[1.1.1]') }
+ shouldFail(JsonException) { parser.parseText('{"num": 1a}') }
+ shouldFail(JsonException) { parser.parseText('{"num": 1A}') }
+ shouldFail(JsonException) { parser.parseText('{"num": -1a}') }
+ shouldFail(JsonException) { parser.parseText('[98ab9]') }
+ shouldFail(JsonException) { parser.parseText('[-98ab9]') }
+ shouldFail(JsonException) { parser.parseText('[12/25/1980]') }
+
+ // TODO: Exception class differs from this point by parser type
+ // Probably something to be addressed at some point.
+ Class exceptional = JsonException
+ if (parser.type == JsonParserType.CHAR_BUFFER) {
+ exceptional = NumberFormatException
+ }
+
+ shouldFail(exceptional) { parser.parseText('{"num": 1980-12-25}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 1.2ee5}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 1.2EE5}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 1.2Ee5}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 1.2e++5}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 1.2e--5}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 1.2e+-5}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 1.2+e5}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 1.2E5+}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 1.2e5+}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 37e-5.5}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 6.92e}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 6.92E}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 6.92e-}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 6.92e+}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 6+}') }
+ shouldFail(exceptional) { parser.parseText('{"num": 6-}') }
+ }
+
}