Browse Source

Validate network data when importing portal deltas

pull/7987/head
staphen 10 months ago committed by Stephen C. Wills
parent
commit
5e561d709a
  1. 2
      Source/CMakeLists.txt
  2. 8
      Source/control.cpp
  3. 18
      Source/levels/setmaps.h
  4. 9
      Source/msg.cpp
  5. 49
      Source/portals/validation.cpp
  6. 16
      Source/portals/validation.hpp

2
Source/CMakeLists.txt

@ -142,6 +142,8 @@ set(libdevilutionx_SRCS
platform/locale.cpp
portals/validation.cpp
qol/autopickup.cpp
qol/chatlog.cpp
qol/floatingnumbers.cpp

8
Source/control.cpp

@ -422,12 +422,6 @@ void AppendArenaOverview(std::string &ret)
}
}
const dungeon_type DungeonTypeForArena[] = {
dungeon_type::DTYPE_CATHEDRAL, // SL_ARENA_CHURCH
dungeon_type::DTYPE_HELL, // SL_ARENA_HELL
dungeon_type::DTYPE_HELL, // SL_ARENA_CIRCLE_OF_LIFE
};
std::string TextCmdArena(const std::string_view parameter)
{
std::string ret;
@ -455,7 +449,7 @@ std::string TextCmdArena(const std::string_view parameter)
return ret;
}
setlvltype = DungeonTypeForArena[arenaLevel - SL_FIRST_ARENA];
setlvltype = GetArenaLevelType(arenaLevel);
StartNewLvl(*MyPlayer, WM_DIABSETLVL, arenaLevel);
return ret;
}

18
Source/levels/setmaps.h

@ -5,8 +5,26 @@
*/
#pragma once
#include "levels/gendung.h"
namespace devilution {
/**
* @brief Get the tile type used to render the given arena level
*/
inline dungeon_type GetArenaLevelType(_setlevels arenaLevel)
{
constexpr dungeon_type DungeonTypeForArena[] = {
dungeon_type::DTYPE_CATHEDRAL, // SL_ARENA_CHURCH
dungeon_type::DTYPE_HELL, // SL_ARENA_HELL
dungeon_type::DTYPE_HELL, // SL_ARENA_CIRCLE_OF_LIFE
};
constexpr size_t arenaCount = sizeof(DungeonTypeForArena) / sizeof(dungeon_type);
const size_t index = arenaLevel - SL_FIRST_ARENA;
return index < arenaCount ? DungeonTypeForArena[index] : DTYPE_NONE;
}
/**
* @brief Load a quest map, the given map is specified via the global setlvlnum
*/

9
Source/msg.cpp

@ -39,6 +39,7 @@
#include "pack.h"
#include "pfile.h"
#include "plrmsg.h"
#include "portals/validation.hpp"
#include "spells.h"
#include "storm/storm_net.hpp"
#include "sync.h"
@ -289,6 +290,12 @@ Item ItemLimbo;
/** @brief Last sent player command for the local player. */
TCmdLocParam5 lastSentPlayerCmd;
bool IsPortalDeltaValid(const DPortal &portal)
{
const WorldTilePosition position { portal.x, portal.y };
return IsPortalDeltaValid(position, portal.level, portal.ltype, portal.setlvl);
}
uint8_t GetLevelForMultiplayer(uint8_t level, bool isSetLevel)
{
if (isSetLevel)
@ -689,6 +696,8 @@ const std::byte *DeltaImportJunk(const std::byte *src, const std::byte *end)
if (src + sizeof(DPortal) > end)
return nullptr;
memcpy(&sgJunk.portal[i], src, sizeof(DPortal));
if (!IsPortalDeltaValid(sgJunk.portal[i]))
memset(&sgJunk.portal[i], 0xFF, sizeof(DPortal));
src += sizeof(DPortal);
}
}

49
Source/portals/validation.cpp

@ -0,0 +1,49 @@
/**
* @file portals/validation.cpp
*
* Implementation of functions for validation of portal data.
*/
#include "portals/validation.hpp"
#include <cstdint>
#include "engine/world_tile.hpp"
#include "levels/gendung.h"
#include "levels/setmaps.h"
#include "quests.h"
namespace devilution {
namespace {
dungeon_type GetQuestLevelType(_setlevels questLevel)
{
for (const Quest &quest : Quests) {
if (quest._qslvl == questLevel)
return quest._qlvltype;
}
return DTYPE_NONE;
}
dungeon_type GetSetLevelType(_setlevels setLevel)
{
bool isArenaLevel = setLevel >= SL_FIRST_ARENA && setLevel <= SL_LAST;
return isArenaLevel ? GetArenaLevelType(setLevel) : GetQuestLevelType(setLevel);
}
} // namespace
bool IsPortalDeltaValid(WorldTilePosition location, uint8_t level, uint8_t ltype, bool isOnSetLevel)
{
if (!InDungeonBounds(location))
return false;
dungeon_type levelType = static_cast<dungeon_type>(ltype);
if (levelType == DTYPE_NONE)
return false;
if (isOnSetLevel)
return levelType == GetSetLevelType(static_cast<_setlevels>(level));
return levelType == GetLevelType(level);
}
} // namespace devilution

16
Source/portals/validation.hpp

@ -0,0 +1,16 @@
/**
* @file portals/validation.hpp
*
* Interface of functions for validation of portal data.
*/
#pragma once
#include <cstdint>
#include "engine/world_tile.hpp"
namespace devilution {
bool IsPortalDeltaValid(WorldTilePosition location, uint8_t level, uint8_t levelType, bool isOnSetLevel);
} // namespace devilution
Loading…
Cancel
Save