Skip to content

Commit 595960a

Browse files
committed
Start work on #1046, add configurability
1 parent 8093f43 commit 595960a

File tree

2 files changed

+93
-17
lines changed

2 files changed

+93
-17
lines changed

src/main/java/com/fasterxml/jackson/core/StreamReadConstraints.java

+93-11
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
* </li>
2121
* <li>Maximum Nesting depth: default 1000 (see {@link #DEFAULT_MAX_DEPTH})
2222
* </li>
23+
* <li>Maximum Document length: default {@code unlimited} (coded as {@code -1},
24+
* (see {@link #DEFAULT_MAX_DOC_LEN})
25+
* </li>
2326
* </ul>
2427
*
2528
* @since 2.15
@@ -35,7 +38,13 @@ public class StreamReadConstraints
3538
public static final int DEFAULT_MAX_DEPTH = 1000;
3639

3740
/**
38-
* Default setting for maximum number length: see {@link Builder#maxNumberLength(int)} for details.
41+
* Default setting for maximum document length:
42+
* see {@link Builder#maxDocumentLength} for details.
43+
*/
44+
public static final long DEFAULT_MAX_DOC_LEN = -1L;
45+
46+
/**
47+
* @since 2.16
3948
*/
4049
public static final int DEFAULT_MAX_NUM_LEN = 1000;
4150

@@ -64,13 +73,16 @@ public class StreamReadConstraints
6473
private static final int MAX_BIGINT_SCALE_MAGNITUDE = 100_000;
6574

6675
protected final int _maxNestingDepth;
76+
protected final long _maxDocLen;
77+
6778
protected final int _maxNumLen;
6879
protected final int _maxStringLen;
6980
protected final int _maxNameLen;
7081

7182
private static StreamReadConstraints DEFAULT =
72-
new StreamReadConstraints(DEFAULT_MAX_DEPTH, DEFAULT_MAX_NUM_LEN,
73-
DEFAULT_MAX_STRING_LEN, DEFAULT_MAX_NAME_LEN);
83+
new StreamReadConstraints(DEFAULT_MAX_DEPTH,
84+
DEFAULT_MAX_DOC_LEN,
85+
DEFAULT_MAX_NUM_LEN, DEFAULT_MAX_STRING_LEN, DEFAULT_MAX_NAME_LEN);
7486

7587
/**
7688
* Override the default StreamReadConstraints. These defaults are only used when {@link JsonFactory}
@@ -91,13 +103,15 @@ public class StreamReadConstraints
91103
*/
92104
public static void overrideDefaultStreamReadConstraints(final StreamReadConstraints streamReadConstraints) {
93105
if (streamReadConstraints == null) {
94-
DEFAULT = new StreamReadConstraints(DEFAULT_MAX_DEPTH, DEFAULT_MAX_NUM_LEN, DEFAULT_MAX_STRING_LEN);
106+
DEFAULT = new StreamReadConstraints(DEFAULT_MAX_DEPTH, DEFAULT_MAX_DOC_LEN,
107+
DEFAULT_MAX_NUM_LEN, DEFAULT_MAX_STRING_LEN);
95108
} else {
96109
DEFAULT = streamReadConstraints;
97110
}
98111
}
99112

100113
public static final class Builder {
114+
private long maxDocLen;
101115
private int maxNestingDepth;
102116
private int maxNumLen;
103117
private int maxStringLen;
@@ -120,6 +134,28 @@ public Builder maxNestingDepth(final int maxNestingDepth) {
120134
return this;
121135
}
122136

137+
/**
138+
* Sets the maximum allowed document length (for positive values over 0) or
139+
* indicate that any length is acceptable ({@code 0} or negative number).
140+
* The length is in input units of the input source, that is, in
141+
* {@code byte}s or {@code char}s.
142+
*
143+
* @param maxDocLen the maximum allowed document if positive number above 0; otherwise
144+
* ({@code 0} or negative number) means "unlimited".
145+
*
146+
* @return this builder
147+
*
148+
* @since 2.16
149+
*/
150+
public Builder maxDocumentLength(long maxDocLen) {
151+
// Negative values and 0 mean "unlimited", mark with -1L
152+
if (maxDocLen <= 0L) {
153+
maxDocLen = -1L;
154+
}
155+
this.maxDocLen = maxDocLen;
156+
return this;
157+
}
158+
123159
/**
124160
* Sets the maximum number length (in chars or bytes, depending on input context).
125161
* The default is 1000.
@@ -184,25 +220,30 @@ public Builder maxNameLength(final int maxNameLen) {
184220
}
185221

186222
Builder() {
187-
this(DEFAULT_MAX_DEPTH, DEFAULT_MAX_NUM_LEN, DEFAULT_MAX_STRING_LEN, DEFAULT_MAX_NAME_LEN);
223+
this(DEFAULT_MAX_DEPTH, DEFAULT_MAX_DOC_LEN,
224+
DEFAULT_MAX_NUM_LEN, DEFAULT_MAX_STRING_LEN, DEFAULT_MAX_NAME_LEN);
188225
}
189226

190-
Builder(final int maxNestingDepth, final int maxNumLen, final int maxStringLen, final int maxNameLen) {
227+
Builder(final int maxNestingDepth, final long maxDocLen,
228+
final int maxNumLen, final int maxStringLen, final int maxNameLen) {
191229
this.maxNestingDepth = maxNestingDepth;
230+
this.maxDocLen = maxDocLen;
192231
this.maxNumLen = maxNumLen;
193232
this.maxStringLen = maxStringLen;
194233
this.maxNameLen = maxNameLen;
195234
}
196235

197236
Builder(StreamReadConstraints src) {
198237
maxNestingDepth = src._maxNestingDepth;
238+
maxDocLen = src._maxDocLen;
199239
maxNumLen = src._maxNumLen;
200240
maxStringLen = src._maxStringLen;
201241
maxNameLen = src._maxNameLen;
202242
}
203243

204244
public StreamReadConstraints build() {
205-
return new StreamReadConstraints(maxNestingDepth, maxNumLen, maxStringLen, maxNameLen);
245+
return new StreamReadConstraints(maxNestingDepth, maxDocLen,
246+
maxNumLen, maxStringLen, maxNameLen);
206247
}
207248
}
208249

@@ -213,13 +254,19 @@ public StreamReadConstraints build() {
213254
*/
214255

215256
@Deprecated // since 2.16
216-
protected StreamReadConstraints(final int maxNestingDepth, final int maxNumLen, final int maxStringLen) {
217-
this(maxNestingDepth, maxNumLen, maxStringLen, DEFAULT_MAX_NAME_LEN);
257+
protected StreamReadConstraints(final int maxNestingDepth, final long maxDocLen,
258+
final int maxNumLen, final int maxStringLen) {
259+
this(maxNestingDepth, DEFAULT_MAX_DOC_LEN,
260+
maxNumLen, maxStringLen, DEFAULT_MAX_NAME_LEN);
218261
}
219262

220-
protected StreamReadConstraints(final int maxNestingDepth, final int maxNumLen,
221-
final int maxStringLen, final int maxNameLen) {
263+
/**
264+
* @since 2.16
265+
*/
266+
protected StreamReadConstraints(final int maxNestingDepth, final long maxDocLen,
267+
final int maxNumLen, final int maxStringLen, final int maxNameLen) {
222268
_maxNestingDepth = maxNestingDepth;
269+
_maxDocLen = maxDocLen;
223270
_maxNumLen = maxNumLen;
224271
_maxStringLen = maxStringLen;
225272
_maxNameLen = maxNameLen;
@@ -261,6 +308,16 @@ public int getMaxNestingDepth() {
261308
return _maxNestingDepth;
262309
}
263310

311+
/**
312+
* Accessor for maximum document length.
313+
* see {@link Builder#maxDocumentLength(long)} for details.
314+
*
315+
* @return Maximum allowed depth
316+
*/
317+
public long getMaxDocumentLength() {
318+
return _maxDocLen;
319+
}
320+
264321
/**
265322
* Accessor for maximum length of numbers to decode.
266323
* see {@link Builder#maxNumberLength(int)} for details.
@@ -318,6 +375,31 @@ public void validateNestingDepth(int depth) throws StreamConstraintsException
318375
}
319376
}
320377

378+
/**
379+
* Convenience method that can be used to verify that the
380+
* document length does not exceed the maximum specified by this
381+
* constraints object (if any): if it does, a
382+
* {@link StreamConstraintsException}
383+
* is thrown.
384+
*
385+
* @param len Current length of processed document content
386+
*
387+
* @throws StreamConstraintsException If length exceeds maximum
388+
*
389+
* @since 2.16
390+
*/
391+
public void validateDocumentLength(long len) throws StreamConstraintsException
392+
{
393+
if ((len > _maxDocLen)
394+
// Note: -1L used as marker for "unlimited"
395+
&& (_maxDocLen > 0L)) {
396+
throw _constructException(
397+
"Document nesting depth (%d) exceeds the maximum allowed (%d, from %s)",
398+
len, _maxDocLen,
399+
_constrainRef("getMaxDocumentLength"));
400+
}
401+
}
402+
321403
/*
322404
/**********************************************************************
323405
/* Convenience methods for validation, token lengths

src/test/java/com/fasterxml/jackson/core/io/BufferRecyclerPoolTest.java

-6
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,5 @@ private static class NopOutputStream extends OutputStream {
7474

7575
@Override
7676
public void write(byte[] b, int offset, int len) throws IOException { size += len; }
77-
78-
public NopOutputStream reset() {
79-
size = 0;
80-
return this;
81-
}
82-
public int size() { return size; }
8377
}
8478
}

0 commit comments

Comments
 (0)