mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add exception for json
This commit is contained in:
parent
bc808210fd
commit
68d28c4fd4
@ -18,7 +18,7 @@
|
||||
|
||||
<properties>
|
||||
<!-- versions -->
|
||||
<bouncycastle.version>1.71</bouncycastle.version>
|
||||
<bouncycastle.version>1.72</bouncycastle.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -20,10 +20,12 @@
|
||||
<!-- versions -->
|
||||
<c3p0.version>0.9.5.5</c3p0.version>
|
||||
<dbcp2.version>2.9.0</dbcp2.version>
|
||||
<tomcat-jdbc.version>10.0.20</tomcat-jdbc.version>
|
||||
<druid.version>1.2.12</druid.version>
|
||||
<!-- 固定10.0.x -->
|
||||
<tomcat-jdbc.version>10.0.27</tomcat-jdbc.version>
|
||||
<druid.version>1.2.15</druid.version>
|
||||
<!-- 固定4.x -->
|
||||
<hikariCP.version>4.0.3</hikariCP.version>
|
||||
<sqlite.version>3.39.3.0</sqlite.version>
|
||||
<sqlite.version>3.39.4.1</sqlite.version>
|
||||
<!-- 此处固定2.5.x,支持到JDK8 -->
|
||||
<hsqldb.version>2.5.2</hsqldb.version>
|
||||
</properties>
|
||||
@ -79,7 +81,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.chris2018998</groupId>
|
||||
<artifactId>beecp</artifactId>
|
||||
<version>3.3.8</version>
|
||||
<version>3.3.9</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
@ -135,7 +137,7 @@
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.0.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<properties>
|
||||
<!-- versions -->
|
||||
<velocity.version>2.3</velocity.version>
|
||||
<beetl.version>3.10.0.RELEASE</beetl.version>
|
||||
<beetl.version>3.13.0.RELEASE</beetl.version>
|
||||
<rythm.version>1.4.1</rythm.version>
|
||||
<freemarker.version>2.3.31</freemarker.version>
|
||||
<enjoy.version>4.9.21</enjoy.version>
|
||||
@ -31,7 +31,7 @@
|
||||
<net.version>3.8.0</net.version>
|
||||
<emoji-java.version>5.1.1</emoji-java.version>
|
||||
<servlet-api.version>4.0.1</servlet-api.version>
|
||||
<spring-boot.version>2.7.4</spring-boot.version>
|
||||
<spring-boot.version>2.7.5</spring-boot.version>
|
||||
<cglib.version>3.3.0</cglib.version>
|
||||
</properties>
|
||||
|
||||
@ -430,7 +430,7 @@
|
||||
<dependency>
|
||||
<groupId>com.googlecode.aviator</groupId>
|
||||
<artifactId>aviator</artifactId>
|
||||
<version>5.3.2</version>
|
||||
<version>5.3.3</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@ -465,7 +465,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>5.3.23</version>
|
||||
<version>5.3.24</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@ -495,13 +495,13 @@
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>6.2.2</version>
|
||||
<version>6.3.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.xml.bind</groupId>
|
||||
<artifactId>jaxb-impl</artifactId>
|
||||
<version>2.3.6</version>
|
||||
<version>2.3.7</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
<properties>
|
||||
<!-- versions -->
|
||||
<bouncycastle.version>1.70</bouncycastle.version>
|
||||
<bouncycastle.version>1.72</bouncycastle.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -50,19 +50,26 @@ public class JSONParser {
|
||||
public void parseTo(final JSONObject jsonObject, final Predicate<MutableEntry<String, Object>> predicate) {
|
||||
final JSONTokener tokener = this.tokener;
|
||||
|
||||
char c;
|
||||
String key;
|
||||
|
||||
if (tokener.nextClean() != '{') {
|
||||
throw tokener.syntaxError("A JSONObject text must begin with '{'");
|
||||
}
|
||||
|
||||
char prev;
|
||||
char c;
|
||||
String key;
|
||||
while (true) {
|
||||
prev = tokener.getPrevious();
|
||||
c = tokener.nextClean();
|
||||
switch (c) {
|
||||
case 0:
|
||||
throw tokener.syntaxError("A JSONObject text must end with '}'");
|
||||
case '}':
|
||||
return;
|
||||
case '{':
|
||||
case '[':
|
||||
if(prev=='{') {
|
||||
throw tokener.syntaxError("A JSONObject can not directly nest another JSONObject or JSONArray.");
|
||||
}
|
||||
default:
|
||||
tokener.back();
|
||||
key = tokener.nextValue().toString();
|
||||
|
@ -162,6 +162,15 @@ public class JSONTokener {
|
||||
return this.previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last character read from the input or '\0' if nothing has been read yet.
|
||||
*
|
||||
* @return the last character read from the input.
|
||||
*/
|
||||
protected char getPrevious() {
|
||||
return this.previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取下一个字符,并比对是否和指定字符匹配
|
||||
*
|
||||
@ -334,10 +343,18 @@ public class JSONTokener {
|
||||
return this.nextString(c);
|
||||
case '{':
|
||||
this.back();
|
||||
return new JSONObject(this, this.config);
|
||||
try {
|
||||
return new JSONObject(this, this.config);
|
||||
} catch (final StackOverflowError e) {
|
||||
throw new JSONException("JSONObject depth too large to process.", e);
|
||||
}
|
||||
case '[':
|
||||
this.back();
|
||||
return new JSONArray(this, this.config);
|
||||
try {
|
||||
return new JSONArray(this, this.config);
|
||||
} catch (final StackOverflowError e) {
|
||||
throw new JSONException("JSONArray depth too large to process.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -113,9 +113,38 @@ public class XMLTokener extends JSONTokener {
|
||||
throw syntaxError("Missing ';' in XML entity: &" + sb);
|
||||
}
|
||||
}
|
||||
final String string = sb.toString();
|
||||
final Object object = entity.get(string);
|
||||
return object != null ? object : ampersand + string + ";";
|
||||
return unescapeEntity(sb.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescape an XML entity encoding;
|
||||
*
|
||||
* @param e entity (only the actual entity value, not the preceding & or ending ;
|
||||
* @return Unescape str
|
||||
*/
|
||||
static String unescapeEntity(final String e) {
|
||||
// validate
|
||||
if (e == null || e.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
// if our entity is an encoded unicode point, parse it.
|
||||
if (e.charAt(0) == '#') {
|
||||
final int cp;
|
||||
if (e.charAt(1) == 'x' || e.charAt(1) == 'X') {
|
||||
// hex encoded unicode
|
||||
cp = Integer.parseInt(e.substring(2), 16);
|
||||
} else {
|
||||
// decimal encoded unicode
|
||||
cp = Integer.parseInt(e.substring(1));
|
||||
}
|
||||
return new String(new int[]{cp}, 0, 1);
|
||||
}
|
||||
final Character knownEntity = entity.get(e);
|
||||
if (knownEntity == null) {
|
||||
// we don't know the entity so keep it encoded
|
||||
return '&' + e + ';';
|
||||
}
|
||||
return knownEntity.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
24
hutool-json/src/test/java/cn/hutool/json/Issue2746Test.java
Executable file
24
hutool-json/src/test/java/cn/hutool/json/Issue2746Test.java
Executable file
@ -0,0 +1,24 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Issue2746Test {
|
||||
|
||||
@Test
|
||||
public void parseObjTest() {
|
||||
final String str = StrUtil.repeat("{", 1500) + StrUtil.repeat("}", 1500);
|
||||
try{
|
||||
JSONUtil.parseObj(str);
|
||||
} catch (final JSONException e){
|
||||
Assert.assertTrue(e.getMessage().startsWith("A JSONObject can not directly nest another JSONObject or JSONArray"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = JSONException.class)
|
||||
public void parseTest() {
|
||||
final String str = StrUtil.repeat("[", 1500) + StrUtil.repeat("]", 1500);
|
||||
JSONUtil.parseArray(str);
|
||||
}
|
||||
}
|
37
hutool-json/src/test/java/cn/hutool/json/Issue2749Test.java
Executable file
37
hutool-json/src/test/java/cn/hutool/json/Issue2749Test.java
Executable file
@ -0,0 +1,37 @@
|
||||
package cn.hutool.json;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* https://github.com/dromara/hutool/issues/2749
|
||||
* <p>
|
||||
* 由于使用了递归方式解析和写出,导致JSON太长的话容易栈溢出。
|
||||
*/
|
||||
public class Issue2749Test {
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void jsonObjectTest() {
|
||||
final Map<String, Object> map = new HashMap<>(1, 1f);
|
||||
Map<String, Object> node = map;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
//noinspection unchecked
|
||||
node = (Map<String, Object>) node.computeIfAbsent("a", k -> new HashMap<String, Object>(1, 1f));
|
||||
}
|
||||
node.put("a", 1);
|
||||
final String jsonStr = JSONUtil.toJsonStr(map);
|
||||
|
||||
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
|
||||
final JSONObject jsonObject = new JSONObject(jsonStr);
|
||||
Assert.assertNotNull(jsonObject);
|
||||
|
||||
// 栈溢出
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
jsonObject.toString();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user