mirror of
https://github.com/google/flatbuffers.git
synced 2026-07-01 17:33:57 +00:00
[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.
This commit is contained in:
@@ -197,12 +197,17 @@ namespace flatbuffers {
|
|||||||
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
|
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
|
||||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
|
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
|
||||||
defined(__clang__)
|
defined(__clang__)
|
||||||
#define FLATBUFFERS_DEFAULT_DECLARATION
|
|
||||||
#define FLATBUFFERS_DELETE_FUNC(func) func = delete;
|
#define FLATBUFFERS_DELETE_FUNC(func) func = delete;
|
||||||
#else
|
#else
|
||||||
#define FLATBUFFERS_DELETE_FUNC(func) private: func;
|
#define FLATBUFFERS_DELETE_FUNC(func) private: func;
|
||||||
#endif
|
#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
|
// Check if we can use template aliases
|
||||||
// Not possible if Microsoft Compiler before 2012
|
// Not possible if Microsoft Compiler before 2012
|
||||||
// Possible is the language feature __cpp_alias_templates is defined well
|
// Possible is the language feature __cpp_alias_templates is defined well
|
||||||
|
|||||||
@@ -164,6 +164,8 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
|||||||
using conditional = std::conditional<B, T, F>;
|
using conditional = std::conditional<B, T, F>;
|
||||||
template<class T, T v>
|
template<class T, T v>
|
||||||
using integral_constant = std::integral_constant<T, v>;
|
using integral_constant = std::integral_constant<T, v>;
|
||||||
|
template <bool B>
|
||||||
|
using bool_constant = integral_constant<bool, B>;
|
||||||
#else
|
#else
|
||||||
// Map C++ TR1 templates defined by stlport.
|
// Map C++ TR1 templates defined by stlport.
|
||||||
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
|
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>;
|
using conditional = std::tr1::conditional<B, T, F>;
|
||||||
template<class T, T v>
|
template<class T, T v>
|
||||||
using integral_constant = std::tr1::integral_constant<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
|
#endif // !FLATBUFFERS_CPP98_STL
|
||||||
#else
|
#else
|
||||||
// MSVC 2010 doesn't support C++11 aliases.
|
// 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> {};
|
struct conditional : public std::conditional<B, T, F> {};
|
||||||
template<class T, T v>
|
template<class T, T v>
|
||||||
struct integral_constant : public std::integral_constant<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)
|
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_CPP98_STL
|
#ifndef FLATBUFFERS_CPP98_STL
|
||||||
|
|||||||
@@ -172,8 +172,21 @@ template<typename T> std::string TypeToIntervalString() {
|
|||||||
|
|
||||||
// atot: template version of atoi/atof: convert a string to an instance of T.
|
// atot: template version of atoi/atof: convert a string to an instance of T.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline CheckedError atot(const char *s, Parser &parser, T *val) {
|
bool atot_scalar(const char *s, T *val, bool_constant<false>) {
|
||||||
auto done = StringToNumber(s, val);
|
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 (done) return NoError();
|
||||||
if (0 == *val)
|
if (0 == *val)
|
||||||
return parser.Error("invalid number: \"" + std::string(s) + "\"");
|
return parser.Error("invalid number: \"" + std::string(s) + "\"");
|
||||||
@@ -1806,7 +1819,6 @@ CheckedError Parser::ParseSingleValue(const std::string *name, Value &e,
|
|||||||
match = true;
|
match = true;
|
||||||
}
|
}
|
||||||
// Parse a float/integer number from the string.
|
// 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.
|
// A "scalar-in-string" value needs extra checks.
|
||||||
if (!match && is_tok_string && IsScalar(in_type)) {
|
if (!match && is_tok_string && IsScalar(in_type)) {
|
||||||
// Strip trailing whitespaces from attribute_.
|
// Strip trailing whitespaces from attribute_.
|
||||||
|
|||||||
@@ -139,6 +139,23 @@ target_link_libraries(monster_fuzzer PRIVATE flatbuffers_fuzzed)
|
|||||||
# Build debugger for weird cases found with fuzzer.
|
# Build debugger for weird cases found with fuzzer.
|
||||||
if(BUILD_DEBUGGER)
|
if(BUILD_DEBUGGER)
|
||||||
add_library(flatbuffers_nonfuzz STATIC ${FlatBuffers_Library_SRCS})
|
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(
|
target_compile_definitions(
|
||||||
flatbuffers_nonfuzz
|
flatbuffers_nonfuzz
|
||||||
PUBLIC
|
PUBLIC
|
||||||
@@ -147,6 +164,9 @@ if(BUILD_DEBUGGER)
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
FLATBUFFERS_MAX_PARSING_DEPTH=${FLATBUFFERS_MAX_PARSING_DEPTH}
|
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)
|
target_link_libraries(scalar_debug PRIVATE flatbuffers_nonfuzz)
|
||||||
endif(BUILD_DEBUGGER)
|
endif(BUILD_DEBUGGER)
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse original input as-is.
|
// Parse original input as-is.
|
||||||
auto orig_scalar = "{ \"Y\" : " + input + " }";
|
auto orig_scalar = "{\"Y\" : " + input + "}";
|
||||||
std::string orig_back;
|
std::string orig_back;
|
||||||
auto orig_done = Parse(parser, orig_scalar, &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
|
// Test quoted version of the string
|
||||||
if (!qouted_input.empty()) {
|
if (!qouted_input.empty()) {
|
||||||
auto fix_scalar = "{ \"Y\" : " + qouted_input + " }";
|
auto fix_scalar = "{\"Y\" : " + qouted_input + "}";
|
||||||
std::string fix_back;
|
std::string fix_back;
|
||||||
auto fix_done = Parse(parser, fix_scalar, &fix_back);
|
auto fix_done = Parse(parser, fix_scalar, &fix_back);
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,6 @@ int main(int argc, char *argv[]) {
|
|||||||
auto rc = LLVMFuzzerTestOneInput(
|
auto rc = LLVMFuzzerTestOneInput(
|
||||||
reinterpret_cast<const uint8_t *>(crash_file_data.data()),
|
reinterpret_cast<const uint8_t *>(crash_file_data.data()),
|
||||||
crash_file_data.size());
|
crash_file_data.size());
|
||||||
std::cout << "LLVMFuzzerTestOneInput finished with code " << rc;
|
std::cout << "LLVMFuzzerTestOneInput finished with code " << rc << "\n\n";
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,11 @@
|
|||||||
"e"
|
"e"
|
||||||
"f"
|
"f"
|
||||||
"nan"
|
"nan"
|
||||||
|
"-nan"
|
||||||
|
"+nan"
|
||||||
"inf"
|
"inf"
|
||||||
|
"+inf"
|
||||||
"-inf"
|
"-inf"
|
||||||
"infinity"
|
"infinity"
|
||||||
|
"+infinity"
|
||||||
"-infinity"
|
"-infinity"
|
||||||
|
|||||||
Reference in New Issue
Block a user