[Git][java-team/openjson][master] 5 commits: New upstream version 1.0.13
Tony Mancill (@tmancill)
gitlab at salsa.debian.org
Sun Jul 2 01:44:57 BST 2023
Tony Mancill pushed to branch master at Debian Java Maintainers / openjson
Commits:
8072e7c4 by tony mancill at 2023-07-01T17:09:03-07:00
New upstream version 1.0.13
- - - - -
8cc81954 by tony mancill at 2023-07-01T17:09:04-07:00
Update upstream source from tag 'upstream/1.0.13'
Update to upstream version '1.0.13'
with Debian dir 468b643630975cf2d82f65cb1a5d5d566ca2027a
- - - - -
d08b45e0 by tony mancill at 2023-07-01T17:15:59-07:00
Bump Standards-Version to 4.6.2 (no changes)
- - - - -
c3c05136 by tony mancill at 2023-07-01T17:15:59-07:00
Freshen years in debian/copyright
- - - - -
9a8893c0 by tony mancill at 2023-07-01T17:15:59-07:00
Prepare changelog for upload
- - - - -
10 changed files:
- README.md
- debian/changelog
- debian/control
- debian/copyright
- pom.xml
- src/main/java/com/github/openjson/JSONTokener.java
- src/test/java/com/github/openjson/JSONFunctionTestObject.java
- src/test/java/com/github/openjson/JSONTokenerTest.java
- src/test/java/com/github/openjson/SelfUseTest.java
- + src/test/java/com/github/openjson/issues/Issue18Test.java
Changes:
=====================================
README.md
=====================================
@@ -1,4 +1,4 @@
-# Open JSON [![Build Status](https://travis-ci.org/openjson/openjson.svg?branch=master)](https://travis-ci.org/openjson/openjson) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
+# Open JSON [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
This code is extracted from the Android project to allow
a clean-room implementation of the popular JSON API to be
=====================================
debian/changelog
=====================================
@@ -1,3 +1,14 @@
+openjson (1.0.13-1) unstable; urgency=medium
+
+ * Team upload.
+ * New upstream version 1.0.13
+ Fixes potential DoS via stack overflow
+ https://github.com/openjson/openjson/issues/18
+ * Bump Standards-Version to 4.6.2 (no changes)
+ * Freshen years in debian/copyright
+
+ -- tony mancill <tmancill at debian.org> Sat, 01 Jul 2023 17:15:32 -0700
+
openjson (1.0.12-2) unstable; urgency=medium
* Source only upload.
=====================================
debian/control
=====================================
@@ -6,7 +6,7 @@ Uploaders: Sudip Mukherjee <sudipm.mukherjee at gmail.com>
Build-Depends: debhelper-compat (= 13), default-jdk, maven-debian-helper (>= 2.1)
Build-Depends-Indep: junit4 (>= 4.12), libmaven-bundle-plugin-java (>= 3.5.1)
Rules-Requires-Root: no
-Standards-Version: 4.5.0
+Standards-Version: 4.6.2
Vcs-Git: https://salsa.debian.org/java-team/openjson.git
Vcs-Browser: https://salsa.debian.org/java-team/openjson
Homepage: https://github.com/openjson/openjson
=====================================
debian/copyright
=====================================
@@ -3,11 +3,11 @@ Upstream-Name: Open-JSON
Source: https://github.com/openjson/openjson
Files: *
-Copyright: 2010, The Android Open Source Project
+Copyright: 2010-2023, The Android Open Source Project
License: Apache-2.0
Files: debian/*
-Copyright: 2020, Sudip Mukherjee <sudipm.mukherjee at gmail.com>
+Copyright: 2020-2023, Sudip Mukherjee <sudipm.mukherjee at gmail.com>
License: Apache-2.0
License: Apache-2.0
=====================================
pom.xml
=====================================
@@ -6,7 +6,7 @@
<groupId>com.github.openjson</groupId>
<artifactId>openjson</artifactId>
- <version>1.0.12</version>
+ <version>1.0.13</version>
<packaging>jar</packaging>
<name>Open JSON</name>
@@ -43,7 +43,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>4.12</version>
+ <version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
=====================================
src/main/java/com/github/openjson/JSONTokener.java
=====================================
@@ -35,8 +35,8 @@ import java.io.Reader;
* String query = object.getString("query");
* JSONArray locations = object.getJSONArray("locations");</pre>
*
- * <p>For best interoperability and performance use JSON that complies with
- * RFC 4627, such as that generated by {@link JSONStringer}. For legacy reasons
+ * <p>For the best interoperability and performance use JSON that complies with
+ * RFC 4627, such as that generated by {@link JSONStringer}. For legacy reasons,
* this parser is lenient, so a successful parse does not indicate that the
* input string was valid JSON. All of the following syntax errors will be
* ignored:
@@ -56,7 +56,7 @@ import java.io.Reader;
* </ul>
*
* <p>Each tokener may be used to parse a single JSON string. Instances of this
- * class are not thread safe. Although this class is nonfinal, it was not
+ * class are not thread safe. Although this class is non-final, it was not
* designed for inheritance and should not be subclassed. In particular,
* self-use by overrideable methods is not specified. See <i>Effective Java</i>
* Item 17, "Design and Document or inheritance or else prohibit it" for further
@@ -64,6 +64,14 @@ import java.io.Reader;
*/
public class JSONTokener {
+ /**
+ * Maximum allowed JSON nesting level supported by the parser.
+ * Used to avoid StackOverflow errors.
+ * For backward compatibility, the value can be changed (globally) using a system property.
+ */
+ public static final int MAX_NESTING_LEVEL =
+ Integer.getInteger("com.github.openjson.MAX_NESTING_LEVEL", 100);
+
/**
* The input JSON.
*/
@@ -108,16 +116,24 @@ public class JSONTokener {
* @throws JSONException if the input is malformed.
*/
public Object nextValue() throws JSONException {
+ return nextValue(0);
+ }
+
+ private Object nextValue(int nestingLevel) throws JSONException {
+ if (nestingLevel >= MAX_NESTING_LEVEL) {
+ throw new JSONException("Failed to parse input. JSONTokener." +
+ "MAX_NESTING_LEVEL is reached: " + MAX_NESTING_LEVEL);
+ }
int c = nextCleanInternal();
switch (c) {
case -1:
throw syntaxError("End of input");
case '{':
- return readObject();
+ return readObject(nestingLevel);
case '[':
- return readArray();
+ return readArray(nestingLevel);
case '\'':
case '"':
@@ -343,8 +359,7 @@ public class JSONTokener {
}
/* ... finally give up. We have an unquoted string */
- //noinspection RedundantStringConstructorCall
- return new String(literal); // a new string avoids leaking memory
+ return literal; // a new string avoids leaking memory
}
/**
@@ -366,7 +381,7 @@ public class JSONTokener {
* Reads a sequence of key/value pairs and the trailing closing brace '}' of
* an object. The opening brace '{' should have already been read.
*/
- private JSONObject readObject() throws JSONException {
+ private JSONObject readObject(int nestingLevel) throws JSONException {
JSONObject result = new JSONObject();
/* Peek to see if this is the empty object. */
@@ -378,7 +393,7 @@ public class JSONTokener {
}
while (true) {
- Object name = nextValue();
+ Object name = nextValue(nestingLevel + 1);
if (!(name instanceof String)) {
if (name == null) {
throw syntaxError("Names cannot be null");
@@ -389,9 +404,8 @@ public class JSONTokener {
}
/*
- * Expect the name/value separator to be either a colon ':', an
- * equals sign '=', or an arrow "=>". The last two are bogus but we
- * include them because that's what the original implementation did.
+ * Expect the name/value separator to be either a colon ':', an equals sign '=', or an arrow "=>".
+ * The last two are bogus, but we include them because that's what the original implementation did.
*/
int separator = nextCleanInternal();
if (separator != ':' && separator != '=') {
@@ -401,7 +415,7 @@ public class JSONTokener {
pos++;
}
- result.put((String) name, nextValue());
+ result.put((String) name, nextValue(nestingLevel + 1));
switch (nextCleanInternal()) {
case '}':
@@ -421,7 +435,7 @@ public class JSONTokener {
* "[]" yields an empty array, but "[,]" returns a two-element array
* equivalent to "[null,null]".
*/
- private JSONArray readArray() throws JSONException {
+ private JSONArray readArray(int nestingLevel) throws JSONException {
JSONArray result = new JSONArray();
/* to cover input that ends with ",]". */
@@ -446,7 +460,7 @@ public class JSONTokener {
pos--;
}
- result.put(nextValue());
+ result.put(nextValue(nestingLevel + 1));
switch (nextCleanInternal()) {
case ']':
@@ -500,8 +514,8 @@ public class JSONTokener {
/**
* Returns the next available character, or the null character '\0' if all
- * input has been exhausted. The return value of this method is ambiguous
- * for JSON strings that contain the character '\0'.
+ * inputs have been exhausted.
+ * The return value of this method is ambiguous for JSON strings that contain the character '\0'.
*
* @return the next character.
*/
@@ -510,8 +524,8 @@ public class JSONTokener {
}
/**
- * Returns the next available character if it equals {@code c}. Otherwise an
- * exception is thrown.
+ * Returns the next available character if it equals {@code c}.
+ * Otherwise, an exception is thrown.
*
* @param c The character we are looking for.
* @return the next character.
@@ -608,7 +622,7 @@ public class JSONTokener {
}
/**
- * Advances past all input up to but not including the next occurrence of
+ * Advances past all inputs up to but not including the next occurrence of
* {@code to}. If the remaining input doesn't contain {@code to}, the input
* is unchanged.
*
=====================================
src/test/java/com/github/openjson/JSONFunctionTestObject.java
=====================================
@@ -4,7 +4,7 @@ package com.github.openjson;
* Class to test the function hack
*/
public class JSONFunctionTestObject {
- private String value;
+ private final String value;
public JSONFunctionTestObject(String value) {
this.value = value;
@@ -14,4 +14,4 @@ public class JSONFunctionTestObject {
public String toString() {
return value;
}
-}
\ No newline at end of file
+}
=====================================
src/test/java/com/github/openjson/JSONTokenerTest.java
=====================================
@@ -17,13 +17,16 @@
package com.github.openjson;
import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
/**
* This black box test was written without inspecting the non-free org.json sourcecode.
*/
-public class JSONTokenerTest extends TestCase {
+public class JSONTokenerTest {
+ @Test
public void testNulls() throws JSONException {
// JSONTokener accepts null, only to fail later on almost all APIs!
new JSONTokener((String) null).back();
@@ -94,12 +97,12 @@ public class JSONTokenerTest extends TestCase {
} catch (NullPointerException ignored) {
}
- assertEquals("foo! at character 0 of null",
- new JSONTokener((String) null).syntaxError("foo!").getMessage());
+ assertEquals("foo! at character 0 of null", new JSONTokener((String) null).syntaxError("foo!").getMessage());
assertEquals(" at character 0 of null", new JSONTokener((String) null).toString());
}
+ @Test
public void testEmptyString() throws JSONException {
JSONTokener backTokener = new JSONTokener("");
backTokener.back();
@@ -131,11 +134,11 @@ public class JSONTokenerTest extends TestCase {
}
new JSONTokener("").skipPast("ABC");
assertEquals('\0', new JSONTokener("").skipTo('A'));
- assertEquals("foo! at character 0 of ",
- new JSONTokener("").syntaxError("foo!").getMessage());
+ assertEquals("foo! at character 0 of ", new JSONTokener("").syntaxError("foo!").getMessage());
assertEquals(" at character 0 of ", new JSONTokener("").toString());
}
+ @Test
public void testCharacterNavigation() throws JSONException {
JSONTokener abcdeTokener = new JSONTokener("ABCDE");
assertEquals('A', abcdeTokener.next());
@@ -154,6 +157,7 @@ public class JSONTokenerTest extends TestCase {
assertEquals('E', abcdeTokener.next());
}
+ @Test
public void testBackNextAndMore() throws JSONException {
JSONTokener abcTokener = new JSONTokener("ABC");
assertTrue(abcTokener.more());
@@ -173,6 +177,7 @@ public class JSONTokenerTest extends TestCase {
assertEquals('A', abcTokener.next());
}
+ @Test
public void testNextMatching() throws JSONException {
JSONTokener abcdTokener = new JSONTokener("ABCD");
assertEquals('A', abcdTokener.next('A'));
@@ -190,6 +195,7 @@ public class JSONTokenerTest extends TestCase {
}
}
+ @Test
public void testNextN() throws JSONException {
JSONTokener abcdeTokener = new JSONTokener("ABCDEF");
assertEquals("", abcdeTokener.next(0));
@@ -206,6 +212,7 @@ public class JSONTokenerTest extends TestCase {
}
}
+ @Test
public void testNextNWithAllRemaining() throws JSONException {
JSONTokener tokener = new JSONTokener("ABCDEF");
tokener.next(3);
@@ -218,6 +225,7 @@ public class JSONTokenerTest extends TestCase {
}
}
+ @Test
public void testNext0() throws JSONException {
JSONTokener tokener = new JSONTokener("ABCDEF");
tokener.next(5);
@@ -231,6 +239,7 @@ public class JSONTokenerTest extends TestCase {
}
}
+ @Test
public void testNextCleanComments() throws JSONException {
JSONTokener tokener = new JSONTokener(
" A /*XX*/B/*XX//XX\n//XX\nXX*/C//X//X//X\nD/*X*///X\n");
@@ -241,6 +250,7 @@ public class JSONTokenerTest extends TestCase {
assertEquals('\0', tokener.nextClean());
}
+ @Test
public void testNextCleanNestedCStyleComments() throws JSONException {
JSONTokener tokener = new JSONTokener("A /* B /* C */ D */ E");
assertEquals('A', tokener.nextClean());
@@ -254,6 +264,7 @@ public class JSONTokenerTest extends TestCase {
* Some applications rely on parsing '#' to lead an end-of-line comment.
* http://b/2571423
*/
+ @Test
public void testNextCleanHashComments() throws JSONException {
JSONTokener tokener = new JSONTokener("A # B */ /* C */ \nD #");
assertEquals('A', tokener.nextClean());
@@ -261,15 +272,16 @@ public class JSONTokenerTest extends TestCase {
assertEquals('\0', tokener.nextClean());
}
+ @Test
public void testNextCleanCommentsTrailingSingleSlash() throws JSONException {
JSONTokener tokener = new JSONTokener(" / S /");
assertEquals('/', tokener.nextClean());
assertEquals('S', tokener.nextClean());
assertEquals('/', tokener.nextClean());
- assertEquals("nextClean doesn't consume a trailing slash",
- '\0', tokener.nextClean());
+ assertEquals("nextClean doesn't consume a trailing slash", '\0', tokener.nextClean());
}
+ @Test
public void testNextCleanTrailingOpenComment() throws JSONException {
try {
new JSONTokener(" /* ").nextClean();
@@ -279,17 +291,19 @@ public class JSONTokenerTest extends TestCase {
assertEquals('\0', new JSONTokener(" // ").nextClean());
}
+ @Test
public void testNextCleanNewlineDelimiters() throws JSONException {
assertEquals('B', new JSONTokener(" // \r\n B ").nextClean());
assertEquals('B', new JSONTokener(" // \n B ").nextClean());
assertEquals('B', new JSONTokener(" // \r B ").nextClean());
}
+ @Test
public void testNextCleanSkippedWhitespace() throws JSONException {
assertEquals("character tabulation", 'A', new JSONTokener("\tA").nextClean());
- assertEquals("line feed", 'A', new JSONTokener("\nA").nextClean());
- assertEquals("carriage return", 'A', new JSONTokener("\rA").nextClean());
- assertEquals("space", 'A', new JSONTokener(" A").nextClean());
+ assertEquals("line feed", 'A', new JSONTokener("\nA").nextClean());
+ assertEquals("carriage return", 'A', new JSONTokener("\rA").nextClean());
+ assertEquals("space", 'A', new JSONTokener(" A").nextClean());
}
/**
@@ -297,44 +311,45 @@ public class JSONTokenerTest extends TestCase {
* <a href="https://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ">list
* of whitespace characters</a>.
*/
+ @Test
public void testNextCleanRetainedWhitespace() throws JSONException {
- assertNotClean("null", '\u0000');
- assertNotClean("next line", '\u0085');
- assertNotClean("non-breaking space", '\u00a0');
- assertNotClean("ogham space mark", '\u1680');
+ assertNotClean("null", '\u0000');
+ assertNotClean("next line", '\u0085');
+ assertNotClean("non-breaking space", '\u00a0');
+ assertNotClean("ogham space mark", '\u1680');
assertNotClean("mongolian vowel separator", '\u180e');
- assertNotClean("en quad", '\u2000');
- assertNotClean("em quad", '\u2001');
- assertNotClean("en space", '\u2002');
- assertNotClean("em space", '\u2003');
- assertNotClean("three-per-em space", '\u2004');
- assertNotClean("four-per-em space", '\u2005');
- assertNotClean("six-per-em space", '\u2006');
- assertNotClean("figure space", '\u2007');
- assertNotClean("punctuation space", '\u2008');
- assertNotClean("thin space", '\u2009');
- assertNotClean("hair space", '\u200a');
- assertNotClean("zero-width space", '\u200b');
- assertNotClean("left-to-right mark", '\u200e');
- assertNotClean("right-to-left mark", '\u200f');
- assertNotClean("line separator", '\u2028');
- assertNotClean("paragraph separator", '\u2029');
+ assertNotClean("en quad", '\u2000');
+ assertNotClean("em quad", '\u2001');
+ assertNotClean("en space", '\u2002');
+ assertNotClean("em space", '\u2003');
+ assertNotClean("three-per-em space", '\u2004');
+ assertNotClean("four-per-em space", '\u2005');
+ assertNotClean("six-per-em space", '\u2006');
+ assertNotClean("figure space", '\u2007');
+ assertNotClean("punctuation space", '\u2008');
+ assertNotClean("thin space", '\u2009');
+ assertNotClean("hair space", '\u200a');
+ assertNotClean("zero-width space", '\u200b');
+ assertNotClean("left-to-right mark", '\u200e');
+ assertNotClean("right-to-left mark", '\u200f');
+ assertNotClean("line separator", '\u2028');
+ assertNotClean("paragraph separator", '\u2029');
assertNotClean("narrow non-breaking space", '\u202f');
assertNotClean("medium mathematical space", '\u205f');
- assertNotClean("ideographic space", '\u3000');
- assertNotClean("line tabulation", '\u000b');
- assertNotClean("form feed", '\u000c');
- assertNotClean("information separator 4", '\u001c');
- assertNotClean("information separator 3", '\u001d');
- assertNotClean("information separator 2", '\u001e');
- assertNotClean("information separator 1", '\u001f');
+ assertNotClean("ideographic space", '\u3000');
+ assertNotClean("line tabulation", '\u000b');
+ assertNotClean("form feed", '\u000c');
+ assertNotClean("information separator 4", '\u001c');
+ assertNotClean("information separator 3", '\u001d');
+ assertNotClean("information separator 2", '\u001e');
+ assertNotClean("information separator 1", '\u001f');
}
private void assertNotClean(String name, char c) throws JSONException {
- assertEquals("The character " + name + " is not whitespace according to the JSON spec.",
- c, new JSONTokener(new String(new char[] { c, 'A' })).nextClean());
+ assertEquals("The character " + name + " is not whitespace according to the JSON spec.", c, new JSONTokener(new String(new char[]{c, 'A'})).nextClean());
}
+ @Test
public void testNextString() throws JSONException {
assertEquals("", new JSONTokener("'").nextString('\''));
assertEquals("", new JSONTokener("\"").nextString('\"'));
@@ -357,6 +372,7 @@ public class JSONTokenerTest extends TestCase {
assertFalse(tokener.more());
}
+ @Test
public void testNextStringNoDelimiter() throws JSONException {
try {
new JSONTokener("").nextString('\'');
@@ -374,6 +390,7 @@ public class JSONTokenerTest extends TestCase {
}
}
+ @Test
public void testNextStringEscapedQuote() throws JSONException {
try {
new JSONTokener("abc\\").nextString('"');
@@ -393,6 +410,7 @@ public class JSONTokenerTest extends TestCase {
assertEquals("abc\tdef", new JSONTokener("abc\\tdef\"ghi").nextString('"'));
}
+ @Test
public void testNextStringUnicodeEscaped() throws JSONException {
// we're mixing Java escaping like \\ and JavaScript escaping like \\u
assertEquals("abc def", new JSONTokener("abc\\u0020def\"ghi").nextString('"'));
@@ -422,12 +440,14 @@ public class JSONTokenerTest extends TestCase {
}
}
+ @Test
public void testNextStringNonQuote() throws JSONException {
assertEquals("AB", new JSONTokener("ABC").nextString('C'));
assertEquals("ABCD", new JSONTokener("AB\\CDC").nextString('C'));
assertEquals("AB\nC", new JSONTokener("AB\\nCn").nextString('n'));
}
+ @Test
public void testNextTo() throws JSONException {
assertEquals("ABC", new JSONTokener("ABCDEFG").nextTo("DHI"));
assertEquals("ABCDEF", new JSONTokener("ABCDEF").nextTo(""));
@@ -469,16 +489,19 @@ public class JSONTokenerTest extends TestCase {
}
}
+ @Test
public void testNextToTrimming() {
assertEquals("ABC", new JSONTokener("\t ABC \tDEF").nextTo("DE"));
assertEquals("ABC", new JSONTokener("\t ABC \tDEF").nextTo('D'));
}
+ @Test
public void testNextToTrailing() {
assertEquals("ABC DEF", new JSONTokener("\t ABC DEF \t").nextTo("G"));
assertEquals("ABC DEF", new JSONTokener("\t ABC DEF \t").nextTo('G'));
}
+ @Test
public void testNextToDoesntStopOnNull() {
String message = "nextTo() shouldn't stop after \\0 characters";
JSONTokener tokener = new JSONTokener(" \0\t \fABC \n DEF");
@@ -487,6 +510,7 @@ public class JSONTokenerTest extends TestCase {
assertEquals(message, "", tokener.nextTo("D"));
}
+ @Test
public void testNextToConsumesNull() {
String message = "nextTo shouldn't consume \\0.";
JSONTokener tokener = new JSONTokener("ABC\0DEF");
@@ -495,6 +519,7 @@ public class JSONTokenerTest extends TestCase {
assertEquals(message, "DEF", tokener.nextTo("\0"));
}
+ @Test
public void testSkipPast() {
JSONTokener tokener = new JSONTokener("ABCDEF");
tokener.skipPast("ABC");
@@ -543,6 +568,7 @@ public class JSONTokenerTest extends TestCase {
}
}
+ @Test
public void testSkipTo() {
JSONTokener tokener = new JSONTokener("ABCDEF");
tokener.skipTo('A');
@@ -567,35 +593,39 @@ public class JSONTokenerTest extends TestCase {
assertEquals('D', tokener.next());
}
+ @Test
public void testSkipToStopsOnNull() {
JSONTokener tokener = new JSONTokener("ABC\0DEF");
tokener.skipTo('F');
assertEquals("skipTo shouldn't stop when it sees '\\0'", 'F', tokener.next());
}
+ @Test
public void testBomIgnoredAsFirstCharacterOfDocument() throws JSONException {
JSONTokener tokener = new JSONTokener("\ufeff[]");
JSONArray array = (JSONArray) tokener.nextValue();
assertEquals(0, array.length());
}
+ @Test
public void testBomTreatedAsCharacterInRestOfDocument() throws JSONException {
JSONTokener tokener = new JSONTokener("[\ufeff]");
JSONArray array = (JSONArray) tokener.nextValue();
assertEquals(1, array.length());
}
+ @Test
public void testDehexchar() {
- assertEquals( 0, JSONTokener.dehexchar('0'));
- assertEquals( 1, JSONTokener.dehexchar('1'));
- assertEquals( 2, JSONTokener.dehexchar('2'));
- assertEquals( 3, JSONTokener.dehexchar('3'));
- assertEquals( 4, JSONTokener.dehexchar('4'));
- assertEquals( 5, JSONTokener.dehexchar('5'));
- assertEquals( 6, JSONTokener.dehexchar('6'));
- assertEquals( 7, JSONTokener.dehexchar('7'));
- assertEquals( 8, JSONTokener.dehexchar('8'));
- assertEquals( 9, JSONTokener.dehexchar('9'));
+ assertEquals(0, JSONTokener.dehexchar('0'));
+ assertEquals(1, JSONTokener.dehexchar('1'));
+ assertEquals(2, JSONTokener.dehexchar('2'));
+ assertEquals(3, JSONTokener.dehexchar('3'));
+ assertEquals(4, JSONTokener.dehexchar('4'));
+ assertEquals(5, JSONTokener.dehexchar('5'));
+ assertEquals(6, JSONTokener.dehexchar('6'));
+ assertEquals(7, JSONTokener.dehexchar('7'));
+ assertEquals(8, JSONTokener.dehexchar('8'));
+ assertEquals(9, JSONTokener.dehexchar('9'));
assertEquals(10, JSONTokener.dehexchar('A'));
assertEquals(11, JSONTokener.dehexchar('B'));
assertEquals(12, JSONTokener.dehexchar('C'));
@@ -616,4 +646,69 @@ public class JSONTokenerTest extends TestCase {
assertEquals("dehexchar " + c, -1, JSONTokener.dehexchar((char) c));
}
}
+
+ @Test
+ public void testNoStackOverflowArray() throws JSONException {
+ String jsonString = generateNestedArray(JSONTokener.MAX_NESTING_LEVEL);
+ new JSONTokener(jsonString).nextValue();
+ }
+
+ @Test
+ public void testStackOverflowArray() throws JSONException {
+ String jsonString = generateNestedArray(JSONTokener.MAX_NESTING_LEVEL + 1);
+ Throwable throwable = null;
+ try {
+ new JSONTokener(jsonString).nextValue();
+ } catch (Throwable t) {
+ throwable = t;
+ }
+ assertIsMaxNestingLevelException(throwable);
+ }
+
+ private static String generateNestedArray(int depth) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < depth; i++) {
+ sb.append('[');
+ }
+ for (int i = 0; i < depth; i++) {
+ sb.append(']');
+ }
+ return sb.toString();
+ }
+
+ @Test
+ public void testNoStackOverflowObject() throws JSONException {
+ String jsonString = generateNestedObject(JSONTokener.MAX_NESTING_LEVEL);
+ new JSONTokener(jsonString).nextValue();
+ }
+
+ @Test
+ public void testStackOverflowObject() throws JSONException {
+ String jsonString = generateNestedObject(JSONTokener.MAX_NESTING_LEVEL + 1);
+ Throwable throwable = null;
+ try {
+ new JSONTokener(jsonString).nextValue();
+ } catch (Throwable t) {
+ throwable = t;
+ }
+ assertIsMaxNestingLevelException(throwable);
+ }
+
+ public static void assertIsMaxNestingLevelException(Throwable throwable) {
+ assertNotNull(throwable);
+ assertTrue(throwable instanceof JSONException);
+ assertTrue(throwable.getMessage().contains("MAX_NESTING_LEVEL"));
+ }
+
+ private static String generateNestedObject(int depth) {
+ StringBuilder sb = new StringBuilder("{");
+ for (int i = 0; i < depth - 1; i++) {
+ sb.append("\"a\":{");
+ }
+ for (int i = 0; i < depth + 1; i++) {
+ sb.append('}');
+ }
+ sb.append('}');
+ return sb.toString();
+ }
}
=====================================
src/test/java/com/github/openjson/SelfUseTest.java
=====================================
@@ -289,6 +289,6 @@ public class SelfUseTest {
@Test
public void testNextValue() throws JSONException {
tokener.nextValue();
- assertEquals(4, tokenerNextValueCalls);
+ assertEquals(1, tokenerNextValueCalls);
}
}
=====================================
src/test/java/com/github/openjson/issues/Issue18Test.java
=====================================
@@ -0,0 +1,57 @@
+package com.github.openjson.issues;
+
+import com.github.openjson.JSONArray;
+import com.github.openjson.JSONException;
+import com.github.openjson.JSONObject;
+import com.github.openjson.JSONTokener;
+import org.junit.Test;
+
+import static com.github.openjson.JSONTokenerTest.assertIsMaxNestingLevelException;
+
+public class Issue18Test {
+ private final static int TOO_DEEP_NESTING = 9999;
+
+ public static String buildNestedDoc(int nesting, String open, String close, String content) {
+ StringBuilder sb = new StringBuilder(nesting * (open.length() + close.length()));
+ for (int i = 0; i < nesting; ++i) {
+ sb.append(open);
+ if ((i & 31) == 0) {
+ sb.append("\n");
+ }
+ }
+ sb.append("\n").append(content).append("\n");
+ for (int i = 0; i < nesting; ++i) {
+ sb.append(close);
+ if ((i & 31) == 0) {
+ sb.append("\n");
+ }
+ }
+ return sb.toString();
+ }
+
+ @Test
+ public void test1() {
+ String tooDeepArray = buildNestedDoc(TOO_DEEP_NESTING, "[ ", "] ", "x");
+ JSONTokener jsonTokener = new JSONTokener(tooDeepArray);
+ Throwable throwable = null;
+ try {
+ new JSONArray(jsonTokener);
+ } catch (JSONException e) {
+ throwable = e;
+ }
+ assertIsMaxNestingLevelException(throwable);
+ }
+
+ @Test
+ public void test2() {
+ String tooDeepObject = "{" + buildNestedDoc(TOO_DEEP_NESTING, "\"a\": { ", "} ", "y") + "}";
+ Throwable throwable = null;
+ JSONTokener jsonTokener2 = new JSONTokener(tooDeepObject);
+ try {
+ new JSONObject(jsonTokener2);
+ } catch (JSONException e) {
+ throwable = e;
+ }
+ assertIsMaxNestingLevelException(throwable);
+ }
+}
View it on GitLab: https://salsa.debian.org/java-team/openjson/-/compare/daa423e2385a197875e15540e3f2f0db8006c4a2...9a8893c09850847d08e039574ef05ac1158f64b5
--
View it on GitLab: https://salsa.debian.org/java-team/openjson/-/compare/daa423e2385a197875e15540e3f2f0db8006c4a2...9a8893c09850847d08e039574ef05ac1158f64b5
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20230702/1e241ee9/attachment.htm>
More information about the pkg-java-commits
mailing list