summaryrefslogtreecommitdiffstats
path: root/src/WorldStorage
diff options
context:
space:
mode:
Diffstat (limited to 'src/WorldStorage')
-rw-r--r--src/WorldStorage/WSSAnvil.cpp30
1 files changed, 29 insertions, 1 deletions
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index e79cc291d..0c31d8b02 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -69,6 +69,18 @@ Since only the header is actually in the memory, this number can be high, but st
/// The maximum size of an inflated chunk; raw chunk data is 192 KiB, allow 64 KiB more of entities
#define CHUNK_INFLATE_MAX 256 KiB
+#define LOAD_FAILED(CHX, CHZ) \
+ { \
+ const int RegionX = FAST_FLOOR_DIV(CHX, 32); \
+ const int RegionZ = FAST_FLOOR_DIV(CHZ, 32); \
+ LOGERROR("%s (%d): Loading chunk [%d, %d] from file r.%d.%d.mca failed. " \
+ "The server will now abort in order to avoid further data loss. " \
+ "Please add the reported file and this message to the issue report.", \
+ __FUNCTION__, __LINE__, CHX, CHZ, RegionX, RegionZ \
+ ); \
+ *((int *)0) = 0; /* Crash intentionally */ \
+ }
+
@@ -263,6 +275,7 @@ bool cWSSAnvil::LoadChunkFromData(const cChunkCoords & a_Chunk, const AString &
inflateEnd(&strm);
if (res != Z_STREAM_END)
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
@@ -271,6 +284,7 @@ bool cWSSAnvil::LoadChunkFromData(const cChunkCoords & a_Chunk, const AString &
if (!NBT.IsValid())
{
// NBT Parsing failed
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
@@ -317,11 +331,13 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
int Level = a_NBT.FindChildByName(0, "Level");
if (Level < 0)
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
int Sections = a_NBT.FindChildByName(Level, "Sections");
if ((Sections < 0) || (a_NBT.GetType(Sections) != TAG_List) || (a_NBT.GetChildrenType(Sections) != TAG_Compound))
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
for (int Child = a_NBT.GetFirstChild(Sections); Child >= 0; Child = a_NBT.GetNextSibling(Child))
@@ -2811,30 +2827,42 @@ bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, AString & a
}
unsigned ChunkLocation = ntohl(m_Header[LocalX + 32 * LocalZ]);
unsigned ChunkOffset = ChunkLocation >> 8;
+ if (ChunkOffset <= 2)
+ {
+ return false;
+ }
m_File.Seek((int)ChunkOffset * 4096);
int ChunkSize = 0;
if (m_File.Read(&ChunkSize, 4) != 4)
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
ChunkSize = ntohl((u_long)ChunkSize);
char CompressionType = 0;
if (m_File.Read(&CompressionType, 1) != 1)
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
if (CompressionType != 2)
{
// Chunk is in an unknown compression
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
ChunkSize--;
// HACK: This depends on the internal knowledge that AString's data() function returns the internal buffer directly
a_Data.assign(ChunkSize, '\0');
- return (m_File.Read((void *)a_Data.data(), ChunkSize) == ChunkSize);
+ if (m_File.Read((void *)a_Data.data(), ChunkSize) == ChunkSize)
+ {
+ return true;
+ }
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
+ return false;
}