Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

validate the length of names #1078

Merged
merged 11 commits into from
Aug 29, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -1848,7 +1848,7 @@ protected final String _parseName() throws IOException
int ch = _inputBuffer[ptr];
if (ch < codes.length && codes[ch] != 0) {
if (ch == '"') {
int start = _inputPtr;
final int start = _inputPtr;
_inputPtr = ptr+1; // to skip the quote
return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash);
}
Expand All @@ -1864,7 +1864,7 @@ protected final String _parseName() throws IOException

private String _parseName2(int startPtr, int hash, int endChar) throws IOException
{
_textBuffer.resetWithShared(_inputBuffer, startPtr, (_inputPtr - startPtr));
_textBuffer.resetWithShared(_inputBuffer, startPtr, _inputPtr - startPtr);

/* Output pointers; calls will also ensure that the buffer is
* not shared and has room for at least one more char.
Expand Down Expand Up @@ -1908,11 +1908,10 @@ private String _parseName2(int startPtr, int hash, int endChar) throws IOExcepti
}
_textBuffer.setCurrentLength(outPtr);
{
TextBuffer tb = _textBuffer;
char[] buf = tb.getTextBuffer();
int start = tb.getTextOffset();
int len = tb.size();
return _symbols.findSymbol(buf, start, len, hash);
final TextBuffer tb = _textBuffer;
final char[] buf = tb.getTextBuffer();
final int start = tb.getTextOffset();
return _symbols.findSymbol(buf, start, tb.size(), hash);
}
}

Expand Down Expand Up @@ -1962,12 +1961,12 @@ protected String _handleOddName(int i) throws IOException
int ch = _inputBuffer[ptr];
if (ch < maxCode) {
if (codes[ch] != 0) {
int start = _inputPtr-1; // -1 to bring back first char
final int start = _inputPtr-1; // -1 to bring back first char
_inputPtr = ptr;
return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash);
}
} else if (!Character.isJavaIdentifierPart((char) ch)) {
int start = _inputPtr-1; // -1 to bring back first char
final int start = _inputPtr-1; // -1 to bring back first char
_inputPtr = ptr;
return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash);
}
Expand Down Expand Up @@ -2029,7 +2028,7 @@ protected JsonToken _handleOddValue(int i) throws IOException
switch (i) {
case '\'':
/* Allow single quotes? Unlike with regular Strings, we'll eagerly parse
* contents; this so that there'sno need to store information on quote char used.
* contents; this so that there's no need to store information on quote char used.
* Also, no separation to fast/slow parsing; we'll just do
* one regular (~= slowish) parsing, to keep code simple
*/
Expand Down Expand Up @@ -2129,7 +2128,7 @@ protected JsonToken _handleApos() throws IOException

private String _handleOddName2(int startPtr, int hash, int[] codes) throws IOException
{
_textBuffer.resetWithShared(_inputBuffer, startPtr, (_inputPtr - startPtr));
_textBuffer.resetWithShared(_inputBuffer, startPtr, _inputPtr - startPtr);
char[] outBuf = _textBuffer.getCurrentSegment();
int outPtr = _textBuffer.getCurrentSegmentSize();
final int maxCode = codes.length;
Expand Down Expand Up @@ -2162,12 +2161,10 @@ private String _handleOddName2(int startPtr, int hash, int[] codes) throws IOExc
}
_textBuffer.setCurrentLength(outPtr);
{
TextBuffer tb = _textBuffer;
char[] buf = tb.getTextBuffer();
int start = tb.getTextOffset();
int len = tb.size();

return _symbols.findSymbol(buf, start, len, hash);
final TextBuffer tb = _textBuffer;
final char[] buf = tb.getTextBuffer();
final int start = tb.getTextOffset();
return _symbols.findSymbol(buf, start, tb.size(), hash);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1980,7 +1980,7 @@ protected final String parseLongName(int q, final int q2, int q3) throws IOExcep

// Nope, no end in sight. Need to grow quad array etc
if (qlen >= _quadBuffer.length) {
_quadBuffer = growArrayBy(_quadBuffer, qlen);
_quadBuffer = growArrayWithNameLenCheck(_quadBuffer, qlen);
}
_quadBuffer[qlen++] = q;
q = i;
Expand Down Expand Up @@ -2014,6 +2014,12 @@ private final String parseName(int q1, int ch, int lastQuadBytes) throws IOExcep
return parseEscapedName(_quadBuffer, 0, q1, ch, lastQuadBytes);
}

private int[] growArrayWithNameLenCheck(int[] arr, int more) throws StreamConstraintsException {
// the following check will fail if the array is already bigger than is allowed for names
_streamReadConstraints.validateNameLength(arr.length << 2);
return growArrayBy(_quadBuffer, more);
}

private final String parseName(int q1, int q2, int ch, int lastQuadBytes) throws IOException {
_quadBuffer[0] = q1;
return parseEscapedName(_quadBuffer, 1, q2, ch, lastQuadBytes);
Expand Down Expand Up @@ -2057,7 +2063,7 @@ protected final String parseEscapedName(int[] quads, int qlen, int currQuad, int
// Ok, we'll need room for first byte right away
if (currQuadBytes >= 4) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = 0;
Expand All @@ -2073,7 +2079,7 @@ protected final String parseEscapedName(int[] quads, int qlen, int currQuad, int
// need room for middle byte?
if (currQuadBytes >= 4) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = 0;
Expand All @@ -2092,7 +2098,7 @@ protected final String parseEscapedName(int[] quads, int qlen, int currQuad, int
currQuad = (currQuad << 8) | ch;
} else {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = ch;
Expand All @@ -2108,10 +2114,11 @@ protected final String parseEscapedName(int[] quads, int qlen, int currQuad, int

if (currQuadBytes > 0) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = _padLastQuad(currQuad, currQuadBytes);
}
_streamReadConstraints.validateNameLength(qlen << 2);
String name = _symbols.findName(quads, qlen);
if (name == null) {
name = addName(quads, qlen, currQuadBytes);
Expand Down Expand Up @@ -2168,7 +2175,7 @@ protected String _handleOddName(int ch) throws IOException
currQuad = (currQuad << 8) | ch;
} else {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = ch;
Expand All @@ -2188,10 +2195,11 @@ protected String _handleOddName(int ch) throws IOException

if (currQuadBytes > 0) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
}
_streamReadConstraints.validateNameLength(qlen << 2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this could be instead moved to inside addName() which is only called if findName() does not find already canonicalized name.

String name = _symbols.findName(quads, qlen);
if (name == null) {
name = addName(quads, qlen, currQuadBytes);
Expand Down Expand Up @@ -2242,7 +2250,7 @@ protected String _parseAposName() throws IOException
// Ok, we'll need room for first byte right away
if (currQuadBytes >= 4) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = 0;
Expand All @@ -2258,7 +2266,7 @@ protected String _parseAposName() throws IOException
// need room for middle byte?
if (currQuadBytes >= 4) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = 0;
Expand All @@ -2277,7 +2285,7 @@ protected String _parseAposName() throws IOException
currQuad = (currQuad << 8) | ch;
} else {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = ch;
Expand All @@ -2293,10 +2301,11 @@ protected String _parseAposName() throws IOException

if (currQuadBytes > 0) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = _padLastQuad(currQuad, currQuadBytes);
}
_streamReadConstraints.validateNameLength(qlen << 2);
String name = _symbols.findName(quads, qlen);
if (name == null) {
name = addName(quads, qlen, currQuadBytes);
Expand Down Expand Up @@ -2358,9 +2367,10 @@ private final String findName(int[] quads, int qlen, int lastQuad, int lastQuadB
throws JsonParseException, StreamConstraintsException
{
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = _padLastQuad(lastQuad, lastQuadBytes);
_streamReadConstraints.validateNameLength(qlen << 2);
String name = _symbols.findName(quads, qlen);
if (name == null) {
return addName(quads, qlen, lastQuadBytes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,8 @@ protected final String _addName(int[] quads, int qlen, int lastQuadBytes)
* (as well as error reporting for unescaped control chars)
*/
// 4 bytes per quad, except last one maybe less
int byteLen = (qlen << 2) - 4 + lastQuadBytes;
final int byteLen = (qlen << 2) - 4 + lastQuadBytes;
_streamReadConstraints.validateNameLength(byteLen);

/* And last one is not correctly aligned (leading zero bytes instead
* need to shift a bit, instead of trailing). Only need to shift it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.exc.StreamConstraintsException;
import com.fasterxml.jackson.core.io.CharTypes;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.core.json.JsonReadFeature;
Expand Down Expand Up @@ -2096,7 +2097,7 @@ private final JsonToken _parseEscapedName(int qlen, int currQuad, int currQuadBy
continue;
}
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = ch;
Expand Down Expand Up @@ -2129,7 +2130,7 @@ private final JsonToken _parseEscapedName(int qlen, int currQuad, int currQuadBy
// 7-bit ASCII. Gets pretty messy. If this happens often, may
// want to use different name canonicalization to avoid these hits.
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
if (ch > 127) {
// Ok, we'll need room for first byte right away
Expand Down Expand Up @@ -2169,7 +2170,7 @@ private final JsonToken _parseEscapedName(int qlen, int currQuad, int currQuadBy

if (currQuadBytes > 0) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = _padLastQuad(currQuad, currQuadBytes);
} else if (qlen == 0) { // rare, but may happen
Expand Down Expand Up @@ -2259,7 +2260,7 @@ private JsonToken _finishUnquotedName(int qlen, int currQuad, int currQuadBytes)
currQuad = (currQuad << 8) | ch;
} else {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = ch;
Expand All @@ -2269,7 +2270,7 @@ private JsonToken _finishUnquotedName(int qlen, int currQuad, int currQuadBytes)

if (currQuadBytes > 0) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
}
Expand Down Expand Up @@ -2319,7 +2320,7 @@ private JsonToken _finishAposName(int qlen, int currQuad, int currQuadBytes)
// Ok, we'll need room for first byte right away
if (currQuadBytes >= 4) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = 0;
Expand All @@ -2335,7 +2336,7 @@ private JsonToken _finishAposName(int qlen, int currQuad, int currQuadBytes)
// need room for middle byte?
if (currQuadBytes >= 4) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = 0;
Expand All @@ -2354,7 +2355,7 @@ private JsonToken _finishAposName(int qlen, int currQuad, int currQuadBytes)
currQuad = (currQuad << 8) | ch;
} else {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = currQuad;
currQuad = ch;
Expand All @@ -2364,7 +2365,7 @@ private JsonToken _finishAposName(int qlen, int currQuad, int currQuadBytes)

if (currQuadBytes > 0) {
if (qlen >= quads.length) {
_quadBuffer = quads = growArrayBy(quads, quads.length);
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
}
quads[qlen++] = _padLastQuad(currQuad, currQuadBytes);
} else if (qlen == 0) { // rare case but possible
Expand All @@ -2386,7 +2387,7 @@ protected final JsonToken _finishFieldWithEscape() throws IOException
return JsonToken.NOT_AVAILABLE;
}
if (_quadLength >= _quadBuffer.length) {
_quadBuffer = growArrayBy(_quadBuffer, 32);
_quadBuffer = growArrayWithNameLenCheck(_quadBuffer, 32);
}
int currQuad = _pending32;
int currQuadBytes = _pendingBytes;
Expand Down Expand Up @@ -2429,6 +2430,12 @@ protected final JsonToken _finishFieldWithEscape() throws IOException
return _parseEscapedName(_quadLength, currQuad, currQuadBytes);
}

private int[] growArrayWithNameLenCheck(int[] arr, int more) throws StreamConstraintsException {
// the following check will fail if the array is already bigger than is allowed for names
_streamReadConstraints.validateNameLength(arr.length << 2);
return growArrayBy(_quadBuffer, more);
}

private int _decodeSplitEscaped(int value, int bytesRead) throws IOException
{
if (_inputPtr >= _inputEnd) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ public String findSymbol(char[] buffer, int start, int len, int h) throws IOExce
if (len < 1) { // empty Strings are simplest to handle up front
return "";
}
_streamReadConstraints.validateNameLength(len);
if (!_canonicalize) { // [JACKSON-259]
return new String(buffer, start, len);
}
Expand Down
Loading