diff --git a/src/main/java/org/json/XML.java b/src/main/java/org/json/XML.java index 7e4b0bb0c..becf0e6e1 100644 --- a/src/main/java/org/json/XML.java +++ b/src/main/java/org/json/XML.java @@ -158,7 +158,7 @@ public static String escape(String string) { * @param cp code point to test * @return true if the code point is not valid for an XML */ - private static boolean mustEscape(int cp) { + static boolean mustEscape(int cp) { /* Valid range from https://www.w3.org/TR/REC-xml/#charsets * * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] diff --git a/src/main/java/org/json/XMLTokener.java b/src/main/java/org/json/XMLTokener.java index dad2e2897..dc90f84d4 100644 --- a/src/main/java/org/json/XMLTokener.java +++ b/src/main/java/org/json/XMLTokener.java @@ -167,6 +167,9 @@ static String unescapeEntity(String e) throws JSONException { int cp = (e.charAt(1) == 'x' || e.charAt(1) == 'X') ? parseHexEntity(e) : parseDecimalEntity(e); + if (XML.mustEscape(cp)) { + throw new JSONException("Invalid numeric character reference: &#" + e.substring(1) + ";"); + } return new String(new int[] {cp}, 0, 1); } Character knownEntity = entity.get(e); diff --git a/src/test/java/org/json/junit/XMLTest.java b/src/test/java/org/json/junit/XMLTest.java index 25b0a0e42..589536fd2 100644 --- a/src/test/java/org/json/junit/XMLTest.java +++ b/src/test/java/org/json/junit/XMLTest.java @@ -1468,6 +1468,42 @@ public void testInvalidHexEntityThrowsJSONException() { XML.toJSONObject(xmlStr); } + /** + * Tests that out-of-range hex entities throw JSONException rather than an uncaught runtime exception. + */ + @Test(expected = JSONException.class) + public void testOutOfRangeHexEntityThrowsJSONException() { + String xmlStr = ""; + XML.toJSONObject(xmlStr); + } + + /** + * Tests that out-of-range decimal entities throw JSONException rather than an uncaught runtime exception. + */ + @Test(expected = JSONException.class) + public void testOutOfRangeDecimalEntityThrowsJSONException() { + String xmlStr = ""; + XML.toJSONObject(xmlStr); + } + + /** + * Tests that surrogate code point entities throw JSONException. + */ + @Test(expected = JSONException.class) + public void testSurrogateHexEntityThrowsJSONException() { + String xmlStr = ""; + XML.toJSONObject(xmlStr); + } + + /** + * Tests that out-of-range numeric entities in attribute values throw JSONException. + */ + @Test(expected = JSONException.class) + public void testOutOfRangeHexEntityInAttributeThrowsJSONException() { + String xmlStr = ""; + XML.toJSONObject(xmlStr); + } + /** * Tests that valid decimal numeric entity A works correctly. * Should decode to character 'A'.