From 56e60223c38af0f64ddc8aafad27dd3a28668e7c Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Sat, 10 Sep 2022 13:41:58 -0700 Subject: [PATCH] prevent force_align attribute on enums (#7523) --- src/idl_parser.cpp | 45 ++++++++++++++++--------------------------- tests/parser_test.cpp | 1 + 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index fabe9acb568..2d961b22203 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -79,7 +79,7 @@ static bool IsLowerSnakeCase(const std::string &str) { } static void DeserializeDoc(std::vector &doc, - const Vector> *documentation) { + const Vector> *documentation) { if (documentation == nullptr) return; for (uoffset_t index = 0; index < documentation->size(); index++) doc.push_back(documentation->Get(index)->str()); @@ -87,13 +87,11 @@ static void DeserializeDoc(std::vector &doc, static CheckedError NoError() { return CheckedError(false); } -template -static std::string TypeToIntervalString() { +template static std::string TypeToIntervalString() { return "[" + NumToString((flatbuffers::numeric_limits::lowest)()) + "; " + NumToString((flatbuffers::numeric_limits::max)()) + "]"; } - // atot: template version of atoi/atof: convert a string to an instance of T. template static bool atot_scalar(const char *s, T *val, bool_constant) { @@ -120,15 +118,17 @@ static CheckedError atot(const char *s, Parser &parser, T *val) { } template<> CheckedError atot>(const char *s, Parser &parser, - Offset *val) { + Offset *val) { (void)parser; *val = Offset(atoi(s)); return NoError(); } template -static T *LookupTableByName(const SymbolTable &table, const std::string &name, - const Namespace ¤t_namespace, size_t skip_top) { +static T *LookupTableByName(const SymbolTable &table, + const std::string &name, + const Namespace ¤t_namespace, + size_t skip_top) { const auto &components = current_namespace.components; if (table.dict.empty()) return nullptr; if (components.size() < skip_top) return nullptr; @@ -187,9 +187,7 @@ static std::string TokenToString(int t) { } // clang-format on -static bool IsIdentifierStart(char c) { - return is_alpha(c) || (c == '_'); -} +static bool IsIdentifierStart(char c) { return is_alpha(c) || (c == '_'); } static bool CompareSerializedScalars(const uint8_t *a, const uint8_t *b, const FieldDef &key) { @@ -258,7 +256,8 @@ static void SwapSerializedTables(Offset *a, Offset
*b) { // See below for why we need our own sort :( template -static void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) { +static void SimpleQsort(T *begin, T *end, size_t width, F comparator, + S swapper) { if (end - begin <= static_cast(width)) return; auto l = begin + width; auto r = end; @@ -276,9 +275,7 @@ static void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) SimpleQsort(r, end, width, comparator, swapper); } - -template -static inline void SingleValueRepack(Value &e, T val) { +template static inline void SingleValueRepack(Value &e, T val) { // Remove leading zeros. if (IsInteger(e.type.base_type)) { e.constant = NumToString(val); } } @@ -294,7 +291,6 @@ static void SingleValueRepack(Value &e, double val) { } #endif - template static uint64_t EnumDistanceImpl(T e1, T e2) { if (e1 < e2) { std::swap(e1, e2); } // use std for scalars // Signed overflow may occur, use unsigned calculation. @@ -346,26 +342,19 @@ static uint64_t HashFile(const char *source_filename, const char *source) { return hash; } -template -static bool compareName(const T *a, const T *b) { +template static bool compareName(const T *a, const T *b) { return a->defined_namespace->GetFullyQualifiedName(a->name) < b->defined_namespace->GetFullyQualifiedName(b->name); } -template -static void AssignIndices(const std::vector &defvec) { +template static void AssignIndices(const std::vector &defvec) { // Pre-sort these vectors, such that we can set the correct indices for them. auto vec = defvec; std::sort(vec.begin(), vec.end(), compareName); for (int i = 0; i < static_cast(vec.size()); i++) vec[i]->index = i; } -} // namespace - - - - - +} // namespace // clang-format off const char *const kTypeNames[] = { @@ -384,7 +373,6 @@ const char kTypeSizes[] = { }; // clang-format on - void Parser::Message(const std::string &msg) { if (!error_.empty()) error_ += "\n"; // log all warnings and errors error_ += file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : ""; @@ -447,7 +435,6 @@ class Parser::ParseDepthGuard { const int caller_depth_; }; - std::string Namespace::GetFullyQualifiedName(const std::string &name, size_t max_components) const { // Early exit if we don't have a defined namespace. @@ -465,7 +452,6 @@ std::string Namespace::GetFullyQualifiedName(const std::string &name, return stream_str; } - std::string Parser::TokenToStringId(int t) const { return t == kTokenIdentifier ? attribute_ : TokenToString(t); } @@ -2413,6 +2399,9 @@ CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest, // todo: Convert to the Error in the future? Warning("underlying type of bit_flags enum must be unsigned"); } + if (enum_def->attributes.Lookup("force_align")) { + return Error("`force_align` is not a valid attribute for Enums. "); + } EnumValBuilder evb(*this, *enum_def); EXPECT('{'); // A lot of code generatos expect that an enum is not-empty. diff --git a/tests/parser_test.cpp b/tests/parser_test.cpp index 026534ad5ba..1a435044576 100644 --- a/tests/parser_test.cpp +++ b/tests/parser_test.cpp @@ -85,6 +85,7 @@ void ErrorTest() { TestError("enum X:float {}", "underlying"); TestError("enum X:byte { Y, Y }", "value already"); TestError("enum X:byte { Y=2, Z=2 }", "unique"); + TestError("enum X:byte (force_align: 4) { Y }", "force_align"); TestError("table X { Y:int; } table X {", "datatype already"); TestError("table X { } union X { }", "datatype already"); TestError("union X { } table X { }", "datatype already");