diff --git a/data/src/main/java/com/google/maps/android/data/parser/geojson/GeoJsonParser.kt b/data/src/main/java/com/google/maps/android/data/parser/geojson/GeoJsonParser.kt index 6f672aaa7..c0e9f4392 100644 --- a/data/src/main/java/com/google/maps/android/data/parser/geojson/GeoJsonParser.kt +++ b/data/src/main/java/com/google/maps/android/data/parser/geojson/GeoJsonParser.kt @@ -15,6 +15,7 @@ */ package com.google.maps.android.data.parser.geojson +import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonNull @@ -29,6 +30,11 @@ public class GeoJsonParser @JvmOverloads public constructor( private val maxInputSize: Long = DEFAULT_MAX_INPUT_SIZE, private val maxStructuralDepth: Int = DEFAULT_MAX_STRUCTURAL_DEPTH, ) { + // kotlinx.serialization enforces its own nesting limit (400 by default since 1.12.0). Align it + // with [maxStructuralDepth] so [checkStructuralDepth] remains the single bound on nesting. + @OptIn(ExperimentalSerializationApi::class) + private val jsonParser = Json { maxNestingDepth = maxStructuralDepth } + public fun parse(inputStream: InputStream): GeoJsonObject? { // Bound the untrusted input *before* materialising it. [Json.parseToJsonElement] reads the // whole document into an in-memory tree, so without these guards a hostile document can @@ -36,7 +42,7 @@ public class GeoJsonParser @JvmOverloads public constructor( // before the [MAX_GEOMETRY_DEPTH] check — which runs on the already-built tree — can act. val json = inputStream.readTextBounded(maxInputSize) checkStructuralDepth(json, maxStructuralDepth) - val jsonElement = Json.parseToJsonElement(json) + val jsonElement = jsonParser.parseToJsonElement(json) return when (jsonElement.jsonObject["type"]?.jsonPrimitive?.content) { "FeatureCollection" -> { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1d37314de..01560bd45 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ appcompat = "1.8.0" core-ktx = "1.19.1" kotlin = "2.4.21" kotlinx-coroutines = "1.11.0" -kotlinx-serialization = "1.11.0" +kotlinx-serialization = "1.12.0" ktor = "3.6.0" lifecycle-extensions = "2.2.0" lifecycle-viewmodel-ktx = "2.11.0" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e7bb9fd6..91c4fc64a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500