Browse Source

Fix out of range enum casts in deSerialize functions (#14090)

cx384 3 months ago
parent
commit
2ea8d9ca11

+ 3 - 0
src/client/game.cpp

@@ -3027,6 +3027,9 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca
 		CASE_SET(HUD_STAT_TEXT2, text2, sdata);
 
 		CASE_SET(HUD_STAT_STYLE, style, data);
+
+		case HudElementStat_END:
+			break;
 	}
 
 #undef CASE_SET

+ 2 - 1
src/hud.h

@@ -70,7 +70,7 @@ enum HudElementType {
 	HUD_ELEM_MINIMAP   = 7
 };
 
-enum HudElementStat {
+enum HudElementStat : u8 {
 	HUD_STAT_POS = 0,
 	HUD_STAT_NAME,
 	HUD_STAT_SCALE,
@@ -85,6 +85,7 @@ enum HudElementStat {
 	HUD_STAT_Z_INDEX,
 	HUD_STAT_TEXT2,
 	HUD_STAT_STYLE,
+	HudElementStat_END // Dummy for validity check
 };
 
 enum HudCompassDir {

+ 5 - 1
src/itemdef.cpp

@@ -198,7 +198,11 @@ void ItemDefinition::deSerialize(std::istream &is, u16 protocol_version)
 	if (version < 6)
 		throw SerializationError("unsupported ItemDefinition version");
 
-	type = (enum ItemType)readU8(is);
+	type = static_cast<ItemType>(readU8(is));
+	if (type >= ItemType_END) {
+		type = ITEM_NONE;
+	}
+
 	name = deSerializeString16(is);
 	description = deSerializeString16(is);
 	inventory_image = deSerializeString16(is);

+ 2 - 1
src/itemdef.h

@@ -41,12 +41,13 @@ struct ItemStack;
 	Base item definition
 */
 
-enum ItemType
+enum ItemType : u8
 {
 	ITEM_NONE,
 	ITEM_NODE,
 	ITEM_CRAFT,
 	ITEM_TOOL,
+	ItemType_END // Dummy for validity check
 };
 
 struct ItemDefinition

+ 6 - 0
src/map.cpp

@@ -604,6 +604,8 @@ void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
 				floodable_node = n0.getContent();
 				liquid_kind = CONTENT_AIR;
 				break;
+			case LiquidType_END:
+				break;
 		}
 
 		/*
@@ -696,6 +698,8 @@ void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
 							flowing_down = true;
 					}
 					break;
+				case LiquidType_END:
+					break;
 			}
 		}
 
@@ -848,6 +852,8 @@ void ServerMap::transformLiquids(std::map<v3s16, MapBlock*> &modified_blocks,
 				for (u16 i = 0; i < num_flows; i++)
 					m_transforming_liquid.push_back(flows[i].p);
 				break;
+			case LiquidType_END:
+				break;
 		}
 	}
 	//infostream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;

+ 6 - 1
src/network/clientpackethandler.cpp

@@ -1230,8 +1230,13 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt)
 
 	*pkt >> server_id >> stat;
 
+	// Do nothing if stat is not known
+	if (stat >= HudElementStat_END) {
+		return;
+	}
+
 	// Keep in sync with:server.cpp -> SendHUDChange
-	switch ((HudElementStat)stat) {
+	switch (static_cast<HudElementStat>(stat)) {
 		case HUD_STAT_POS:
 		case HUD_STAT_SCALE:
 		case HUD_STAT_ALIGN:

+ 74 - 56
src/nodedef.cpp

@@ -126,57 +126,62 @@ void NodeBox::deSerialize(std::istream &is)
 
 	reset();
 
-	type = (enum NodeBoxType)readU8(is);
-
-	if(type == NODEBOX_FIXED || type == NODEBOX_LEVELED)
-	{
-		u16 fixed_count = readU16(is);
-		while(fixed_count--)
-		{
-			aabb3f box;
-			box.MinEdge = readV3F32(is);
-			box.MaxEdge = readV3F32(is);
-			fixed.push_back(box);
+	type = static_cast<NodeBoxType>(readU8(is));
+	switch (type) {
+		case NODEBOX_REGULAR:
+			break;
+		case NODEBOX_FIXED:
+		case NODEBOX_LEVELED: {
+			u16 fixed_count = readU16(is);
+			while(fixed_count--) {
+				aabb3f box;
+				box.MinEdge = readV3F32(is);
+				box.MaxEdge = readV3F32(is);
+				fixed.push_back(box);
+			}
+			break;
 		}
-	}
-	else if(type == NODEBOX_WALLMOUNTED)
-	{
-		wall_top.MinEdge = readV3F32(is);
-		wall_top.MaxEdge = readV3F32(is);
-		wall_bottom.MinEdge = readV3F32(is);
-		wall_bottom.MaxEdge = readV3F32(is);
-		wall_side.MinEdge = readV3F32(is);
-		wall_side.MaxEdge = readV3F32(is);
-	}
-	else if (type == NODEBOX_CONNECTED)
-	{
+		case NODEBOX_WALLMOUNTED:
+			wall_top.MinEdge = readV3F32(is);
+			wall_top.MaxEdge = readV3F32(is);
+			wall_bottom.MinEdge = readV3F32(is);
+			wall_bottom.MaxEdge = readV3F32(is);
+			wall_side.MinEdge = readV3F32(is);
+			wall_side.MaxEdge = readV3F32(is);
+			break;
+		case NODEBOX_CONNECTED: {
 #define READBOXES(box) { \
-		count = readU16(is); \
-		(box).reserve(count); \
-		while (count--) { \
-			v3f min = readV3F32(is); \
-			v3f max = readV3F32(is); \
-			(box).emplace_back(min, max); }; }
-
-		u16 count;
-
-		auto &c = getConnected();
-
-		READBOXES(fixed);
-		READBOXES(c.connect_top);
-		READBOXES(c.connect_bottom);
-		READBOXES(c.connect_front);
-		READBOXES(c.connect_left);
-		READBOXES(c.connect_back);
-		READBOXES(c.connect_right);
-		READBOXES(c.disconnected_top);
-		READBOXES(c.disconnected_bottom);
-		READBOXES(c.disconnected_front);
-		READBOXES(c.disconnected_left);
-		READBOXES(c.disconnected_back);
-		READBOXES(c.disconnected_right);
-		READBOXES(c.disconnected);
-		READBOXES(c.disconnected_sides);
+			count = readU16(is); \
+			(box).reserve(count); \
+			while (count--) { \
+				v3f min = readV3F32(is); \
+				v3f max = readV3F32(is); \
+				(box).emplace_back(min, max); }; }
+
+			u16 count;
+
+			auto &c = getConnected();
+
+			READBOXES(fixed);
+			READBOXES(c.connect_top);
+			READBOXES(c.connect_bottom);
+			READBOXES(c.connect_front);
+			READBOXES(c.connect_left);
+			READBOXES(c.connect_back);
+			READBOXES(c.connect_right);
+			READBOXES(c.disconnected_top);
+			READBOXES(c.disconnected_bottom);
+			READBOXES(c.disconnected_front);
+			READBOXES(c.disconnected_left);
+			READBOXES(c.disconnected_back);
+			READBOXES(c.disconnected_right);
+			READBOXES(c.disconnected);
+			READBOXES(c.disconnected_sides);
+			break;
+		}
+		default:
+			type = NODEBOX_REGULAR;
+			break;
 	}
 }
 
@@ -266,10 +271,13 @@ void TileDef::deSerialize(std::istream &is, NodeDrawType drawtype, u16 protocol_
 		color.setBlue(readU8(is));
 	}
 	scale = has_scale ? readU8(is) : 0;
-	if (has_align_style)
+	if (has_align_style) {
 		align_style = static_cast<AlignStyle>(readU8(is));
-	else
+		if (align_style >= AlignStyle_END)
+			align_style = ALIGN_STYLE_NODE;
+	} else {
 		align_style = ALIGN_STYLE_NODE;
+	}
 }
 
 void TextureSettings::readSettings()
@@ -559,11 +567,19 @@ void ContentFeatures::deSerialize(std::istream &is, u16 protocol_version)
 		int value = readS16(is);
 		groups[name] = value;
 	}
-	param_type = (enum ContentParamType) readU8(is);
-	param_type_2 = (enum ContentParamType2) readU8(is);
+
+	param_type = static_cast<ContentParamType>(readU8(is));
+	if (param_type >= ContentParamType_END)
+		param_type = CPT_NONE;
+
+	param_type_2 = static_cast<ContentParamType2>(readU8(is));
+	if (param_type_2 >= ContentParamType2_END)
+		param_type_2 = CPT2_NONE;
 
 	// visual
-	drawtype = (enum NodeDrawType) readU8(is);
+	drawtype = static_cast<NodeDrawType>(readU8(is));
+	if (drawtype >= NodeDrawType_END)
+		drawtype = NDT_NORMAL;
 	mesh = deSerializeString16(is);
 	visual_scale = readF32(is);
 	if (readU8(is) != 6)
@@ -609,7 +625,9 @@ void ContentFeatures::deSerialize(std::istream &is, u16 protocol_version)
 	damage_per_second = readU32(is);
 
 	// liquid
-	liquid_type = (enum LiquidType) readU8(is);
+	liquid_type = static_cast<LiquidType>(readU8(is));
+	if (liquid_type >= LiquidType_END)
+		liquid_type = LIQUID_NONE;
 	liquid_move_physics = liquid_type != LIQUID_NONE;
 	liquid_alternative_flowing = deSerializeString16(is);
 	liquid_alternative_source = deSerializeString16(is);
@@ -646,7 +664,7 @@ void ContentFeatures::deSerialize(std::istream &is, u16 protocol_version)
 		if (is.eof())
 			throw SerializationError("");
 		alpha = static_cast<enum AlphaMode>(tmp);
-		if (alpha == ALPHAMODE_LEGACY_COMPAT)
+		if (alpha >= AlphaMode_END || alpha == ALPHAMODE_LEGACY_COMPAT)
 			alpha = ALPHAMODE_OPAQUE;
 
 		tmp = readU8(is);

+ 13 - 5
src/nodedef.h

@@ -45,13 +45,14 @@ class NodeResolver;
 class TestSchematic;
 #endif
 
-enum ContentParamType
+enum ContentParamType : u8
 {
 	CPT_NONE,
 	CPT_LIGHT,
+	ContentParamType_END // Dummy for validity check
 };
 
-enum ContentParamType2
+enum ContentParamType2 : u8
 {
 	CPT2_NONE,
 	// Need 8-bit param2
@@ -82,16 +83,19 @@ enum ContentParamType2
 	CPT2_4DIR,
 	// 6 bits of palette index, then 4dir
 	CPT2_COLORED_4DIR,
+	// Dummy for validity check
+	ContentParamType2_END
 };
 
-enum LiquidType
+enum LiquidType : u8
 {
 	LIQUID_NONE,
 	LIQUID_FLOWING,
 	LIQUID_SOURCE,
+	LiquidType_END // Dummy for validity check
 };
 
-enum NodeBoxType
+enum NodeBoxType : u8
 {
 	NODEBOX_REGULAR, // Regular block; allows buildable_to
 	NODEBOX_FIXED, // Static separately defined box(es)
@@ -189,7 +193,7 @@ public:
 	void readSettings();
 };
 
-enum NodeDrawType
+enum NodeDrawType : u8
 {
 	// A basic solid block
 	NDT_NORMAL,
@@ -233,6 +237,8 @@ enum NodeDrawType
 	NDT_MESH,
 	// Combined plantlike-on-solid
 	NDT_PLANTLIKE_ROOTED,
+	// Dummy for validity check
+	NodeDrawType_END
 };
 
 // Mesh options for NDT_PLANTLIKE with CPT2_MESHOPTIONS
@@ -252,6 +258,7 @@ enum AlignStyle : u8 {
 	ALIGN_STYLE_NODE,
 	ALIGN_STYLE_WORLD,
 	ALIGN_STYLE_USER_DEFINED,
+	AlignStyle_END // Dummy for validity check
 };
 
 enum AlphaMode : u8 {
@@ -259,6 +266,7 @@ enum AlphaMode : u8 {
 	ALPHAMODE_CLIP,
 	ALPHAMODE_OPAQUE,
 	ALPHAMODE_LEGACY_COMPAT, /* only sent by old servers, equals OPAQUE */
+	AlphaMode_END // Dummy for validity check
 };
 
 

+ 4 - 0
src/particles.cpp

@@ -84,6 +84,8 @@ T TweenedParameter<T>::blend(float fac) const
 					fac *= myrand_range(0.7f, 1.0f);
 				}
 			}
+			case TweenStyle::TweenStyle_END:
+				break;
 		}
 		if (fac>1.f)
 			fac = 1.f;
@@ -110,6 +112,8 @@ template<typename T>
 void TweenedParameter<T>::deSerialize(std::istream &is)
 {
 	style = static_cast<TweenStyle>(readU8(is));
+	if (style >= TweenStyle::TweenStyle_END)
+		style = TweenStyle::fwd;
 	reps = readU16(is);
 	beginning = readF32(is);
 	start.deSerialize(is);

+ 2 - 1
src/particles.h

@@ -202,7 +202,8 @@ namespace ParticleParamTypes
 	}
 
 	// Animation styles (fwd is normal, linear interpolation)
-	enum class TweenStyle : u8 { fwd, rev, pulse, flicker };
+	// TweenStyle_END is a dummy value for validity check
+	enum class TweenStyle : u8 { fwd, rev, pulse, flicker, TweenStyle_END};
 
 	// "Tweened" pretty much means "animated" in this context
 	template <typename T>

+ 4 - 1
src/script/common/c_content.cpp

@@ -2104,7 +2104,7 @@ bool read_hud_change(lua_State *L, HudElementStat &stat, HudElement *elem, void
 			return false;
 		}
 
-		stat = (HudElementStat)statint;
+		stat = static_cast<HudElementStat>(statint);
 	}
 
 	switch (stat) {
@@ -2166,6 +2166,9 @@ bool read_hud_change(lua_State *L, HudElementStat &stat, HudElement *elem, void
 			elem->style = luaL_checknumber(L, 4);
 			*value = &elem->style;
 			break;
+		case HudElementStat_END:
+			return false;
+			break;
 	}
 
 	return true;

+ 17 - 10
src/tileanimation.cpp

@@ -41,16 +41,23 @@ void TileAnimationParams::serialize(std::ostream &os, u16 protocol_ver) const
 
 void TileAnimationParams::deSerialize(std::istream &is, u16 protocol_ver)
 {
-	type = (TileAnimationType) readU8(is);
-
-	if (type == TAT_VERTICAL_FRAMES) {
-		vertical_frames.aspect_w = readU16(is);
-		vertical_frames.aspect_h = readU16(is);
-		vertical_frames.length = readF32(is);
-	} else if (type == TAT_SHEET_2D) {
-		sheet_2d.frames_w = readU8(is);
-		sheet_2d.frames_h = readU8(is);
-		sheet_2d.frame_length = readF32(is);
+	type = static_cast<TileAnimationType>(readU8(is));
+	switch(type) {
+		case TAT_NONE:
+			break;
+		case TAT_VERTICAL_FRAMES:
+			vertical_frames.aspect_w = readU16(is);
+			vertical_frames.aspect_h = readU16(is);
+			vertical_frames.length = readF32(is);
+			break;
+		case TAT_SHEET_2D:
+			sheet_2d.frames_w = readU8(is);
+			sheet_2d.frames_h = readU8(is);
+			sheet_2d.frame_length = readF32(is);
+			break;
+		default:
+			type = TAT_NONE;
+			break;
 	}
 }
 

+ 1 - 1
src/tileanimation.h

@@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <iostream>
 #include "irrlichttypes_bloated.h"
 
-enum TileAnimationType
+enum TileAnimationType : u8
 {
 	TAT_NONE = 0,
 	TAT_VERTICAL_FRAMES = 1,

+ 1 - 1
src/util/pointedthing.cpp

@@ -92,7 +92,7 @@ void PointedThing::deSerialize(std::istream &is)
 	int version = readU8(is);
 	if (version != 0) throw SerializationError(
 			"unsupported PointedThing version");
-	type = (PointedThingType) readU8(is);
+	type = static_cast<PointedThingType>(readU8(is));
 	switch (type) {
 	case POINTEDTHING_NOTHING:
 		break;

+ 1 - 1
src/util/pointedthing.h

@@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <iostream>
 #include <string>
 
-enum PointedThingType
+enum PointedThingType : u8
 {
 	POINTEDTHING_NOTHING,
 	POINTEDTHING_NODE,