report an error instead of abort() while parsing an input strings with too deep nested objects/arrays when JSON_USE_EXCEPTION=0 (#1710)
diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp
index 164d41d..2f901f5 100644
--- a/src/lib_json/json_reader.cpp
+++ b/src/lib_json/json_reader.cpp
@@ -1048,10 +1048,19 @@
}
bool OurReader::readValue() {
- // To preserve the old behaviour we cast size_t to int.
- if (nodes_.size() > features_.stackLimit_)
- throwRuntimeError("Exceeded stackLimit in readValue().");
Token token;
+ if (nodes_.size() > features_.stackLimit_) {
+#if JSON_USE_EXCEPTION
+ throwRuntimeError("Exceeded stackLimit in readValue().");
+#else
+ // throwRuntimeError aborts. Don't abort here.
+ token.start_ = current_;
+ token.end_ = current_;
+ token.type_ = tokenError;
+ return addError(
+ "Exceeded stackLimit for nested object and/or array values.", token);
+#endif
+ }
readTokenSkippingComments(token);
bool successful = true;
diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp
index 0d1c330..2e106bc 100644
--- a/src/test_lib_json/main.cpp
+++ b/src/test_lib_json/main.cpp
@@ -467,6 +467,7 @@
JSONTEST_ASSERT_EQUAL(Json::Value(17), got);
JSONTEST_ASSERT_EQUAL(false, array1_.removeIndex(2, &got)); // gone now
}
+
JSONTEST_FIXTURE_LOCAL(ValueTest, resizeArray) {
Json::Value array;
{
@@ -3550,10 +3551,10 @@
}
JSONTEST_FIXTURE_LOCAL(CharReaderTest, parseWithStackLimit) {
-#if JSON_USE_EXCEPTION
-
Json::CharReaderBuilder b;
Json::Value root;
+
+#if JSON_USE_EXCEPTION
char const doc[] = R"({ "property" : "value" })";
{
b.settings_["stackLimit"] = 2;
@@ -3581,7 +3582,36 @@
JSONTEST_ASSERT_THROWS(reader->parse(
nested.data(), nested.data() + nested.size(), &root, &errs));
}
-
+#else
+ b.settings_["stackLimit"] = 10;
+ CharReaderPtr reader(b.newCharReader());
+ {
+ Json::String nested(16, '[');
+ Json::String errs;
+ JSONTEST_ASSERT(!reader->parse(nested.data(), nested.data() + nested.size(),
+ &root, &errs));
+ JSONTEST_ASSERT(
+ errs ==
+ "* Line 1, Column 11\n"
+ " Exceeded stackLimit for nested object and/or array values.\n");
+ }
+ {
+ // even if there are mixed object/array nestings
+ char const mixedNested[] = R"({"property":[[[[[[[[[[[]]]]]]]]]]]})";
+ Json::String errs;
+ JSONTEST_ASSERT(!reader->parse(
+ mixedNested, mixedNested + std::strlen(mixedNested), &root, &errs));
+ JSONTEST_ASSERT(
+ errs ==
+ "* Line 1, Column 22\n"
+ " Exceeded stackLimit for nested object and/or array values.\n");
+ }
+ { // should succeed: test on the limit
+ Json::String onLimit = Json::String(10, '[') + Json::String(10, ']');
+ Json::String errs;
+ JSONTEST_ASSERT(reader->parse(
+ onLimit.data(), onLimit.data() + onLimit.size(), &root, &errs));
+ }
#endif // JSON_USE_EXCEPTION
}