diff --git a/CMakeLists.txt b/CMakeLists.txt
index 76619dcbd..4a6b259fa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,6 +23,12 @@ if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
set(FLATBUFFERS_BUILD_TESTS OFF)
endif()
+if(DEFINED FLATBUFFERS_MAX_PARSING_DEPTH)
+ # Override the default recursion depth limit.
+ add_definitions(-DFLATBUFFERS_MAX_PARSING_DEPTH=${FLATBUFFERS_MAX_PARSING_DEPTH})
+ message(STATUS "FLATBUFFERS_MAX_PARSING_DEPTH: ${FLATBUFFERS_MAX_PARSING_DEPTH}")
+endif()
+
set(FlatBuffers_Library_SRCS
include/flatbuffers/code_generators.h
include/flatbuffers/base.h
diff --git a/docs/source/Building.md b/docs/source/Building.md
index c2faddad2..a89671109 100644
--- a/docs/source/Building.md
+++ b/docs/source/Building.md
@@ -80,6 +80,14 @@ target_link_libraries(own_project_target PRIVATE flatbuffers)
When build your project the `flatbuffers` library will be compiled and linked
to a target as part of your project.
+#### Override default depth limit of nested objects
+To override [the depth limit of recursion](@ref flatbuffers_guide_use_cpp),
+add this directive:
+```cmake
+set(FLATBUFFERS_MAX_PARSING_DEPTH 16)
+```
+to `CMakeLists.txt` file before `add_subdirectory(${FLATBUFFERS_SRC_DIR})` line.
+
#### For Google Play apps
For applications on Google Play that integrate this library, usage is tracked.
diff --git a/docs/source/CppUsage.md b/docs/source/CppUsage.md
index 983dc5ae6..fff04a9d9 100644
--- a/docs/source/CppUsage.md
+++ b/docs/source/CppUsage.md
@@ -495,4 +495,13 @@ needed to use unions.
To use scalars, simply wrap them in a struct.
+## Depth limit of nested objects and stack-overflow control
+The parser of Flatbuffers schema or json-files is kind of recursive parser.
+To avoid stack-overflow problem the parser has a built-in limiter of recursion depth.
+Number of nested declarations in a schema or number of nested json-objects is limited.
+By default, this depth limit set to `64`.
+It is possible to override this limit with `FLATBUFFERS_MAX_PARSING_DEPTH` definition.
+This definition can be helpful for testing purposes or embedded applications.
+For details see [build](@ref flatbuffers_guide_building) of CMake-based projects.
+
diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h
index 63446247d..cf5446a2d 100644
--- a/include/flatbuffers/idl.h
+++ b/include/flatbuffers/idl.h
@@ -34,6 +34,12 @@
// This file defines the data types representing a parsed IDL (Interface
// Definition Language) / schema file.
+// Limits maximum depth of nested objects.
+// Prevents stack overflow while parse flatbuffers or json.
+#if !defined(FLATBUFFERS_MAX_PARSING_DEPTH)
+# define FLATBUFFERS_MAX_PARSING_DEPTH 64
+#endif
+
namespace flatbuffers {
// The order of these matters for Is*() functions below.
@@ -745,10 +751,11 @@ class Parser : public ParserState {
bool SupportsVectorOfUnions() const;
Namespace *UniqueNamespace(Namespace *ns);
- enum { kMaxParsingDepth = 64 };
FLATBUFFERS_CHECKED_ERROR RecurseError();
template CheckedError Recurse(F f) {
- if (++recurse_protection_counter >= kMaxParsingDepth) return RecurseError();
+ if (recurse_protection_counter >= (FLATBUFFERS_MAX_PARSING_DEPTH))
+ return RecurseError();
+ recurse_protection_counter++;
auto ce = f();
recurse_protection_counter--;
return ce;
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index 518ef7b82..e686f628f 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -115,8 +115,8 @@ CheckedError Parser::Error(const std::string &msg) {
inline CheckedError NoError() { return CheckedError(false); }
CheckedError Parser::RecurseError() {
- return Error("maximum parsing recursion of " + NumToString(kMaxParsingDepth) +
- " reached");
+ return Error("maximum parsing recursion of " +
+ NumToString(FLATBUFFERS_MAX_PARSING_DEPTH) + " reached");
}
inline std::string OutOfRangeErrorMsg(int64_t val, const std::string &op,
@@ -2254,7 +2254,10 @@ bool Parser::ParseFlexBuffer(const char *source, const char *source_filename,
bool Parser::Parse(const char *source, const char **include_paths,
const char *source_filename) {
- return !ParseRoot(source, include_paths, source_filename).Check();
+ FLATBUFFERS_ASSERT(0 == recurse_protection_counter);
+ auto r = !ParseRoot(source, include_paths, source_filename).Check();
+ FLATBUFFERS_ASSERT(0 == recurse_protection_counter);
+ return r;
}
CheckedError Parser::StartParseFile(const char *source,