From 55686100aa6f8b4867e8de62768d8fc0ecc5a541 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Thu, 9 Jan 2020 11:47:02 -0800 Subject: [PATCH] Changed direct calls to strtod to use StringToNumber StringToNumber will correctly use locale-insensitive functions when available. Change-Id: I6bde11039a541634186f8f791012af2eb0d86b8d --- include/flatbuffers/flexbuffers.h | 6 +++++- src/idl_parser.cpp | 12 ++++++++---- src/reflection.cpp | 15 ++++++++++++--- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/include/flatbuffers/flexbuffers.h b/include/flatbuffers/flexbuffers.h index 1bc3e0f3b..fee0e9931 100644 --- a/include/flatbuffers/flexbuffers.h +++ b/include/flatbuffers/flexbuffers.h @@ -491,7 +491,11 @@ class Reference { case FBT_INDIRECT_UINT: return static_cast(ReadUInt64(Indirect(), byte_width_)); case FBT_NULL: return 0.0; - case FBT_STRING: return strtod(AsString().c_str(), nullptr); + case FBT_STRING: { + double d; + flatbuffers::StringToNumber(AsString().c_str(), &d); + return d; + } case FBT_VECTOR: return static_cast(AsVector().size()); case FBT_BOOL: return static_cast(ReadUInt64(data_, parent_width_)); diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index e082352b9..7c3c46dc1 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2764,10 +2764,13 @@ CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) { builder->Int(StringToInt(attribute_.c_str())); EXPECT(kTokenIntegerConstant); break; - case kTokenFloatConstant: - builder->Double(strtod(attribute_.c_str(), nullptr)); + case kTokenFloatConstant: { + double d; + StringToNumber(attribute_.c_str(), &d); + builder->Double(d); EXPECT(kTokenFloatConstant); break; + } default: if (IsIdent("true")) { builder->Bool(true); @@ -3220,13 +3223,14 @@ Offset FieldDef::Serialize(FlatBufferBuilder *builder, auto docs__ = parser.opts.binary_schema_comments ? builder->CreateVectorOfStrings(doc_comment) : 0; + double d; + StringToNumber(value.constant.c_str(), &d); return reflection::CreateField( *builder, name__, type__, id, value.offset, // Is uint64>max(int64) tested? IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0, // result may be platform-dependent if underlying is float (not double) - IsFloat(value.type.base_type) ? strtod(value.constant.c_str(), nullptr) - : 0.0, + IsFloat(value.type.base_type) ? d : 0.0, deprecated, required, key, attr__, docs__); // TODO: value.constant is almost always "0", we could save quite a bit of // space by sharing it. Same for common values of value.type. diff --git a/src/reflection.cpp b/src/reflection.cpp index 409dbd038..77ea0dcf4 100644 --- a/src/reflection.cpp +++ b/src/reflection.cpp @@ -56,7 +56,13 @@ double GetAnyValueF(reflection::BaseType type, const uint8_t *data) { case reflection::String: { auto s = reinterpret_cast(ReadScalar(data) + data); - return s ? strtod(s->c_str(), nullptr) : 0.0; + if (s) { + double d; + StringToNumber(s->c_str(), &d); + return d; + } else { + return 0.0; + } } default: return static_cast(GetAnyValueI(type, data)); } @@ -149,9 +155,12 @@ void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val) { void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val) { switch (type) { case reflection::Float: - case reflection::Double: - SetAnyValueF(type, data, strtod(val, nullptr)); + case reflection::Double: { + double d; + StringToNumber(val, &d); + SetAnyValueF(type, data, d); break; + } // TODO: support strings. default: SetAnyValueI(type, data, StringToInt(val)); break; }