From 1df15fc5b5834e234df343c4469c5b6d5d4c8efa Mon Sep 17 00:00:00 2001 From: Dmytro Nosan Date: Mon, 3 Mar 2025 14:03:16 +0200 Subject: [PATCH] Prevent StackOverflowError when serializing Path using JsonValueWriter Prior to this commit, serializing `java.nio.file.Path` caused a StackOverflowError because `Path.iterator()` always returns itself as the first element of the iterator, which results in a StackOverflowError. This commit serializes `java.nio.file.Path` as JSON String. Signed-off-by: Dmytro Nosan --- .../boot/json/JsonValueWriter.java | 7 ++++++- .../boot/json/JsonValueWriterTests.java | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonValueWriter.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonValueWriter.java index dbd8237aebd2..c0270e21738f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonValueWriter.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/JsonValueWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ import java.io.IOException; import java.io.UncheckedIOException; +import java.nio.file.Path; import java.util.ArrayDeque; import java.util.Arrays; import java.util.Deque; @@ -114,6 +115,10 @@ else if (value instanceof WritableJson writableJson) { throw new UncheckedIOException(ex); } } + // https://github.com/spring-projects/spring-boot/issues/44502 + else if (value instanceof Path p) { + writeString(p.toString()); + } else if (value instanceof Iterable iterable) { writeArray(iterable::forEach); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/JsonValueWriterTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/JsonValueWriterTests.java index 94939db8da53..4c4d4314dedd 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/JsonValueWriterTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/JsonValueWriterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.boot.json; +import java.nio.file.Path; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -240,6 +241,18 @@ void endWhenNotStartedThrowsException() { .isThrownBy(() -> valueWriter.end(Series.ARRAY))); } + // https://github.com/spring-projects/spring-boot/issues/44502 + @Test + void writeJavaNioPathWhenSingleElementShouldBeSerializedAsString() { + assertThat(doWrite((valueWriter) -> valueWriter.write(Path.of("overflow")))).isEqualTo(quoted("overflow")); + } + + @Test + void writeJavaNioPathShouldShouldBeSerializedAsString() { + assertThat(doWrite((valueWriter) -> valueWriter.write(Path.of("stack/overflow/error")))) + .isEqualTo(quoted("stack\\/overflow\\/error")); + } + private String write(V value) { return doWrite((valueWriter) -> valueWriter.write(value)); }