Skip to content

Commit bc8433b

Browse files
authored
validate the length of names (#1078)
1 parent e13b72f commit bc8433b

File tree

6 files changed

+142
-41
lines changed

6 files changed

+142
-41
lines changed

src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,7 +1848,7 @@ protected final String _parseName() throws IOException
18481848
int ch = _inputBuffer[ptr];
18491849
if (ch < codes.length && codes[ch] != 0) {
18501850
if (ch == '"') {
1851-
int start = _inputPtr;
1851+
final int start = _inputPtr;
18521852
_inputPtr = ptr+1; // to skip the quote
18531853
return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash);
18541854
}
@@ -1864,7 +1864,7 @@ protected final String _parseName() throws IOException
18641864

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

18691869
/* Output pointers; calls will also ensure that the buffer is
18701870
* not shared and has room for at least one more char.
@@ -1908,11 +1908,10 @@ private String _parseName2(int startPtr, int hash, int endChar) throws IOExcepti
19081908
}
19091909
_textBuffer.setCurrentLength(outPtr);
19101910
{
1911-
TextBuffer tb = _textBuffer;
1912-
char[] buf = tb.getTextBuffer();
1913-
int start = tb.getTextOffset();
1914-
int len = tb.size();
1915-
return _symbols.findSymbol(buf, start, len, hash);
1911+
final TextBuffer tb = _textBuffer;
1912+
final char[] buf = tb.getTextBuffer();
1913+
final int start = tb.getTextOffset();
1914+
return _symbols.findSymbol(buf, start, tb.size(), hash);
19161915
}
19171916
}
19181917

@@ -1962,12 +1961,12 @@ protected String _handleOddName(int i) throws IOException
19621961
int ch = _inputBuffer[ptr];
19631962
if (ch < maxCode) {
19641963
if (codes[ch] != 0) {
1965-
int start = _inputPtr-1; // -1 to bring back first char
1964+
final int start = _inputPtr-1; // -1 to bring back first char
19661965
_inputPtr = ptr;
19671966
return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash);
19681967
}
19691968
} else if (!Character.isJavaIdentifierPart((char) ch)) {
1970-
int start = _inputPtr-1; // -1 to bring back first char
1969+
final int start = _inputPtr-1; // -1 to bring back first char
19711970
_inputPtr = ptr;
19721971
return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash);
19731972
}
@@ -2029,7 +2028,7 @@ protected JsonToken _handleOddValue(int i) throws IOException
20292028
switch (i) {
20302029
case '\'':
20312030
/* Allow single quotes? Unlike with regular Strings, we'll eagerly parse
2032-
* contents; this so that there'sno need to store information on quote char used.
2031+
* contents; this so that there's no need to store information on quote char used.
20332032
* Also, no separation to fast/slow parsing; we'll just do
20342033
* one regular (~= slowish) parsing, to keep code simple
20352034
*/
@@ -2129,7 +2128,7 @@ protected JsonToken _handleApos() throws IOException
21292128

21302129
private String _handleOddName2(int startPtr, int hash, int[] codes) throws IOException
21312130
{
2132-
_textBuffer.resetWithShared(_inputBuffer, startPtr, (_inputPtr - startPtr));
2131+
_textBuffer.resetWithShared(_inputBuffer, startPtr, _inputPtr - startPtr);
21332132
char[] outBuf = _textBuffer.getCurrentSegment();
21342133
int outPtr = _textBuffer.getCurrentSegmentSize();
21352134
final int maxCode = codes.length;
@@ -2162,12 +2161,10 @@ private String _handleOddName2(int startPtr, int hash, int[] codes) throws IOExc
21622161
}
21632162
_textBuffer.setCurrentLength(outPtr);
21642163
{
2165-
TextBuffer tb = _textBuffer;
2166-
char[] buf = tb.getTextBuffer();
2167-
int start = tb.getTextOffset();
2168-
int len = tb.size();
2169-
2170-
return _symbols.findSymbol(buf, start, len, hash);
2164+
final TextBuffer tb = _textBuffer;
2165+
final char[] buf = tb.getTextBuffer();
2166+
final int start = tb.getTextOffset();
2167+
return _symbols.findSymbol(buf, start, tb.size(), hash);
21712168
}
21722169
}
21732170

src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,7 +1980,7 @@ protected final String parseLongName(int q, final int q2, int q3) throws IOExcep
19801980

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

2017+
private int[] growArrayWithNameLenCheck(int[] arr, int more) throws StreamConstraintsException {
2018+
// the following check will fail if the array is already bigger than is allowed for names
2019+
_streamReadConstraints.validateNameLength(arr.length << 2);
2020+
return growArrayBy(_quadBuffer, more);
2021+
}
2022+
20172023
private final String parseName(int q1, int q2, int ch, int lastQuadBytes) throws IOException {
20182024
_quadBuffer[0] = q1;
20192025
return parseEscapedName(_quadBuffer, 1, q2, ch, lastQuadBytes);
@@ -2057,7 +2063,7 @@ protected final String parseEscapedName(int[] quads, int qlen, int currQuad, int
20572063
// Ok, we'll need room for first byte right away
20582064
if (currQuadBytes >= 4) {
20592065
if (qlen >= quads.length) {
2060-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2066+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
20612067
}
20622068
quads[qlen++] = currQuad;
20632069
currQuad = 0;
@@ -2073,7 +2079,7 @@ protected final String parseEscapedName(int[] quads, int qlen, int currQuad, int
20732079
// need room for middle byte?
20742080
if (currQuadBytes >= 4) {
20752081
if (qlen >= quads.length) {
2076-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2082+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
20772083
}
20782084
quads[qlen++] = currQuad;
20792085
currQuad = 0;
@@ -2092,7 +2098,7 @@ protected final String parseEscapedName(int[] quads, int qlen, int currQuad, int
20922098
currQuad = (currQuad << 8) | ch;
20932099
} else {
20942100
if (qlen >= quads.length) {
2095-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2101+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
20962102
}
20972103
quads[qlen++] = currQuad;
20982104
currQuad = ch;
@@ -2108,7 +2114,7 @@ protected final String parseEscapedName(int[] quads, int qlen, int currQuad, int
21082114

21092115
if (currQuadBytes > 0) {
21102116
if (qlen >= quads.length) {
2111-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2117+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
21122118
}
21132119
quads[qlen++] = _padLastQuad(currQuad, currQuadBytes);
21142120
}
@@ -2168,7 +2174,7 @@ protected String _handleOddName(int ch) throws IOException
21682174
currQuad = (currQuad << 8) | ch;
21692175
} else {
21702176
if (qlen >= quads.length) {
2171-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2177+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
21722178
}
21732179
quads[qlen++] = currQuad;
21742180
currQuad = ch;
@@ -2188,7 +2194,7 @@ protected String _handleOddName(int ch) throws IOException
21882194

21892195
if (currQuadBytes > 0) {
21902196
if (qlen >= quads.length) {
2191-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2197+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
21922198
}
21932199
quads[qlen++] = currQuad;
21942200
}
@@ -2242,7 +2248,7 @@ protected String _parseAposName() throws IOException
22422248
// Ok, we'll need room for first byte right away
22432249
if (currQuadBytes >= 4) {
22442250
if (qlen >= quads.length) {
2245-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2251+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
22462252
}
22472253
quads[qlen++] = currQuad;
22482254
currQuad = 0;
@@ -2258,7 +2264,7 @@ protected String _parseAposName() throws IOException
22582264
// need room for middle byte?
22592265
if (currQuadBytes >= 4) {
22602266
if (qlen >= quads.length) {
2261-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2267+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
22622268
}
22632269
quads[qlen++] = currQuad;
22642270
currQuad = 0;
@@ -2277,7 +2283,7 @@ protected String _parseAposName() throws IOException
22772283
currQuad = (currQuad << 8) | ch;
22782284
} else {
22792285
if (qlen >= quads.length) {
2280-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2286+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
22812287
}
22822288
quads[qlen++] = currQuad;
22832289
currQuad = ch;
@@ -2293,7 +2299,7 @@ protected String _parseAposName() throws IOException
22932299

22942300
if (currQuadBytes > 0) {
22952301
if (qlen >= quads.length) {
2296-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2302+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
22972303
}
22982304
quads[qlen++] = _padLastQuad(currQuad, currQuadBytes);
22992305
}
@@ -2358,7 +2364,7 @@ private final String findName(int[] quads, int qlen, int lastQuad, int lastQuadB
23582364
throws JsonParseException, StreamConstraintsException
23592365
{
23602366
if (qlen >= quads.length) {
2361-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2367+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
23622368
}
23632369
quads[qlen++] = _padLastQuad(lastQuad, lastQuadBytes);
23642370
String name = _symbols.findName(quads, qlen);
@@ -2381,7 +2387,8 @@ private final String addName(int[] quads, int qlen, int lastQuadBytes)
23812387
* (as well as error reporting for unescaped control chars)
23822388
*/
23832389
// 4 bytes per quad, except last one maybe less
2384-
int byteLen = (qlen << 2) - 4 + lastQuadBytes;
2390+
final int byteLen = (qlen << 2) - 4 + lastQuadBytes;
2391+
_streamReadConstraints.validateNameLength(byteLen);
23852392

23862393
/* And last one is not correctly aligned (leading zero bytes instead
23872394
* need to shift a bit, instead of trailing). Only need to shift it

src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParserBase.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,8 @@ protected final String _addName(int[] quads, int qlen, int lastQuadBytes)
696696
* (as well as error reporting for unescaped control chars)
697697
*/
698698
// 4 bytes per quad, except last one maybe less
699-
int byteLen = (qlen << 2) - 4 + lastQuadBytes;
699+
final int byteLen = (qlen << 2) - 4 + lastQuadBytes;
700+
_streamReadConstraints.validateNameLength(byteLen);
700701

701702
/* And last one is not correctly aligned (leading zero bytes instead
702703
* need to shift a bit, instead of trailing). Only need to shift it

src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingUtf8JsonParserBase.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.fasterxml.jackson.core.JsonParseException;
44
import com.fasterxml.jackson.core.JsonToken;
5+
import com.fasterxml.jackson.core.exc.StreamConstraintsException;
56
import com.fasterxml.jackson.core.io.CharTypes;
67
import com.fasterxml.jackson.core.io.IOContext;
78
import com.fasterxml.jackson.core.json.JsonReadFeature;
@@ -2096,7 +2097,7 @@ private final JsonToken _parseEscapedName(int qlen, int currQuad, int currQuadBy
20962097
continue;
20972098
}
20982099
if (qlen >= quads.length) {
2099-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2100+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
21002101
}
21012102
quads[qlen++] = currQuad;
21022103
currQuad = ch;
@@ -2129,7 +2130,7 @@ private final JsonToken _parseEscapedName(int qlen, int currQuad, int currQuadBy
21292130
// 7-bit ASCII. Gets pretty messy. If this happens often, may
21302131
// want to use different name canonicalization to avoid these hits.
21312132
if (qlen >= quads.length) {
2132-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2133+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
21332134
}
21342135
if (ch > 127) {
21352136
// Ok, we'll need room for first byte right away
@@ -2169,7 +2170,7 @@ private final JsonToken _parseEscapedName(int qlen, int currQuad, int currQuadBy
21692170

21702171
if (currQuadBytes > 0) {
21712172
if (qlen >= quads.length) {
2172-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2173+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
21732174
}
21742175
quads[qlen++] = _padLastQuad(currQuad, currQuadBytes);
21752176
} else if (qlen == 0) { // rare, but may happen
@@ -2259,7 +2260,7 @@ private JsonToken _finishUnquotedName(int qlen, int currQuad, int currQuadBytes)
22592260
currQuad = (currQuad << 8) | ch;
22602261
} else {
22612262
if (qlen >= quads.length) {
2262-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2263+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
22632264
}
22642265
quads[qlen++] = currQuad;
22652266
currQuad = ch;
@@ -2269,7 +2270,7 @@ private JsonToken _finishUnquotedName(int qlen, int currQuad, int currQuadBytes)
22692270

22702271
if (currQuadBytes > 0) {
22712272
if (qlen >= quads.length) {
2272-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2273+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
22732274
}
22742275
quads[qlen++] = currQuad;
22752276
}
@@ -2319,7 +2320,7 @@ private JsonToken _finishAposName(int qlen, int currQuad, int currQuadBytes)
23192320
// Ok, we'll need room for first byte right away
23202321
if (currQuadBytes >= 4) {
23212322
if (qlen >= quads.length) {
2322-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2323+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
23232324
}
23242325
quads[qlen++] = currQuad;
23252326
currQuad = 0;
@@ -2335,7 +2336,7 @@ private JsonToken _finishAposName(int qlen, int currQuad, int currQuadBytes)
23352336
// need room for middle byte?
23362337
if (currQuadBytes >= 4) {
23372338
if (qlen >= quads.length) {
2338-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2339+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
23392340
}
23402341
quads[qlen++] = currQuad;
23412342
currQuad = 0;
@@ -2354,7 +2355,7 @@ private JsonToken _finishAposName(int qlen, int currQuad, int currQuadBytes)
23542355
currQuad = (currQuad << 8) | ch;
23552356
} else {
23562357
if (qlen >= quads.length) {
2357-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2358+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
23582359
}
23592360
quads[qlen++] = currQuad;
23602361
currQuad = ch;
@@ -2364,7 +2365,7 @@ private JsonToken _finishAposName(int qlen, int currQuad, int currQuadBytes)
23642365

23652366
if (currQuadBytes > 0) {
23662367
if (qlen >= quads.length) {
2367-
_quadBuffer = quads = growArrayBy(quads, quads.length);
2368+
_quadBuffer = quads = growArrayWithNameLenCheck(quads, quads.length);
23682369
}
23692370
quads[qlen++] = _padLastQuad(currQuad, currQuadBytes);
23702371
} else if (qlen == 0) { // rare case but possible
@@ -2386,7 +2387,7 @@ protected final JsonToken _finishFieldWithEscape() throws IOException
23862387
return JsonToken.NOT_AVAILABLE;
23872388
}
23882389
if (_quadLength >= _quadBuffer.length) {
2389-
_quadBuffer = growArrayBy(_quadBuffer, 32);
2390+
_quadBuffer = growArrayWithNameLenCheck(_quadBuffer, 32);
23902391
}
23912392
int currQuad = _pending32;
23922393
int currQuadBytes = _pendingBytes;
@@ -2429,6 +2430,12 @@ protected final JsonToken _finishFieldWithEscape() throws IOException
24292430
return _parseEscapedName(_quadLength, currQuad, currQuadBytes);
24302431
}
24312432

2433+
private int[] growArrayWithNameLenCheck(int[] arr, int more) throws StreamConstraintsException {
2434+
// the following check will fail if the array is already bigger than is allowed for names
2435+
_streamReadConstraints.validateNameLength(arr.length << 2);
2436+
return growArrayBy(_quadBuffer, more);
2437+
}
2438+
24322439
private int _decodeSplitEscaped(int value, int bytesRead) throws IOException
24332440
{
24342441
if (_inputPtr >= _inputEnd) {

src/main/java/com/fasterxml/jackson/core/sym/CharsToNameCanonicalizer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ public String findSymbol(char[] buffer, int start, int len, int h) throws IOExce
499499
if (len < 1) { // empty Strings are simplest to handle up front
500500
return "";
501501
}
502+
_streamReadConstraints.validateNameLength(len);
502503
if (!_canonicalize) { // [JACKSON-259]
503504
return new String(buffer, start, len);
504505
}

0 commit comments

Comments
 (0)