Skip to content

Commit 47de8b0

Browse files
juntae6942bclozel
authored andcommitted
Fix HtmlUtils unescape for supplementary chars
See gh-35477 Signed-off-by: potato <[email protected]>
1 parent 3b6be3d commit 47de8b0

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

spring-web/src/main/java/org/springframework/web/util/HtmlCharacterEntityDecoder.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,10 @@ private boolean processNumberedReference() {
124124
int value = (!isHexNumberedReference ?
125125
Integer.parseInt(getReferenceSubstring(2)) :
126126
Integer.parseInt(getReferenceSubstring(3), 16));
127-
this.decodedMessage.append((char) value);
127+
if (value > Character.MAX_CODE_POINT) {
128+
return false;
129+
}
130+
this.decodedMessage.appendCodePoint(value);
128131
return true;
129132
}
130133
catch (NumberFormatException ex) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.springframework.web.util;
2+
3+
import org.junit.jupiter.api.DisplayName;
4+
import org.junit.jupiter.api.Test;
5+
6+
import static org.junit.jupiter.api.Assertions.assertEquals;
7+
8+
class HtmlCharacterEntityDecoderTest {
9+
10+
@Test
11+
@DisplayName("Should correctly unescape Unicode supplementary characters")
12+
void unescapeHandlesSupplementaryCharactersCorrectly() {
13+
// Arrange: Prepare test cases with the 'grinning face' emoji (😀, U+1F600).
14+
String expectedCharacter = "😀";
15+
String decimalEntity = "&#128512;";
16+
String hexEntity = "&#x1F600;";
17+
18+
// Act: Call the HtmlUtils.htmlUnescape method to get the actual results.
19+
String actualResultFromDecimal = HtmlUtils.htmlUnescape(decimalEntity);
20+
String actualResultFromHex = HtmlUtils.htmlUnescape(hexEntity);
21+
22+
// Assert: Verify that the actual results match the expected character.
23+
assertEquals(expectedCharacter, actualResultFromDecimal, "Decimal entity was not converted correctly.");
24+
assertEquals(expectedCharacter, actualResultFromHex, "Hexadecimal entity was not converted correctly.");
25+
}
26+
27+
@Test
28+
@DisplayName("Should correctly unescape basic and named HTML entities")
29+
void unescapeHandlesBasicEntities() {
30+
// Arrange
31+
String input = "&lt;p&gt;Tom &amp; Jerry&#39;s &quot;Show&quot;&lt;/p&gt;";
32+
String expectedOutput = "<p>Tom & Jerry's \"Show\"</p>";
33+
34+
// Act
35+
String actualOutput = HtmlUtils.htmlUnescape(input);
36+
37+
// Assert
38+
assertEquals(expectedOutput, actualOutput, "Basic HTML entities were not unescaped correctly.");
39+
}
40+
41+
}
42+

0 commit comments

Comments
 (0)