fix(rx): reject undersized typed frames safely

This commit is contained in:
2026-08-28 14:54:06 +03:00
parent 36f234739a
commit c7efd1cb65
4 changed files with 299 additions and 15 deletions

View File

@ -2,12 +2,30 @@
namespace PacketTypes
{
bool BasePack::checkPacketLayout() const
{
if (packInfo == nullptr || packInfo->buffer == nullptr ||
packInfo->packSize < msgBytes + crcBytes ||
packInfo->packSize > irproto::kMaxWireFrameBytes)
{
return false;
}
return (packInfo->buffer[msgOffset] & IR_MASK_MSG_INFO) == packInfo->packSize;
}
bool BasePack::checkAddress() { return true; };
void BasePack::set(IR_FOX::PackInfo *packInfo, uint16_t id)
{
isAvailable = false;
isRawAvailable = false;
this->packInfo = packInfo;
this->id = id;
if (!checkPacketLayout())
{
return;
}
if (checkAddress())
{
isAvailable = true;
@ -27,24 +45,58 @@ namespace PacketTypes
uint16_t BasePack::_getAddrFrom(BasePack *obj)
{
if (obj == nullptr || !obj->checkPacketLayout() ||
obj->packInfo == nullptr || obj->packInfo->buffer == nullptr ||
obj->packInfo->packSize < crcBytes ||
static_cast<uint16_t>(obj->addressFromOffset) + 1U >=
static_cast<uint16_t>(obj->packInfo->packSize - crcBytes))
{
return 0U;
}
return (obj->packInfo->buffer[obj->addressFromOffset] << 8) | obj->packInfo->buffer[obj->addressFromOffset + 1];
};
uint16_t BasePack::_getAddrTo(BasePack *obj)
{
if (obj == nullptr || !obj->checkPacketLayout() ||
obj->packInfo == nullptr || obj->packInfo->buffer == nullptr ||
obj->packInfo->packSize < crcBytes ||
static_cast<uint16_t>(obj->addressToOffset) + 1U >=
static_cast<uint16_t>(obj->packInfo->packSize - crcBytes))
{
return 0U;
}
return (obj->packInfo->buffer[obj->addressToOffset] << 8) | obj->packInfo->buffer[obj->addressToOffset + 1];
};
uint8_t BasePack::_getDataSize(BasePack *obj)
{
return obj->packInfo->packSize - crcBytes - obj->DataOffset;
if (obj == nullptr || !obj->checkPacketLayout() ||
obj->packInfo == nullptr || obj->packInfo->buffer == nullptr)
{
return 0U;
}
const uint16_t overhead = static_cast<uint16_t>(obj->DataOffset) + crcBytes;
return static_cast<uint16_t>(obj->packInfo->packSize) > overhead
? static_cast<uint8_t>(static_cast<uint16_t>(obj->packInfo->packSize) - overhead)
: 0U;
};
uint8_t *BasePack::_getDataPrt(BasePack *obj)
{
if (obj == nullptr || !obj->checkPacketLayout() ||
obj->packInfo == nullptr || obj->packInfo->buffer == nullptr ||
obj->packInfo->packSize < crcBytes ||
static_cast<uint16_t>(obj->DataOffset) >
static_cast<uint16_t>(obj->packInfo->packSize - crcBytes))
{
return nullptr;
}
return obj->packInfo->buffer + obj->DataOffset;
};
uint8_t BasePack::_getDataRawSize(BasePack *obj)
{
return obj->packInfo->packSize;
return obj != nullptr && obj->checkPacketLayout() && obj->packInfo != nullptr
? obj->packInfo->packSize
: 0U;
};
bool BasePack::available()
@ -73,6 +125,17 @@ namespace PacketTypes
}
};
bool Data::checkPacketLayout() const
{
if (!BasePack::checkPacketLayout())
{
return false;
}
const uint8_t msgType = (packInfo->buffer[msgOffset] >> 5) & IR_MASK_MSG_TYPE;
return (msgType == IR_MSG_DATA_ACCEPT || msgType == IR_MSG_DATA_NOACCEPT) &&
irproto::isTypedWireSizeValid(msgType, packInfo->packSize);
}
bool Data::checkAddress()
{
bool ret;
@ -80,6 +143,17 @@ namespace PacketTypes
return ret;
}
bool DataBack::checkPacketLayout() const
{
if (!BasePack::checkPacketLayout())
{
return false;
}
const uint8_t msgType = (packInfo->buffer[msgOffset] >> 5) & IR_MASK_MSG_TYPE;
return (msgType == IR_MSG_BACK || msgType == IR_MSG_BACK_TO) &&
irproto::isTypedWireSizeValid(msgType, packInfo->packSize);
}
bool DataBack::checkAddress()
{
bool ret;
@ -96,12 +170,34 @@ namespace PacketTypes
return ret;
}
bool Accept::checkPacketLayout() const
{
if (!BasePack::checkPacketLayout())
{
return false;
}
const uint8_t msgType = (packInfo->buffer[msgOffset] >> 5) & IR_MASK_MSG_TYPE;
return msgType == IR_MSG_ACCEPT &&
irproto::isTypedWireSizeValid(msgType, packInfo->packSize);
}
bool Accept::checkAddress() { return true; }
bool Request::checkPacketLayout() const
{
if (!BasePack::checkPacketLayout())
{
return false;
}
const uint8_t msgType = (packInfo->buffer[msgOffset] >> 5) & IR_MASK_MSG_TYPE;
return msgType == IR_MSG_REQUEST &&
irproto::isTypedWireSizeValid(msgType, packInfo->packSize);
}
bool Request::checkAddress()
{
bool ret;
IR_FOX::checkAddressRuleApply(getAddrTo(), this->id, ret);
return ret;
}
}
}