summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Glavnyy <31897320+vglavnyy@users.noreply.github.com>2020-12-08 02:12:58 +0700
committerGitHub <noreply@github.com>2020-12-07 11:12:58 -0800
commit8d9eae9ac95c06ca1ae0139a8d80522163a17ae5 (patch)
tree850b481c2e7a48b44f6e13b125a3e7f8f7d383ed
parent2046bffa40400904c926c2a5bedab67a8d6b7e08 (diff)
downloadflatbuffers-8d9eae9ac95c06ca1ae0139a8d80522163a17ae5.tar.gz
flatbuffers-8d9eae9ac95c06ca1ae0139a8d80522163a17ae5.tar.bz2
flatbuffers-8d9eae9ac95c06ca1ae0139a8d80522163a17ae5.zip
[idl_parser] Unify parsing of NaN values read from .fbs and .json files (#6296)
This commit unifies parsing of NaN values read from .fbs and .json files by converting them to unsigned NaN.
-rw-r--r--include/flatbuffers/base.h7
-rw-r--r--include/flatbuffers/stl_emulation.h6
-rw-r--r--src/idl_parser.cpp18
-rw-r--r--tests/fuzzer/CMakeLists.txt22
-rw-r--r--tests/fuzzer/flatbuffers_scalar_fuzzer.cc4
-rw-r--r--tests/fuzzer/scalar_debug.cpp2
-rw-r--r--tests/fuzzer/scalar_json.dict4
7 files changed, 55 insertions, 8 deletions
diff --git a/include/flatbuffers/base.h b/include/flatbuffers/base.h
index 95b788e0..92db55b7 100644
--- a/include/flatbuffers/base.h
+++ b/include/flatbuffers/base.h
@@ -197,12 +197,17 @@ namespace flatbuffers {
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
defined(__clang__)
- #define FLATBUFFERS_DEFAULT_DECLARATION
#define FLATBUFFERS_DELETE_FUNC(func) func = delete;
#else
#define FLATBUFFERS_DELETE_FUNC(func) private: func;
#endif
+#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
+ (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
+ defined(__clang__)
+ #define FLATBUFFERS_DEFAULT_DECLARATION
+#endif
+
// Check if we can use template aliases
// Not possible if Microsoft Compiler before 2012
// Possible is the language feature __cpp_alias_templates is defined well
diff --git a/include/flatbuffers/stl_emulation.h b/include/flatbuffers/stl_emulation.h
index 66bd620d..70e5dc94 100644
--- a/include/flatbuffers/stl_emulation.h
+++ b/include/flatbuffers/stl_emulation.h
@@ -164,6 +164,8 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
using conditional = std::conditional<B, T, F>;
template<class T, T v>
using integral_constant = std::integral_constant<T, v>;
+ template <bool B>
+ using bool_constant = integral_constant<bool, B>;
#else
// Map C++ TR1 templates defined by stlport.
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
@@ -187,6 +189,8 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
using conditional = std::tr1::conditional<B, T, F>;
template<class T, T v>
using integral_constant = std::tr1::integral_constant<T, v>;
+ template <bool B>
+ using bool_constant = integral_constant<bool, B>;
#endif // !FLATBUFFERS_CPP98_STL
#else
// MSVC 2010 doesn't support C++11 aliases.
@@ -201,6 +205,8 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
struct conditional : public std::conditional<B, T, F> {};
template<class T, T v>
struct integral_constant : public std::integral_constant<T, v> {};
+ template <bool B>
+ struct bool_constant : public integral_constant<bool, B> {};
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
#ifndef FLATBUFFERS_CPP98_STL
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index 6d916e5d..bb23dc11 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -172,8 +172,21 @@ template<typename T> std::string TypeToIntervalString() {
// atot: template version of atoi/atof: convert a string to an instance of T.
template<typename T>
-inline CheckedError atot(const char *s, Parser &parser, T *val) {
- auto done = StringToNumber(s, val);
+bool atot_scalar(const char *s, T *val, bool_constant<false>) {
+ return StringToNumber(s, val);
+}
+
+template<typename T>
+bool atot_scalar(const char *s, T *val, bool_constant<true>) {
+ // Normalize NaN parsed from fbs or json to unsigned NaN.
+ if (false == StringToNumber(s, val)) return false;
+ *val = (*val != *val) ? std::fabs(*val) : *val;
+ return true;
+}
+
+template<typename T>
+CheckedError atot(const char *s, Parser &parser, T *val) {
+ auto done = atot_scalar(s, val, bool_constant<is_floating_point<T>::value>());
if (done) return NoError();
if (0 == *val)
return parser.Error("invalid number: \"" + std::string(s) + "\"");
@@ -1806,7 +1819,6 @@ CheckedError Parser::ParseSingleValue(const std::string *name, Value &e,
match = true;
}
// Parse a float/integer number from the string.
- if (!match) check_now = true; // Re-pack if parsed from string literal.
// A "scalar-in-string" value needs extra checks.
if (!match && is_tok_string && IsScalar(in_type)) {
// Strip trailing whitespaces from attribute_.
diff --git a/tests/fuzzer/CMakeLists.txt b/tests/fuzzer/CMakeLists.txt
index 5deba0fd..717bc943 100644
--- a/tests/fuzzer/CMakeLists.txt
+++ b/tests/fuzzer/CMakeLists.txt
@@ -139,6 +139,23 @@ target_link_libraries(monster_fuzzer PRIVATE flatbuffers_fuzzed)
# Build debugger for weird cases found with fuzzer.
if(BUILD_DEBUGGER)
add_library(flatbuffers_nonfuzz STATIC ${FlatBuffers_Library_SRCS})
+ target_compile_options(
+ flatbuffers_nonfuzz
+ PUBLIC
+ $<$<BOOL:${USE_ASAN}>:
+ -fsanitize=undefined,address
+ >
+ -fno-limit-debug-info
+ )
+
+ target_link_libraries(
+ flatbuffers_nonfuzz
+ PUBLIC
+ $<$<BOOL:${USE_ASAN}>:
+ -fsanitize=undefined,address
+ >
+ )
+
target_compile_definitions(
flatbuffers_nonfuzz
PUBLIC
@@ -147,6 +164,9 @@ if(BUILD_DEBUGGER)
PRIVATE
FLATBUFFERS_MAX_PARSING_DEPTH=${FLATBUFFERS_MAX_PARSING_DEPTH}
)
- add_executable(scalar_debug flatbuffers_scalar_fuzzer.cc scalar_debug.cpp)
+ add_executable(scalar_debug
+ flatbuffers_scalar_fuzzer.cc
+ scalar_debug.cpp
+ )
target_link_libraries(scalar_debug PRIVATE flatbuffers_nonfuzz)
endif(BUILD_DEBUGGER)
diff --git a/tests/fuzzer/flatbuffers_scalar_fuzzer.cc b/tests/fuzzer/flatbuffers_scalar_fuzzer.cc
index 3c711fcb..16728d29 100644
--- a/tests/fuzzer/flatbuffers_scalar_fuzzer.cc
+++ b/tests/fuzzer/flatbuffers_scalar_fuzzer.cc
@@ -288,7 +288,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
}
// Parse original input as-is.
- auto orig_scalar = "{ \"Y\" : " + input + " }";
+ auto orig_scalar = "{\"Y\" : " + input + "}";
std::string orig_back;
auto orig_done = Parse(parser, orig_scalar, &orig_back);
@@ -326,7 +326,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Test quoted version of the string
if (!qouted_input.empty()) {
- auto fix_scalar = "{ \"Y\" : " + qouted_input + " }";
+ auto fix_scalar = "{\"Y\" : " + qouted_input + "}";
std::string fix_back;
auto fix_done = Parse(parser, fix_scalar, &fix_back);
diff --git a/tests/fuzzer/scalar_debug.cpp b/tests/fuzzer/scalar_debug.cpp
index 9ce9e5e1..d0c9b407 100644
--- a/tests/fuzzer/scalar_debug.cpp
+++ b/tests/fuzzer/scalar_debug.cpp
@@ -23,6 +23,6 @@ int main(int argc, char *argv[]) {
auto rc = LLVMFuzzerTestOneInput(
reinterpret_cast<const uint8_t *>(crash_file_data.data()),
crash_file_data.size());
- std::cout << "LLVMFuzzerTestOneInput finished with code " << rc;
+ std::cout << "LLVMFuzzerTestOneInput finished with code " << rc << "\n\n";
return rc;
}
diff --git a/tests/fuzzer/scalar_json.dict b/tests/fuzzer/scalar_json.dict
index 60689ddf..7558dc3e 100644
--- a/tests/fuzzer/scalar_json.dict
+++ b/tests/fuzzer/scalar_json.dict
@@ -17,7 +17,11 @@
"e"
"f"
"nan"
+"-nan"
+"+nan"
"inf"
+"+inf"
"-inf"
"infinity"
+"+infinity"
"-infinity"