don't crash when calling EnumNameXXX on sparse enum (#4982)
authorFrank Benkstein <frank@benkstein.net>
Mon, 8 Oct 2018 21:37:35 +0000 (23:37 +0200)
committerWouter van Oortmerssen <aardappel@gmail.com>
Mon, 8 Oct 2018 21:37:35 +0000 (14:37 -0700)
Make an out-of-bounds check for enum values before using them to index the
names array.  For consistency with non-sparse enums an empty string is
returned.

Fixes #4821

samples/monster_generated.h
src/idl_gen_cpp.cpp
tests/monster_test_generated.h
tests/namespace_test/namespace_test1_generated.h
tests/test.cpp
tests/union_vector/union_vector_generated.h

index 07fbd3a..4fbbecc 100644 (file)
@@ -55,6 +55,7 @@ inline const char * const *EnumNamesColor() {
 }
 
 inline const char *EnumNameColor(Color e) {
+  if (e < Color_Red || e > Color_Blue) return "";
   const size_t index = static_cast<int>(e);
   return EnumNamesColor()[index];
 }
@@ -84,6 +85,7 @@ inline const char * const *EnumNamesEquipment() {
 }
 
 inline const char *EnumNameEquipment(Equipment e) {
+  if (e < Equipment_NONE || e > Equipment_Weapon) return "";
   const size_t index = static_cast<int>(e);
   return EnumNamesEquipment()[index];
 }
index 8880769..1783813 100644 (file)
@@ -991,6 +991,10 @@ class CppGenerator : public BaseGenerator {
 
       code_ += "inline const char *EnumName{{ENUM_NAME}}({{ENUM_NAME}} e) {";
 
+      code_ += "  if (e < " + GetEnumValUse(enum_def, *enum_def.vals.vec.front()) +
+               " || e > " + GetEnumValUse(enum_def, *enum_def.vals.vec.back()) +
+               ") return \"\";";
+
       code_ += "  const size_t index = static_cast<int>(e)\\";
       if (enum_def.vals.vec.front()->value) {
         auto vals = GetEnumValUse(enum_def, *enum_def.vals.vec.front());
index 7e555cc..80146a9 100644 (file)
@@ -122,6 +122,7 @@ inline const char * const *EnumNamesColor() {
 }
 
 inline const char *EnumNameColor(Color e) {
+  if (e < Color_Red || e > Color_Blue) return "";
   const size_t index = static_cast<int>(e) - static_cast<int>(Color_Red);
   return EnumNamesColor()[index];
 }
@@ -157,6 +158,7 @@ inline const char * const *EnumNamesAny() {
 }
 
 inline const char *EnumNameAny(Any e) {
+  if (e < Any_NONE || e > Any_MyGame_Example2_Monster) return "";
   const size_t index = static_cast<int>(e);
   return EnumNamesAny()[index];
 }
index 247673f..0811c8e 100644 (file)
@@ -45,6 +45,7 @@ inline const char * const *EnumNamesEnumInNestedNS() {
 }
 
 inline const char *EnumNameEnumInNestedNS(EnumInNestedNS e) {
+  if (e < EnumInNestedNS_A || e > EnumInNestedNS_C) return "";
   const size_t index = static_cast<int>(e);
   return EnumNamesEnumInNestedNS()[index];
 }
index 030c5d9..d735723 100644 (file)
@@ -1285,6 +1285,14 @@ void EnumStringsTest() {
           true);
 }
 
+void EnumNamesTest() {
+  TEST_EQ_STR("Red", EnumNameColor(Color_Red));
+  TEST_EQ_STR("Green", EnumNameColor(Color_Green));
+  TEST_EQ_STR("Blue", EnumNameColor(Color_Blue));
+  TEST_EQ_STR("", EnumNameColor(static_cast<Color>(-1)));
+  TEST_EQ_STR("", EnumNameColor(static_cast<Color>(1000)));
+}
+
 void IntegerOutOfRangeTest() {
   TestError("table T { F:byte; } root_type T; { F:128 }",
             "constant does not fit");
@@ -2058,6 +2066,7 @@ int FlatBufferTests() {
   ErrorTest();
   ValueTest();
   EnumStringsTest();
+  EnumNamesTest();
   IntegerOutOfRangeTest();
   IntegerBoundaryTest();
   UnicodeTest();
index 077e9a0..4c6ee09 100644 (file)
@@ -69,6 +69,7 @@ inline const char * const *EnumNamesCharacter() {
 }
 
 inline const char *EnumNameCharacter(Character e) {
+  if (e < Character_NONE || e > Character_Unused) return "";
   const size_t index = static_cast<int>(e);
   return EnumNamesCharacter()[index];
 }