44
55package play .api .libs .json
66
7+ import com .fasterxml .jackson .core .StreamReadConstraints
8+
79import play .api .libs .json .JsonConfig .defaultMaxPlain
810import play .api .libs .json .JsonConfig .defaultMinPlain
911import play .api .libs .json .JsonConfig .defaultDigitsLimit
@@ -103,6 +105,7 @@ private final case class DecimalSerializerSettingsImpl(
103105sealed trait JsonConfig {
104106 def bigDecimalParseConfig : BigDecimalParseConfig
105107 def bigDecimalSerializerConfig : BigDecimalSerializerConfig
108+ def streamReadConstraints : StreamReadConstraints
106109}
107110
108111object JsonConfig {
@@ -168,6 +171,17 @@ object JsonConfig {
168171 */
169172 val maxPlainProperty : String = " play.json.serializer.maxPlain"
170173
174+ /**
175+ * The system property to override the max nesting depth for JSON parsing.
176+ */
177+ val maxNestingDepth : String = " play.json.parser.maxNestingDepth"
178+
179+ /**
180+ * The system property to override the max string length for JSON parsing.
181+ * This is used to limit the length of individual strings in JSON documents.
182+ */
183+ val maxStringLength : String = " play.json.parser.maxStringLength"
184+
171185 /**
172186 * The system property to override whether zero decimals (e.g. .0 or .00) are written by default. These are dropped by default.
173187 */
@@ -183,15 +197,30 @@ object JsonConfig {
183197
184198 private [json] def loadMaxPlain : BigDecimal = prop(maxPlainProperty, defaultMaxPlain)(BigDecimal .exact)
185199
200+ private [json] def loadMaxNestingDepth : Int =
201+ prop(maxNestingDepth, StreamReadConstraints .DEFAULT_MAX_DEPTH )(Integer .parseInt)
202+
203+ private [json] def loadMaxStringLength : Int =
204+ prop(maxStringLength, StreamReadConstraints .DEFAULT_MAX_STRING_LEN )(Integer .parseInt)
205+
186206 private [json] def loadPreserveZeroDecimal : Boolean =
187207 prop(preserveZeroDecimalProperty, defaultPreserveZeroDecimal)(_.toBoolean)
188208
209+ private [json] val defaultStreamReadConstraints : StreamReadConstraints =
210+ StreamReadConstraints
211+ .builder()
212+ .maxNestingDepth(loadMaxNestingDepth)
213+ .maxStringLength(loadMaxStringLength)
214+ .maxNumberLength(Int .MaxValue ) // play-json has its own support for limiting number length
215+ .build()
216+
189217 // Default settings, which can be controlled with system properties.
190218 // To override, call JacksonJson.setConfig()
191219 val settings : JsonConfig =
192220 JsonConfig (
193221 BigDecimalParseConfig (loadMathContext, loadScaleLimit, loadDigitsLimit),
194- BigDecimalSerializerConfig (loadMinPlain, loadMaxPlain, loadPreserveZeroDecimal)
222+ BigDecimalSerializerConfig (loadMinPlain, loadMaxPlain, loadPreserveZeroDecimal),
223+ defaultStreamReadConstraints
195224 )
196225
197226 def apply (): JsonConfig = apply(BigDecimalParseConfig (), BigDecimalSerializerConfig ())
@@ -200,7 +229,14 @@ object JsonConfig {
200229 bigDecimalParseConfig : BigDecimalParseConfig ,
201230 bigDecimalSerializerConfig : BigDecimalSerializerConfig
202231 ): JsonConfig =
203- JsonConfigImpl (bigDecimalParseConfig, bigDecimalSerializerConfig)
232+ JsonConfigImpl (bigDecimalParseConfig, bigDecimalSerializerConfig, defaultStreamReadConstraints)
233+
234+ def apply (
235+ bigDecimalParseConfig : BigDecimalParseConfig ,
236+ bigDecimalSerializerConfig : BigDecimalSerializerConfig ,
237+ streamReadConstraints : StreamReadConstraints
238+ ): JsonConfig =
239+ JsonConfigImpl (bigDecimalParseConfig, bigDecimalSerializerConfig, streamReadConstraints)
204240
205241 private [json] def parseMathContext (key : String ): MathContext = sys.props.get(key).map(_.toLowerCase) match {
206242 case Some (" decimal128" ) => MathContext .DECIMAL128
@@ -220,7 +256,8 @@ object JsonConfig {
220256
221257private final case class JsonConfigImpl (
222258 bigDecimalParseConfig : BigDecimalParseConfig ,
223- bigDecimalSerializerConfig : BigDecimalSerializerConfig
259+ bigDecimalSerializerConfig : BigDecimalSerializerConfig ,
260+ streamReadConstraints : StreamReadConstraints
224261) extends JsonConfig
225262
226263@ deprecated(" Use BigDecimalParseConfig instead" , " 2.9.4" )
@@ -241,7 +278,8 @@ final case class BigDecimalSerializerSettings(
241278@ deprecated(" Use JsonConfig instead" , " 2.9.4" )
242279final case class JsonParserSettings (
243280 bigDecimalParseSettings : BigDecimalParseSettings ,
244- bigDecimalSerializerSettings : BigDecimalSerializerSettings
281+ bigDecimalSerializerSettings : BigDecimalSerializerSettings ,
282+ streamReadConstraints : StreamReadConstraints = JsonConfig .defaultStreamReadConstraints
245283) extends JsonConfig {
246284 override def bigDecimalParseConfig : BigDecimalParseConfig = bigDecimalParseSettings
247285
0 commit comments