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
 }