From 2f85ea3a305f7766cbc89e7ebc4be6b30682197a Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 9 Aug 2022 10:19:40 +0100 Subject: [PATCH] Protect against deeply nested maps Update BasicJsonParser to fix the deeply nested map protection logic. Fixes gh-32029 --- .../org/springframework/boot/json/BasicJsonParser.java | 2 +- .../boot/json/AbstractJsonParserTests.java | 8 ++++++++ .../springframework/boot/json/YamlJsonParserTests.java | 5 +++++ .../springframework/boot/json/deeply-nested-map-json.txt | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/json/deeply-nested-map-json.txt diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java index da029cdce436..dad9038123b4 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java @@ -67,7 +67,7 @@ private Object parseInternal(int nesting, String json) { return parseListInternal(nesting + 1, json); } if (json.startsWith("{")) { - return parseMapInternal(nesting, json); + return parseMapInternal(nesting + 1, json); } if (json.startsWith("\"")) { return trimTrailingCharacter(trimLeadingCharacter(json, '"'), '"'); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/AbstractJsonParserTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/AbstractJsonParserTests.java index 2ef4b49c57c6..2d1a234de444 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/AbstractJsonParserTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/AbstractJsonParserTests.java @@ -205,4 +205,12 @@ void largeMalformed() throws IOException { assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input)); } + @Test // gh-32029 + void deeplyNestedMap() throws IOException { + String input = StreamUtils.copyToString( + AbstractJsonParserTests.class.getResourceAsStream("deeply-nested-map-json.txt"), + StandardCharsets.UTF_8); + assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input)); + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/YamlJsonParserTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/YamlJsonParserTests.java index d51b3e51c445..9ce50259933b 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/YamlJsonParserTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/YamlJsonParserTests.java @@ -66,4 +66,9 @@ void listWithRepeatedOpenArray() throws IOException { void largeMalformed() throws IOException { } + @Override + @Disabled("SnakeYaml does not protect against deeply nested JSON") + void deeplyNestedMap() throws IOException { + } + } diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/json/deeply-nested-map-json.txt b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/json/deeply-nested-map-json.txt new file mode 100644 index 000000000000..39b2bfa8a4b9 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/json/deeply-nested-map-json.txt @@ -0,0 +1 @@ +[{":{"":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{"��{":{":{":{":{":{":[{":{"":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{"��{":{":{":{":{":{":[{":{"":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{"��{":{":{":{":{":{":[{":{"":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{"��{":{":{":{":{":{":[{":{"":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{"��{":{":{":{":{":{":[{":{"":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{"��{":{":{":{":{":{":[{":{"":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{"��{":{":{":{":{":{":[{":{"":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{":{"�� \ No newline at end of file