Skip to content

Commit a16cb6a

Browse files
author
Akriti Singh
committed
Fixing vulnerability CVE-2023-34620 in hjson library by adding the implementation of maximum depth while parsing input JSON.
1 parent f7489df commit a16cb6a

2 files changed

Lines changed: 47 additions & 13 deletions

File tree

src/main/org/hjson/HjsonParser.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class HjsonParser {
3838
private StringBuilder captureBuffer, peek;
3939
private boolean capture;
4040
private boolean legacyRoot;
41+
private static final int MAX_DEPTH=1000;
4142

4243
private IHjsonDsfProvider[] dsfProviders;
4344

@@ -111,14 +112,28 @@ JsonValue checkTrailing(JsonValue v) throws ParseException, IOException {
111112
return v;
112113
}
113114

114-
private JsonValue readValue() throws IOException {
115+
private JsonValue readValue() throws IOException, ParseException {
116+
return readValue(0);
117+
}
118+
119+
private JsonValue readValue(int depth) throws IOException, ParseException {
120+
if(current==123) {
121+
++depth;
122+
}
123+
/* The following has been refrenced for the resolution of the vulnerability:
124+
https://github.com/FasterXML/jackson-databind/commit/fcfc4998ec23f0b1f7f8a9521c2b317b6c25892b
125+
*/
126+
if(depth>MAX_DEPTH) {
127+
throw error("The passed json has exhausted the depth supported of "+MAX_DEPTH+".");
128+
}
115129
switch(current) {
116130
case '\'':
117131
case '"': return readString();
118-
case '[': return readArray();
119-
case '{': return readObject(false);
132+
case '[': return readArray(depth);
133+
case '{': return readObject(false, depth);
120134
default: return readTfnns();
121135
}
136+
122137
}
123138

124139
private JsonValue readTfnns() throws IOException {
@@ -161,7 +176,7 @@ private JsonValue readTfnns() throws IOException {
161176
}
162177
}
163178

164-
private JsonArray readArray() throws IOException {
179+
private JsonArray readArray(int depth) throws IOException {
165180
read();
166181
JsonArray array=new JsonArray();
167182
skipWhiteSpace();
@@ -170,7 +185,7 @@ private JsonArray readArray() throws IOException {
170185
}
171186
while (true) {
172187
skipWhiteSpace();
173-
array.add(readValue());
188+
array.add(readValue(depth));
174189
skipWhiteSpace();
175190
if (readIf(',')) skipWhiteSpace(); // , is optional
176191
if (readIf(']')) break;
@@ -180,6 +195,10 @@ private JsonArray readArray() throws IOException {
180195
}
181196

182197
private JsonObject readObject(boolean objectWithoutBraces) throws IOException {
198+
return this.readObject(objectWithoutBraces, 0);
199+
}
200+
201+
private JsonObject readObject(boolean objectWithoutBraces, int depth) throws IOException, ParseException {
183202
if (!objectWithoutBraces) read();
184203
JsonObject object=new JsonObject();
185204
skipWhiteSpace();
@@ -196,7 +215,7 @@ private JsonObject readObject(boolean objectWithoutBraces) throws IOException {
196215
throw expected("':'");
197216
}
198217
skipWhiteSpace();
199-
object.add(name, readValue());
218+
object.add(name, readValue(depth));
200219
skipWhiteSpace();
201220
if (readIf(',')) skipWhiteSpace(); // , is optional
202221
}

src/main/org/hjson/JsonParser.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class JsonParser {
4242
private int current;
4343
private StringBuilder captureBuffer;
4444
private int captureStart;
45+
private static final int MAX_DEPTH=1000;
4546

4647
/*
4748
* | bufferOffset
@@ -77,7 +78,21 @@ JsonValue parse() throws IOException {
7778
return result;
7879
}
7980

80-
private JsonValue readValue() throws IOException {
81+
private JsonValue readValue() throws IOException{
82+
return readValue(0);
83+
}
84+
85+
86+
private JsonValue readValue(int depth) throws IOException {
87+
if(current==123) {
88+
++depth;
89+
}
90+
/* The following has been refrenced for the resolution of the vulnerability:
91+
https://github.com/FasterXML/jackson-databind/commit/fcfc4998ec23f0b1f7f8a9521c2b317b6c25892b
92+
*/
93+
if(depth>MAX_DEPTH) {
94+
throw error("The passed json has exhausted the maximum supported depth of "+MAX_DEPTH+".");
95+
}
8196
switch(current) {
8297
case 'n':
8398
return readNull();
@@ -88,9 +103,9 @@ private JsonValue readValue() throws IOException {
88103
case '"':
89104
return readString();
90105
case '[':
91-
return readArray();
106+
return readArray(depth);
92107
case '{':
93-
return readObject();
108+
return readObject(depth);
94109
case '-':
95110
case '0':
96111
case '1':
@@ -108,7 +123,7 @@ private JsonValue readValue() throws IOException {
108123
}
109124
}
110125

111-
private JsonArray readArray() throws IOException {
126+
private JsonArray readArray(int depth) throws IOException {
112127
read();
113128
JsonArray array=new JsonArray();
114129
skipWhiteSpace();
@@ -117,7 +132,7 @@ private JsonArray readArray() throws IOException {
117132
}
118133
do {
119134
skipWhiteSpace();
120-
array.add(readValue());
135+
array.add(readValue(depth));
121136
skipWhiteSpace();
122137
} while (readIf(','));
123138
if (!readIf(']')) {
@@ -126,7 +141,7 @@ private JsonArray readArray() throws IOException {
126141
return array;
127142
}
128143

129-
private JsonObject readObject() throws IOException {
144+
private JsonObject readObject(int depth) throws IOException {
130145
read();
131146
JsonObject object=new JsonObject();
132147
skipWhiteSpace();
@@ -141,7 +156,7 @@ private JsonObject readObject() throws IOException {
141156
throw expected("':'");
142157
}
143158
skipWhiteSpace();
144-
object.add(name, readValue());
159+
object.add(name, readValue(depth));
145160
skipWhiteSpace();
146161
} while (readIf(','));
147162
if (!readIf('}')) {

0 commit comments

Comments
 (0)