From 0b608005f5f680a26f5b8ce5a34b4a4ea559fc3c Mon Sep 17 00:00:00 2001 From: potato <65760583+juntae6942@users.noreply.github.com> Date: Sat, 13 Sep 2025 23:15:49 +0900 Subject: [PATCH 1/3] Fix HtmlUtils unescape for supplementary chars Signed-off-by: potato <65760583+juntae6942@users.noreply.github.com> --- .../web/util/HtmlCharacterEntityDecoder.java | 5 +++- .../util/HtmlCharacterEntityDecoderTest.java | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java diff --git a/spring-web/src/main/java/org/springframework/web/util/HtmlCharacterEntityDecoder.java b/spring-web/src/main/java/org/springframework/web/util/HtmlCharacterEntityDecoder.java index bf6c7952641d..615ff14c571b 100644 --- a/spring-web/src/main/java/org/springframework/web/util/HtmlCharacterEntityDecoder.java +++ b/spring-web/src/main/java/org/springframework/web/util/HtmlCharacterEntityDecoder.java @@ -124,7 +124,10 @@ private boolean processNumberedReference() { int value = (!isHexNumberedReference ? Integer.parseInt(getReferenceSubstring(2)) : Integer.parseInt(getReferenceSubstring(3), 16)); - this.decodedMessage.append((char) value); + if (value > Character.MAX_CODE_POINT) { + return false; + } + this.decodedMessage.appendCodePoint(value); return true; } catch (NumberFormatException ex) { diff --git a/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java b/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java new file mode 100644 index 000000000000..de6b85400ef8 --- /dev/null +++ b/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java @@ -0,0 +1,26 @@ +package org.springframework.web.util; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class HtmlCharacterEntityDecoderTest { + + @Test + @DisplayName("Should correctly unescape Unicode supplementary characters") + void unescapeHandlesSupplementaryCharactersCorrectly() { + // Arrange: Prepare test cases with the 'grinning face' emoji (😀, U+1F600). + String expectedCharacter = "😀"; + String decimalEntity = "😀"; + String hexEntity = "😀"; + + // Act: Call the HtmlUtils.htmlUnescape method to get the actual results. + String actualResultFromDecimal = HtmlUtils.htmlUnescape(decimalEntity); + String actualResultFromHex = HtmlUtils.htmlUnescape(hexEntity); + + // Assert: Verify that the actual results match the expected character. + assertEquals(expectedCharacter, actualResultFromDecimal, "Decimal entity was not converted correctly."); + assertEquals(expectedCharacter, actualResultFromHex, "Hexadecimal entity was not converted correctly."); + } +} \ No newline at end of file From a6efa2aec7418bd3838ab70ade6eace4a194ff4f Mon Sep 17 00:00:00 2001 From: potato <65760583+juntae6942@users.noreply.github.com> Date: Sun, 14 Sep 2025 13:38:46 +0900 Subject: [PATCH 2/3] Test: Add case for basic HTML entities in HtmlUtils Signed-off-by: potato <65760583+juntae6942@users.noreply.github.com> --- .../web/util/HtmlCharacterEntityDecoderTest.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java b/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java index de6b85400ef8..c412d25bf396 100644 --- a/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java +++ b/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java @@ -23,4 +23,18 @@ void unescapeHandlesSupplementaryCharactersCorrectly() { assertEquals(expectedCharacter, actualResultFromDecimal, "Decimal entity was not converted correctly."); assertEquals(expectedCharacter, actualResultFromHex, "Hexadecimal entity was not converted correctly."); } -} \ No newline at end of file + + @Test + @DisplayName("Should correctly unescape basic and named HTML entities") + void unescapeHandlesBasicEntities() { + // Arrange + String input = "<p>Tom & Jerry's "Show"</p>"; + String expectedOutput = "

Tom & Jerry's \"Show\"

"; + + // Act + String actualOutput = HtmlUtils.htmlUnescape(input); + + // Assert + assertEquals(expectedOutput, actualOutput, "Basic HTML entities were not unescaped correctly."); + } +} From 7378478f7f55efe3008976208bc6ba975c126950 Mon Sep 17 00:00:00 2001 From: potato <65760583+juntae6942@users.noreply.github.com> Date: Sun, 14 Sep 2025 14:07:37 +0900 Subject: [PATCH 3/3] Style: Format code to align with project conventions Signed-off-by: potato <65760583+juntae6942@users.noreply.github.com> --- .../web/util/HtmlCharacterEntityDecoderTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java b/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java index c412d25bf396..88355eadade2 100644 --- a/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java +++ b/spring-web/src/test/java/org/springframework/web/util/HtmlCharacterEntityDecoderTest.java @@ -37,4 +37,6 @@ void unescapeHandlesBasicEntities() { // Assert assertEquals(expectedOutput, actualOutput, "Basic HTML entities were not unescaped correctly."); } + } +