Skip to content

Commit

Permalink
Fix recursion counter check. Add control to override depth of nested … (
Browse files Browse the repository at this point in the history
google#4953)

* Fix recursion counter check. Add control to override depth of nested objects.

* Change if-condition to `>=`
  • Loading branch information
vglavnyy authored and aardappel committed Oct 4, 2018
1 parent c0698cc commit 925c1d7
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 5 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions docs/source/Building.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
9 changes: 9 additions & 0 deletions docs/source/CppUsage.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<br>
11 changes: 9 additions & 2 deletions include/flatbuffers/idl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -745,10 +751,11 @@ class Parser : public ParserState {
bool SupportsVectorOfUnions() const;
Namespace *UniqueNamespace(Namespace *ns);

enum { kMaxParsingDepth = 64 };
FLATBUFFERS_CHECKED_ERROR RecurseError();
template<typename F> 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;
Expand Down
9 changes: 6 additions & 3 deletions src/idl_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 925c1d7

Please sign in to comment.