protocol: specialize exception used for bad packets

This commit is contained in:
Dylan K. Taylor 2020-04-27 12:55:00 +01:00
parent f91e2f41e0
commit 15c744b0d7
15 changed files with 79 additions and 52 deletions

View File

@ -63,6 +63,7 @@ use pocketmine\network\mcpe\protocol\ModalFormRequestPacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket;
use pocketmine\network\mcpe\protocol\Packet;
use pocketmine\network\mcpe\protocol\PacketDecodeException;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\protocol\PlayStatusPacket;
use pocketmine\network\mcpe\protocol\ServerboundPacket;
@ -327,7 +328,11 @@ class NetworkSession{
$timings->startTiming();
try{
$packet->decode();
try{
$packet->decode();
}catch(PacketDecodeException $e){
throw BadPacketException::wrap($e);
}
$stream = $packet->getBinaryStream();
if(!$stream->feof()){
$remains = substr($stream->getBuffer(), $stream->getOffset());

View File

@ -25,7 +25,6 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\types\command\CommandData;
use pocketmine\network\mcpe\protocol\types\command\CommandEnum;
use pocketmine\network\mcpe\protocol\types\command\CommandEnumConstraint;
@ -147,7 +146,7 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
/**
* @param string[] $enumValueList
*
* @throws BadPacketException
* @throws PacketDecodeException
* @throws BinaryDataException
*/
protected function getEnum(array $enumValueList, NetworkBinaryStream $in) : CommandEnum{
@ -159,7 +158,7 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
for($i = 0, $count = $in->getUnsignedVarInt(); $i < $count; ++$i){
$index = $this->getEnumValueIndex($listSize, $in);
if(!isset($enumValueList[$index])){
throw new BadPacketException("Invalid enum value index $index");
throw new PacketDecodeException("Invalid enum value index $index");
}
//Get the enum value from the initial pile of mess
$enumValues[] = $enumValueList[$index];
@ -238,23 +237,23 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
* @param CommandEnum[] $enums
* @param string[] $enumValues
*
* @throws BadPacketException
* @throws PacketDecodeException
* @throws BinaryDataException
*/
protected function getEnumConstraint(array $enums, array $enumValues, NetworkBinaryStream $in) : CommandEnumConstraint{
//wtf, what was wrong with an offset inside the enum? :(
$valueIndex = $in->getLInt();
if(!isset($enumValues[$valueIndex])){
throw new BadPacketException("Enum constraint refers to unknown enum value index $valueIndex");
throw new PacketDecodeException("Enum constraint refers to unknown enum value index $valueIndex");
}
$enumIndex = $in->getLInt();
if(!isset($enums[$enumIndex])){
throw new BadPacketException("Enum constraint refers to unknown enum index $enumIndex");
throw new PacketDecodeException("Enum constraint refers to unknown enum index $enumIndex");
}
$enum = $enums[$enumIndex];
$valueOffset = array_search($enumValues[$valueIndex], $enum->getValues(), true);
if($valueOffset === false){
throw new BadPacketException("Value \"" . $enumValues[$valueIndex] . "\" does not belong to enum \"" . $enum->getName() . "\"");
throw new PacketDecodeException("Value \"" . $enumValues[$valueIndex] . "\" does not belong to enum \"" . $enum->getName() . "\"");
}
$constraintIds = [];
@ -282,7 +281,7 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
* @param CommandEnum[] $enums
* @param string[] $postfixes
*
* @throws BadPacketException
* @throws PacketDecodeException
* @throws BinaryDataException
*/
protected function getCommandData(array $enums, array $postfixes, NetworkBinaryStream $in) : CommandData{
@ -306,16 +305,16 @@ class AvailableCommandsPacket extends DataPacket implements ClientboundPacket{
$index = ($parameter->paramType & 0xffff);
$parameter->enum = $enums[$index] ?? null;
if($parameter->enum === null){
throw new BadPacketException("deserializing $name parameter $parameter->paramName: expected enum at $index, but got none");
throw new PacketDecodeException("deserializing $name parameter $parameter->paramName: expected enum at $index, but got none");
}
}elseif(($parameter->paramType & self::ARG_FLAG_POSTFIX) !== 0){
$index = ($parameter->paramType & 0xffff);
$parameter->postfix = $postfixes[$index] ?? null;
if($parameter->postfix === null){
throw new BadPacketException("deserializing $name parameter $parameter->paramName: expected postfix at $index, but got none");
throw new PacketDecodeException("deserializing $name parameter $parameter->paramName: expected postfix at $index, but got none");
}
}elseif(($parameter->paramType & self::ARG_FLAG_VALID) === 0){
throw new BadPacketException("deserializing $name parameter $parameter->paramName: Invalid parameter type 0x" . dechex($parameter->paramType));
throw new PacketDecodeException("deserializing $name parameter $parameter->paramName: Invalid parameter type 0x" . dechex($parameter->paramType));
}
$overloads[$overloadIndex][$paramIndex] = $parameter;

View File

@ -25,7 +25,6 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
class BookEditPacket extends DataPacket implements ServerboundPacket{
@ -82,7 +81,7 @@ class BookEditPacket extends DataPacket implements ServerboundPacket{
$this->xuid = $in->getString();
break;
default:
throw new BadPacketException("Unknown book edit type $this->type!");
throw new PacketDecodeException("Unknown book edit type $this->type!");
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\types\DimensionIds;
use pocketmine\network\mcpe\protocol\types\MapDecoration;
use pocketmine\network\mcpe\protocol\types\MapTrackedObject;
@ -98,7 +97,7 @@ class ClientboundMapItemDataPacket extends DataPacket implements ClientboundPack
}elseif($object->type === MapTrackedObject::TYPE_ENTITY){
$object->entityUniqueId = $in->getEntityUniqueId();
}else{
throw new BadPacketException("Unknown map object type $object->type");
throw new PacketDecodeException("Unknown map object type $object->type");
}
$this->trackedEntities[] = $object;
}
@ -122,7 +121,7 @@ class ClientboundMapItemDataPacket extends DataPacket implements ClientboundPack
$count = $in->getUnsignedVarInt();
if($count !== $this->width * $this->height){
throw new BadPacketException("Expected colour count of " . ($this->height * $this->width) . " (height $this->height * width $this->width), got $count");
throw new PacketDecodeException("Expected colour count of " . ($this->height * $this->width) . " (height $this->height * width $this->width), got $count");
}
for($y = 0; $y < $this->height; ++$y){

View File

@ -25,7 +25,6 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\types\PotionContainerChangeRecipe;
use pocketmine\network\mcpe\protocol\types\PotionTypeRecipe;
use pocketmine\network\mcpe\protocol\types\recipe\FurnaceRecipe;
@ -80,7 +79,7 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{
$this->entries[] = MultiRecipe::decode($recipeType, $in);
break;
default:
throw new BadPacketException("Unhandled recipe type $recipeType!"); //do not continue attempting to decode
throw new PacketDecodeException("Unhandled recipe type $recipeType!"); //do not continue attempting to decode
}
}
for($i = 0, $count = $in->getUnsignedVarInt(); $i < $count; ++$i){

View File

@ -25,7 +25,6 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
use pocketmine\utils\BinaryDataException;
use function get_class;
@ -69,15 +68,15 @@ abstract class DataPacket implements Packet{
}
/**
* @throws BadPacketException
* @throws PacketDecodeException
*/
final public function decode() : void{
$this->buf->rewind();
try{
$this->decodeHeader($this->buf);
$this->decodePayload($this->buf);
}catch(BinaryDataException | BadPacketException $e){
throw BadPacketException::wrap($e, $this->getName());
}catch(BinaryDataException | PacketDecodeException $e){
throw PacketDecodeException::wrap($e, $this->getName());
}
}
@ -100,7 +99,7 @@ abstract class DataPacket implements Packet{
/**
* Decodes the packet body, without the packet ID or other generic header fields.
*
* @throws BadPacketException
* @throws PacketDecodeException
* @throws BinaryDataException
*/
abstract protected function decodePayload(NetworkBinaryStream $in) : void;

View File

@ -25,7 +25,6 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\types\inventory\MismatchTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\NormalTransactionData;
use pocketmine\network\mcpe\protocol\types\inventory\ReleaseItemTransactionData;
@ -69,7 +68,7 @@ class InventoryTransactionPacket extends DataPacket implements ClientboundPacket
$this->trData = new ReleaseItemTransactionData();
break;
default:
throw new BadPacketException("Unknown transaction type $transactionType");
throw new PacketDecodeException("Unknown transaction type $transactionType");
}
$this->trData->decode($in);

View File

@ -25,7 +25,6 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\types\login\AuthenticationData;
use pocketmine\network\mcpe\protocol\types\login\ClientData;
use pocketmine\network\mcpe\protocol\types\login\JwtChain;
@ -71,7 +70,7 @@ class LoginPacket extends DataPacket implements ServerboundPacket{
}
/**
* @throws BadPacketException
* @throws PacketDecodeException
* @throws BinaryDataException
*/
protected function decodeConnectionRequest(NetworkBinaryStream $in) : void{
@ -84,7 +83,7 @@ class LoginPacket extends DataPacket implements ServerboundPacket{
try{
$chainData = $mapper->map($chainDataJson, new JwtChain);
}catch(\JsonMapper_Exception $e){
throw BadPacketException::wrap($e);
throw PacketDecodeException::wrap($e);
}
$this->chainDataJwt = $chainData;
@ -94,14 +93,14 @@ class LoginPacket extends DataPacket implements ServerboundPacket{
try{
$claims = Utils::getJwtClaims($chain);
}catch(\UnexpectedValueException $e){
throw new BadPacketException($e->getMessage(), 0, $e);
throw new PacketDecodeException($e->getMessage(), 0, $e);
}
if(isset($claims["extraData"])){
if(!is_array($claims["extraData"])){
throw new BadPacketException("'extraData' key should be an array");
throw new PacketDecodeException("'extraData' key should be an array");
}
if($this->extraData !== null){
throw new BadPacketException("Found 'extraData' more than once in chainData");
throw new PacketDecodeException("Found 'extraData' more than once in chainData");
}
$mapper = new \JsonMapper;
@ -111,19 +110,19 @@ class LoginPacket extends DataPacket implements ServerboundPacket{
try{
$this->extraData = $mapper->map($claims['extraData'], new AuthenticationData);
}catch(\JsonMapper_Exception $e){
throw BadPacketException::wrap($e);
throw PacketDecodeException::wrap($e);
}
}
}
if($this->extraData === null){
throw new BadPacketException("'extraData' not found in chain data");
throw new PacketDecodeException("'extraData' not found in chain data");
}
$this->clientDataJwt = $buffer->get($buffer->getLInt());
try{
$clientData = Utils::getJwtClaims($this->clientDataJwt);
}catch(\UnexpectedValueException $e){
throw new BadPacketException($e->getMessage(), 0, $e);
throw new PacketDecodeException($e->getMessage(), 0, $e);
}
$mapper = new \JsonMapper;
@ -133,7 +132,7 @@ class LoginPacket extends DataPacket implements ServerboundPacket{
try{
$this->clientData = $mapper->map($clientData, new ClientData);
}catch(\JsonMapper_Exception $e){
throw BadPacketException::wrap($e);
throw PacketDecodeException::wrap($e);
}
}

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\protocol;
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
interface Packet{
@ -37,7 +36,7 @@ interface Packet{
public function canBeSentBeforeLogin() : bool;
/**
* @throws BadPacketException
* @throws PacketDecodeException
*/
public function decode() : void;
@ -56,7 +55,7 @@ interface Packet{
* @param PacketHandlerInterface $handler
*
* @return bool true if the packet was handled successfully, false if not.
* @throws BadPacketException if broken data was found in the packet
* @throws PacketDecodeException if broken data was found in the packet
*/
public function handle(PacketHandlerInterface $handler) : bool;
}

View File

@ -0,0 +1,31 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\network\mcpe\protocol;
final class PacketDecodeException extends \RuntimeException{
public static function wrap(\Throwable $previous, ?string $prefix = null) : self{
return new self(($prefix !== null ? $prefix . ": " : "") . $previous->getMessage(), 0, $previous);
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\network\mcpe\protocol;
#include <rules/DataPacket.h>
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\types\ScorePacketEntry;
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
use function count;
@ -59,7 +58,7 @@ class SetScorePacket extends DataPacket implements ClientboundPacket{
$entry->customName = $in->getString();
break;
default:
throw new BadPacketException("Unknown entry type $entry->type");
throw new PacketDecodeException("Unknown entry type $entry->type");
}
}
$this->entries[] = $entry;

View File

@ -26,7 +26,7 @@ namespace pocketmine\network\mcpe\protocol\types\entity;
use pocketmine\nbt\NbtDataException;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\TreeRoot;
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\PacketDecodeException;
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
use pocketmine\network\mcpe\serializer\NetworkNbtSerializer;
@ -51,14 +51,14 @@ final class CompoundTagMetadataProperty implements MetadataProperty{
}
/**
* @throws BadPacketException
* @throws PacketDecodeException
*/
public static function read(NetworkBinaryStream $in) : self{
$offset = $in->getOffset();
try{
$tag = (new NetworkNbtSerializer())->read($in->getBuffer(), $offset, 512)->mustGetCompoundTag();
}catch(NbtDataException $e){
throw new BadPacketException($e->getMessage(), 0, $e);
throw new PacketDecodeException($e->getMessage(), 0, $e);
}
$in->setOffset($offset);
return new self($tag);

View File

@ -23,8 +23,8 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\protocol\types\inventory;
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
use pocketmine\network\mcpe\protocol\PacketDecodeException;
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
use function count;
@ -36,7 +36,7 @@ class MismatchTransactionData extends TransactionData{
protected function decodeData(NetworkBinaryStream $stream) : void{
if(count($this->actions) > 0){
throw new BadPacketException("Mismatch transaction type should not have any actions associated with it, but got " . count($this->actions));
throw new PacketDecodeException("Mismatch transaction type should not have any actions associated with it, but got " . count($this->actions));
}
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\protocol\types\inventory;
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\PacketDecodeException;
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
use pocketmine\utils\BinaryDataException;
@ -81,7 +81,7 @@ class NetworkInventoryAction{
* @return $this
*
* @throws BinaryDataException
* @throws BadPacketException
* @throws PacketDecodeException
*/
public function read(NetworkBinaryStream $packet) : NetworkInventoryAction{
$this->sourceType = $packet->getUnsignedVarInt();
@ -99,7 +99,7 @@ class NetworkInventoryAction{
$this->windowId = $packet->getVarInt();
break;
default:
throw new BadPacketException("Unknown inventory action source type $this->sourceType");
throw new PacketDecodeException("Unknown inventory action source type $this->sourceType");
}
$this->inventorySlot = $packet->getUnsignedVarInt();

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\protocol\types\inventory;
use pocketmine\network\BadPacketException;
use pocketmine\network\mcpe\protocol\PacketDecodeException;
use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
use pocketmine\utils\BinaryDataException;
use function count;
@ -43,7 +43,7 @@ abstract class TransactionData{
/**
* @throws BinaryDataException
* @throws BadPacketException
* @throws PacketDecodeException
*/
final public function decode(NetworkBinaryStream $stream) : void{
$actionCount = $stream->getUnsignedVarInt();
@ -55,7 +55,7 @@ abstract class TransactionData{
/**
* @throws BinaryDataException
* @throws BadPacketException
* @throws PacketDecodeException
*/
abstract protected function decodeData(NetworkBinaryStream $stream) : void;