From fdaeb486edac31c5dd4ae24259ded6b1b4831270 Mon Sep 17 00:00:00 2001 From: marilynel Date: Sun, 13 Jul 2025 12:41:17 -0800 Subject: [PATCH 1/2] fixed some strict mode issues 980 --- src/main/java/org/json/JSONObject.java | 16 ++++++++- src/main/java/org/json/JSONTokener.java | 9 +++++ .../java/org/json/junit/JSONObjectTest.java | 35 +++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/json/JSONObject.java b/src/main/java/org/json/JSONObject.java index b504519..10fed95 100644 --- a/src/main/java/org/json/JSONObject.java +++ b/src/main/java/org/json/JSONObject.java @@ -213,6 +213,7 @@ public class JSONObject { this(); char c; String key; + Object obj; boolean isInitial = x.getPrevious() == 0; @@ -230,7 +231,20 @@ public class JSONObject { } return; default: - key = x.nextSimpleValue(c).toString(); + obj = x.nextSimpleValue(c); + key = obj.toString(); + } + + if (jsonParserConfiguration != null && jsonParserConfiguration.isStrictMode()) { + if(obj instanceof Boolean) { + throw x.syntaxError(String.format("Strict mode error: key '%s' cannot be boolean", key)); + } + if(obj == JSONObject.NULL) { + throw x.syntaxError(String.format("Strict mode error: key '%s' cannot be null", key)); + } + if(obj instanceof Number) { + throw x.syntaxError(String.format("Strict mode error: key '%s' cannot be number", key)); + } } // The key is followed by ':'. diff --git a/src/main/java/org/json/JSONTokener.java b/src/main/java/org/json/JSONTokener.java index a90d51a..ffe12d6 100644 --- a/src/main/java/org/json/JSONTokener.java +++ b/src/main/java/org/json/JSONTokener.java @@ -511,6 +511,15 @@ public class JSONTokener { throw this.syntaxError("Missing value"); } Object obj = JSONObject.stringToValue(string); + // if obj is a boolean, look at string + if (jsonParserConfiguration != null && + jsonParserConfiguration.isStrictMode() && obj instanceof Boolean) { + if (!"true".equals(string) && !"false".equals(string)) { + throw this.syntaxError(String.format("Strict mode error: Value '%s' is not lowercase boolean", obj)); + } + } + + // Strict mode only allows strings with explicit double quotes if (jsonParserConfiguration != null && jsonParserConfiguration.isStrictMode() && diff --git a/src/test/java/org/json/junit/JSONObjectTest.java b/src/test/java/org/json/junit/JSONObjectTest.java index 061f185..50319a8 100644 --- a/src/test/java/org/json/junit/JSONObjectTest.java +++ b/src/test/java/org/json/junit/JSONObjectTest.java @@ -3997,6 +3997,41 @@ public class JSONObjectTest { assertThrows(JSONException.class, () -> { new JSONObject(tokener); }); } + @Test + public void test_strictModeWithMisCasedBooleanValue(){ + JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration().withStrictMode(); + + try{ + JSONObject j1 = new JSONObject("{\"a\":True}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } + try{ + JSONObject j2 = new JSONObject("{\"a\":TRUE}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } + } + + @Test + public void test_strictModeWithInappropriateKey(){ + JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration().withStrictMode(); + + // Parsing the following objects should fail + try{ + JSONObject j3 = new JSONObject("{true : 3}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } + try{ + JSONObject j4 = new JSONObject("{TRUE : 3}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } + try{ + JSONObject j5 = new JSONObject("{1 : 3}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } + + } + + /** * Method to build nested map of max maxDepth * From c91b728386112a88d0d8492ecbb69395067481c1 Mon Sep 17 00:00:00 2001 From: marilynel Date: Sun, 13 Jul 2025 12:52:42 -0800 Subject: [PATCH 2/2] oops forgot null --- src/main/java/org/json/JSONTokener.java | 21 ++++++++++--------- .../java/org/json/junit/JSONObjectTest.java | 6 +++++- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/json/JSONTokener.java b/src/main/java/org/json/JSONTokener.java index ffe12d6..05a6e34 100644 --- a/src/main/java/org/json/JSONTokener.java +++ b/src/main/java/org/json/JSONTokener.java @@ -513,18 +513,19 @@ public class JSONTokener { Object obj = JSONObject.stringToValue(string); // if obj is a boolean, look at string if (jsonParserConfiguration != null && - jsonParserConfiguration.isStrictMode() && obj instanceof Boolean) { - if (!"true".equals(string) && !"false".equals(string)) { + jsonParserConfiguration.isStrictMode()) { + if (obj instanceof Boolean && !"true".equals(string) && !"false".equals(string)) { + // Strict mode only allows lowercase true or false throw this.syntaxError(String.format("Strict mode error: Value '%s' is not lowercase boolean", obj)); } - } - - - // Strict mode only allows strings with explicit double quotes - if (jsonParserConfiguration != null && - jsonParserConfiguration.isStrictMode() && - obj instanceof String) { - throw this.syntaxError(String.format("Strict mode error: Value '%s' is not surrounded by quotes", obj)); + else if (obj == JSONObject.NULL && !"null".equals(string)) { + // Strint mode only allows lowercase null + throw this.syntaxError(String.format("Strict mode error: Value '%s' is not lowercase null", obj)); + } + else if (obj instanceof String) { + // Strict mode only allows strings with explicit double quotes + throw this.syntaxError(String.format("Strict mode error: Value '%s' is not surrounded by quotes", obj)); + } } return obj; } diff --git a/src/test/java/org/json/junit/JSONObjectTest.java b/src/test/java/org/json/junit/JSONObjectTest.java index 50319a8..52a5240 100644 --- a/src/test/java/org/json/junit/JSONObjectTest.java +++ b/src/test/java/org/json/junit/JSONObjectTest.java @@ -3998,7 +3998,7 @@ public class JSONObjectTest { } @Test - public void test_strictModeWithMisCasedBooleanValue(){ + public void test_strictModeWithMisCasedBooleanOrNullValue(){ JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration().withStrictMode(); try{ @@ -4009,6 +4009,10 @@ public class JSONObjectTest { JSONObject j2 = new JSONObject("{\"a\":TRUE}", jsonParserConfiguration); fail("Expected an exception"); } catch (JSONException e) { } + try{ + JSONObject j2 = new JSONObject("{\"a\":nUlL}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } } @Test