Skip to content

Commit b594a32

Browse files
authored
Merge pull request #1070 from dong0713/fix/xml-unescape-whitespace-control-chars
Fix XML.unescape rejecting valid whitespace numeric character references
2 parents 1795e8c + 94854a1 commit b594a32

2 files changed

Lines changed: 45 additions & 2 deletions

File tree

‎src/main/java/org/json/XML.java‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,14 @@ static boolean mustEscape(int cp) {
172172
&& cp != 0xA
173173
&& cp != 0xD
174174
) || !(
175-
// valid the range of acceptable characters that aren't control
176-
(cp >= 0x20 && cp <= 0xD7FF)
175+
// Valid character range per W3C XML 1.0 spec:
176+
// #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
177+
// Previously omitted #x9/#xA/#xD, causing unescape("&#10;") etc.
178+
// to reject valid LF/TAB/CR as illegal (see #1059)
179+
cp == 0x9
180+
|| cp == 0xA
181+
|| cp == 0xD
182+
|| (cp >= 0x20 && cp <= 0xD7FF)
177183
|| (cp >= 0xE000 && cp <= 0xFFFD)
178184
|| (cp >= 0x10000 && cp <= 0x10FFFF)
179185
)

‎src/test/java/org/json/junit/XMLTest.java‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,43 @@ public void testValidUppercaseHexEntity() {
15371537
assertEquals("A", jsonObject.getString("a"));
15381538
}
15391539

1540+
/**
1541+
* Tests that valid XML numeric character references for whitespace
1542+
* control characters (TAB, LF, CR) are correctly unescaped. These
1543+
* codepoints are explicitly allowed by the XML 1.0 spec
1544+
* (https://www.w3.org/TR/REC-xml/#charsets) but were previously rejected
1545+
* as invalid. See issue #1059.
1546+
*/
1547+
@Test
1548+
public void testValidWhitespaceNumericEntityUnescape() {
1549+
// decimal references for the three allowed control characters
1550+
assertEquals("\t", XML.unescape("&#9;"));
1551+
assertEquals("\n", XML.unescape("&#10;"));
1552+
assertEquals("\r", XML.unescape("&#13;"));
1553+
// hex references for the same codepoints
1554+
assertEquals("\t", XML.unescape("&#x9;"));
1555+
assertEquals("\n", XML.unescape("&#xA;"));
1556+
assertEquals("\r", XML.unescape("&#xD;"));
1557+
}
1558+
1559+
/**
1560+
* Tests that {@code XML.toJSONObject} accepts numeric character references
1561+
* for the XML-allowed control characters (TAB, LF, CR) without throwing.
1562+
* Regression test for #1059, where {@code XML.toJSONObject("<a>&#10;</a>")}
1563+
* threw JSONException in versions after 20251224.
1564+
*/
1565+
@Test
1566+
public void testValidWhitespaceNumericEntityToJSONObject() {
1567+
// LF reference should round-trip through toJSONObject without throwing
1568+
JSONObject jsonObject = XML.toJSONObject("<a>&#10;</a>");
1569+
// the value is the LF character (possibly trimmed by the JSON path,
1570+
// but the call must not throw)
1571+
assertTrue(jsonObject.has("a"));
1572+
// TAB and CR references also accepted
1573+
XML.toJSONObject("<a>&#9;</a>");
1574+
XML.toJSONObject("<a>&#13;</a>");
1575+
}
1576+
15401577
}
15411578

15421579

0 commit comments

Comments
 (0)