summaryrefslogtreecommitdiffstats
path: root/src/WorldStorage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/WorldStorage/FastNBT.cpp34
-rw-r--r--src/WorldStorage/FastNBT.h4
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.cpp7
3 files changed, 34 insertions, 11 deletions
diff --git a/src/WorldStorage/FastNBT.cpp b/src/WorldStorage/FastNBT.cpp
index 110bc68c8..d7901217d 100644
--- a/src/WorldStorage/FastNBT.cpp
+++ b/src/WorldStorage/FastNBT.cpp
@@ -10,13 +10,6 @@
-/** If a list being loaded has more than this number of items, it's considered corrupted. */
-static const int MAX_LIST_ITEMS = 10000;
-
-
-
-
-
// The number of NBT tags that are reserved when an NBT parsing is started.
// You can override this by using a cmdline define
#ifndef NBT_RESERVE_SIZE
@@ -257,7 +250,8 @@ eNBTParseError cParsedNBT::ReadList(eTagType a_ChildrenType)
NEEDBYTES(4, eNBTParseError::npListMissingLength);
int Count = GetBEInt(m_Data + m_Pos);
m_Pos += 4;
- if ((Count < 0) || (Count > MAX_LIST_ITEMS))
+ auto MinChildSize = GetMinTagSize(a_ChildrenType);
+ if ((Count < 0) || (Count > static_cast<int>((m_Length - m_Pos) / MinChildSize)))
{
return eNBTParseError::npListInvalidLength;
}
@@ -445,6 +439,30 @@ int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const
+size_t cParsedNBT::GetMinTagSize(eTagType a_TagType)
+{
+ switch (a_TagType)
+ {
+ case TAG_End: return 1;
+ case TAG_Byte: return 1;
+ case TAG_Short: return 2;
+ case TAG_Int: return 4;
+ case TAG_Long: return 8;
+ case TAG_Float: return 4;
+ case TAG_Double: return 8;
+ case TAG_String: return 2; // 2 bytes for the string length
+ case TAG_ByteArray: return 4; // 4 bytes for the count
+ case TAG_List: return 5; // 1 byte list type + 4 bytes count
+ case TAG_Compound: return 1; // Single TAG_End byte
+ case TAG_IntArray: return 4; // 4 bytes for the count
+ }
+ UNREACHABLE("Unsupported nbt tag type");
+}
+
+
+
+
+
////////////////////////////////////////////////////////////////////////////////
// cFastNBTWriter:
diff --git a/src/WorldStorage/FastNBT.h b/src/WorldStorage/FastNBT.h
index 0185a49ec..1f11ec7f3 100644
--- a/src/WorldStorage/FastNBT.h
+++ b/src/WorldStorage/FastNBT.h
@@ -307,6 +307,10 @@ protected:
eNBTParseError ReadCompound(void); // Reads the latest tag as a compound
eNBTParseError ReadList(eTagType a_ChildrenType); // Reads the latest tag as a list of items of type a_ChildrenType
eNBTParseError ReadTag(void); // Reads the latest tag, depending on its m_Type setting
+
+ /** Returns the minimum size, in bytes, of the specified tag type.
+ Used for sanity-checking. */
+ static size_t GetMinTagSize(eTagType a_TagType);
} ;
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 96b8874a1..a5195196f 100755
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -326,7 +326,8 @@ bool cWSSAnvil::LoadChunkFromData(const cChunkCoords & a_Chunk, const AString &
if (!NBT.IsValid())
{
// NBT Parsing failed
- ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, "NBT parsing failed", a_Data);
+ auto msg = fmt::format("NBT parsing failed: {}, pos {}", NBT.GetErrorCode().message(), NBT.GetErrorPos());
+ ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, msg, a_Data);
return false;
}
@@ -3520,8 +3521,8 @@ bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, AString & a
m_ParentSchema.ChunkLoadFailed(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Printf("Unknown chunk compression: %d", CompressionType).c_str(), a_Data);
return false;
}
- return true;
- }
+ return true;
+}