LevelDB: fixed server crash when corrupted / invalid blockstate NBT is encountered

This commit is contained in:
Dylan K. Taylor 2021-12-04 18:17:17 +00:00
parent e61aaaccca
commit 1a046c6cd5
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D

View File

@ -29,6 +29,7 @@ use pocketmine\data\bedrock\BiomeIds;
use pocketmine\data\bedrock\LegacyBlockIdToStringIdMap;
use pocketmine\nbt\LittleEndianNbtSerializer;
use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\NbtException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\utils\Binary;
@ -157,6 +158,9 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
BedrockWorldData::generate($path, $name, $options);
}
/**
* @throws CorruptedChunkException
*/
protected function deserializePaletted(BinaryStream $stream) : PalettedBlockArray{
$bitsPerBlock = $stream->getByte() >> 1;
@ -169,13 +173,18 @@ class LevelDB extends BaseWorldProvider implements WritableWorldProvider{
$palette = [];
$idMap = LegacyBlockIdToStringIdMap::getInstance();
for($i = 0, $paletteSize = $stream->getLInt(); $i < $paletteSize; ++$i){
$offset = $stream->getOffset();
$tag = $nbt->read($stream->getBuffer(), $offset)->mustGetCompoundTag();
$stream->setOffset($offset);
try{
$offset = $stream->getOffset();
$id = $idMap->stringToLegacy($tag->getString("name")) ?? BlockLegacyIds::INFO_UPDATE;
$data = $tag->getShort("val");
$palette[] = ($id << Block::INTERNAL_METADATA_BITS) | $data;
$tag = $nbt->read($stream->getBuffer(), $offset)->mustGetCompoundTag();
$stream->setOffset($offset);
$id = $idMap->stringToLegacy($tag->getString("name")) ?? BlockLegacyIds::INFO_UPDATE;
$data = $tag->getShort("val");
$palette[] = ($id << Block::INTERNAL_METADATA_BITS) | $data;
}catch(NbtException $e){
throw new CorruptedChunkException("Invalid blockstate NBT at offset $i in paletted storage: " . $e->getMessage(), 0, $e);
}
}
//TODO: exceptions