region: harden handling of ByteArrayTag

previously this would just explode if the wrong length of data was given.
This commit is contained in:
Dylan K. Taylor 2020-10-31 15:37:06 +00:00
parent 058bb3a91a
commit 0cbc5c9a4a
4 changed files with 24 additions and 5 deletions

View File

@ -36,7 +36,10 @@ class Anvil extends RegionWorldProvider{
}
protected function deserializeSubChunk(CompoundTag $subChunk) : SubChunk{
return new SubChunk(BlockLegacyIds::AIR << 4, [SubChunkConverter::convertSubChunkYZX($subChunk->getByteArray("Blocks"), $subChunk->getByteArray("Data"))]);
return new SubChunk(BlockLegacyIds::AIR << 4, [SubChunkConverter::convertSubChunkYZX(
self::readFixedSizeByteArray($subChunk, "Blocks", 4096),
self::readFixedSizeByteArray($subChunk, "Data", 2048)
)]);
//ignore legacy light information
}

View File

@ -36,7 +36,6 @@ use pocketmine\world\format\io\ChunkUtils;
use pocketmine\world\format\io\exception\CorruptedChunkException;
use pocketmine\world\format\io\SubChunkConverter;
use pocketmine\world\format\SubChunk;
use function str_repeat;
use function zlib_decode;
class McRegion extends RegionWorldProvider{
@ -68,8 +67,8 @@ class McRegion extends RegionWorldProvider{
}
$subChunks = [];
$fullIds = ($fullIdsTag = $chunk->getTag("Blocks")) instanceof ByteArrayTag ? $fullIdsTag->getValue() : str_repeat("\x00", 32768);
$fullData = ($fullDataTag = $chunk->getTag("Data")) instanceof ByteArrayTag ? $fullDataTag->getValue() : str_repeat("\x00", 16384);
$fullIds = self::readFixedSizeByteArray($chunk, "Blocks", 32768);
$fullData = self::readFixedSizeByteArray($chunk, "Data", 16384);
for($y = 0; $y < 8; ++$y){
$subChunks[$y] = new SubChunk(BlockLegacyIds::AIR << 4, [SubChunkConverter::convertSubChunkFromLegacyColumn($fullIds, $fullData, $y)]);

View File

@ -36,7 +36,10 @@ class PMAnvil extends RegionWorldProvider{
use LegacyAnvilChunkTrait;
protected function deserializeSubChunk(CompoundTag $subChunk) : SubChunk{
return new SubChunk(BlockLegacyIds::AIR << 4, [SubChunkConverter::convertSubChunkXZY($subChunk->getByteArray("Blocks"), $subChunk->getByteArray("Data"))]);
return new SubChunk(BlockLegacyIds::AIR << 4, [SubChunkConverter::convertSubChunkXZY(
self::readFixedSizeByteArray($subChunk, "Blocks", 4096),
self::readFixedSizeByteArray($subChunk, "Data", 2048)
)]);
}
protected static function getRegionFileExtension() : string{

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\world\format\io\region;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\ByteArrayTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\utils\Utils;
@ -41,6 +42,7 @@ use function mkdir;
use function morton2d_encode;
use function rename;
use function scandir;
use function strlen;
use function strrpos;
use function substr;
use function time;
@ -196,6 +198,18 @@ abstract class RegionWorldProvider extends BaseWorldProvider{
return $result;
}
protected static function readFixedSizeByteArray(CompoundTag $chunk, string $tagName, int $length) : string{
$tag = $chunk->getTag($tagName);
if(!($tag instanceof ByteArrayTag)){
throw new CorruptedChunkException("Expected TAG_ByteArray for '$tagName'");
}
$data = $tag->getValue();
if(strlen($data) !== $length){
throw new CorruptedChunkException("Expected '$tagName' payload to have exactly $length bytes, but have " . strlen($data));
}
return $data;
}
/**
* @throws CorruptedChunkException
*/