Skip to content

Commit

Permalink
JSON parsing should detect embedded \0 values
Browse files Browse the repository at this point in the history
See:
stleary/JSON-java#758
stleary/JSON-java#759

Port pull #759 from stleary/JSON-java to help
address OOM errors described in
https://www.cve.org/CVERecord?id=CVE-2023-5072

To support the JSONTokener.end() function this
relies on, port over the 'eof' flag & set in
all locations it's used in the latest JSON-java.

Use the String next(int n) implementation from
more recent java versions so we can properly check
end() while reading a group of characters.

Test by:
- importing into alpha locally & running all tests
that depend on //thirdparty:json
- verifying that Snyk's proof-of-concept does
not cause OOMs:
https://security.snyk.io/vuln/SNYK-JAVA-ORGJSON-5962464
  • Loading branch information
claireagordon committed Mar 26, 2024
1 parent bf3a2ff commit 4fa27f1
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 22 deletions.
3 changes: 3 additions & 0 deletions org/json/JSONObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ public JSONObject(JSONTokener x) throws JSONException {
if (x.nextClean() == '}') {
return;
}
if (x.end()) {
throw x.syntaxError("A JSONObject text must end with '}'");
}
x.back();
break;
case '}':
Expand Down
40 changes: 18 additions & 22 deletions org/json/JSONTokener.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ of this software and associated documentation files (the "Software"), to deal
public class JSONTokener {

private int index;
private boolean eof;
private Reader reader;
private char lastChar;
private boolean useLastChar;
Expand All @@ -50,6 +51,7 @@ public class JSONTokener {
* @param reader A reader.
*/
public JSONTokener(Reader reader) {
this.eof = false;
this.reader = reader.markSupported() ?
reader : new BufferedReader(reader);
this.useLastChar = false;
Expand Down Expand Up @@ -78,6 +80,7 @@ public void back() throws JSONException {
}
index -= 1;
useLastChar = true;
this.eof = false;
}


Expand All @@ -101,15 +104,19 @@ public static int dehexchar(char c) {
return -1;
}

public boolean end() {
return eof && !useLastChar;
}


/**
* Determine if the source string still contains characters that next()
* can consume.
* @return true if not yet at the end of the source.
*/
public boolean more() throws JSONException {
char nextChar = next();
if (nextChar == 0) {
next();
if (end()) {
return false;
}
back();
Expand Down Expand Up @@ -138,6 +145,7 @@ public char next() throws JSONException {
}

if (c <= 0) { // End of stream
this.eof = true;
this.lastChar = 0;
return 0;
}
Expand Down Expand Up @@ -181,27 +189,13 @@ public String next(int n) throws JSONException {
char[] buffer = new char[n];
int pos = 0;

if (this.useLastChar) {
this.useLastChar = false;
buffer[0] = this.lastChar;
pos = 1;
}

try {
int len;
while ((pos < n) && ((len = reader.read(buffer, pos, n - pos)) != -1)) {
pos += len;
while (pos < n) {
buffer[pos] = this.next();
if (this.end()) {
throw this.syntaxError("Substring bounds error");
}
} catch (IOException exc) {
throw new JSONException(exc);
pos += 1;
}
this.index += pos;

if (pos < n) {
throw syntaxError("Substring bounds error");
}

this.lastChar = buffer[n - 1];
return new String(buffer);
}

Expand Down Expand Up @@ -400,7 +394,9 @@ Object nextSimpleValue(char c) throws JSONException {
sb.append(c);
c = next();
}
back();
if (!this.eof) {
back();
}

/*
* If it is true, false, or null, return the proper value.
Expand Down

0 comments on commit 4fa27f1

Please sign in to comment.