From b900547b1869ec32cd4a72bfe42ab6a03a60f69a Mon Sep 17 00:00:00 2001 From: Sharon Chua <115637619+scyt01@users.noreply.github.com> Date: Fri, 18 Jul 2025 00:11:12 +0800 Subject: [PATCH] Fix JSON parsing stack overflow vulnerabilities --- .../com/dtstack/chunjun/util/GsonUtil.java | 91 +++++++++++-------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/chunjun-core/src/main/java/com/dtstack/chunjun/util/GsonUtil.java b/chunjun-core/src/main/java/com/dtstack/chunjun/util/GsonUtil.java index 5d64651127..c01c3ed13a 100644 --- a/chunjun-core/src/main/java/com/dtstack/chunjun/util/GsonUtil.java +++ b/chunjun-core/src/main/java/com/dtstack/chunjun/util/GsonUtil.java @@ -72,51 +72,62 @@ public TypeAdapter create(Gson gson, TypeToken type) { return new TypeAdapter() { @Override public Object read(JsonReader in) throws IOException { - JsonToken token = in.peek(); - // 判断字符串的实际类型 - switch (token) { - case BEGIN_ARRAY: - List list = new ArrayList<>(); - in.beginArray(); - while (in.hasNext()) { - list.add(read(in)); + // Either List or Map + Object current; + JsonToken peeked = in.peek(); + + current = tryBeginNesting(in, peeked); + if (current == null) { + return readTerminal(in, peeked); + } + + Deque stack = new ArrayDeque<>(); + + while (true) { + while (in.hasNext()) { + String name = null; + // Name is only used for JSON object members + if (current instanceof Map) { + name = in.nextName(); } - in.endArray(); - return list; - case BEGIN_OBJECT: - Map map = - new LinkedTreeMap<>(); - in.beginObject(); - while (in.hasNext()) { - map.put(in.nextName(), read(in)); + peeked = in.peek(); + Object value = tryBeginNesting(in, peeked); + boolean isNesting = value != null; + + if (value == null) { + value = readTerminal(in, peeked); } - in.endObject(); - return map; - case STRING: - return in.nextString(); - case NUMBER: - String s = in.nextString(); - if (s.contains(".")) { - return Double.valueOf(s); + + if (current instanceof List) { + @SuppressWarnings("unchecked") + List list = (List) current; + list.add(value); } else { - try { - return Integer.valueOf(s); - } catch (Exception e) { - try { - return Long.valueOf(s); - } catch (Exception e1) { - return new BigInteger(s); - } - } + @SuppressWarnings("unchecked") + Map map = (Map) current; + map.put(name, value); } - case BOOLEAN: - return in.nextBoolean(); - case NULL: - in.nextNull(); - return null; - default: - throw new IllegalStateException(); + + if (isNesting) { + stack.addLast(current); + current = value; + } + } + + // End current element + if (current instanceof List) { + in.endArray(); + } else { + in.endObject(); + } + + if (stack.isEmpty()) { + return current; + } else { + // Continue with enclosing element + current = stack.removeLast(); + } } }