Skip to content

Commit

Permalink
Fix oss-fuzz issue 61820 (#1234)
Browse files Browse the repository at this point in the history
  • Loading branch information
sashashura authored Nov 22, 2023
1 parent 6a5cb61 commit f112d0a
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 11 deletions.
20 changes: 20 additions & 0 deletions Packet++/header/DhcpLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,26 @@ namespace pcpp
memcpy(m_Data->recordValue + valueOffset, stringValue.data(), len);
}

/**
* Check if a pointer can be assigned to the TLV record data
* @param[in] recordRawData A pointer to the TLV record raw data
* @param[in] tlvDataLen The size of the TLV record raw data
* @return True if data is valid and can be assigned
*/
static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen)
{
auto data = (TLVRawData*)recordRawData;
if (data == nullptr)
return false;

if (tlvDataLen < sizeof(TLVRawData::recordType))
return false;

if (data->recordType == (uint8_t)DHCPOPT_END || data->recordType == (uint8_t)DHCPOPT_PAD)
return true;

return TLVRecord<uint8_t, uint8_t>::canAssign(recordRawData, tlvDataLen);
}

// implement abstract methods

Expand Down
37 changes: 33 additions & 4 deletions Packet++/header/IPv4Layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,29 @@ namespace pcpp
*/
IPv4OptionTypes getIPv4OptionType() const
{
if (m_Data == nullptr)
return IPV4OPT_Unknown;

return (IPv4OptionTypes)m_Data->recordType;
return getIPv4OptionType(m_Data);
}

/**
* Check if a pointer can be assigned to the TLV record data
* @param[in] recordRawData A pointer to the TLV record raw data
* @param[in] tlvDataLen The size of the TLV record raw data
* @return True if data is valid and can be assigned
*/
static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen)
{
auto data = (TLVRawData*)recordRawData;
if (data == nullptr)
return false;

if (tlvDataLen < sizeof(TLVRawData::recordType))
return false;

if (getIPv4OptionType(data) == (uint8_t)IPV4OPT_EndOfOptionsList || data->recordType == (uint8_t)IPV4OPT_NOP)
return true;

return TLVRecord<uint8_t, uint8_t>::canAssign(recordRawData, tlvDataLen);
}

// implement abstract methods

Expand All @@ -343,6 +360,18 @@ namespace pcpp

return (size_t)m_Data->recordLen - (2*sizeof(uint8_t));
}

private:
/**
* @return IPv4 option type casted as pcpp::IPv4OptionTypes enum
*/
static IPv4OptionTypes getIPv4OptionType(const TLVRawData* data)
{
if (data == nullptr)
return IPV4OPT_Unknown;

return (IPv4OptionTypes)data->recordType;
}
};


Expand Down
21 changes: 21 additions & 0 deletions Packet++/header/IPv6Extensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,27 @@ namespace pcpp
*/
~IPv6Option() { }

/**
* Check if a pointer can be assigned to the TLV record data
* @param[in] recordRawData A pointer to the TLV record raw data
* @param[in] tlvDataLen The size of the TLV record raw data
* @return True if data is valid and can be assigned
*/
static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen)
{
auto data = (TLVRawData*)recordRawData;
if (data == nullptr)
return false;

if (tlvDataLen < sizeof(TLVRawData::recordType))
return false;

if (data->recordType == Pad0OptionType)
return true;

return TLVRecord<uint8_t, uint8_t>::canAssign(recordRawData, tlvDataLen);
}

// implement abstract methods

size_t getTotalSize() const
Expand Down
11 changes: 11 additions & 0 deletions Packet++/header/NflogLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ namespace pcpp
m_Data = (NflogTLVRawData*)recordRawData;
}

/**
* Check if a pointer can be assigned to the TLV record data
* @param[in] recordRawData A pointer to the TLV record raw data
* @param[in] tlvDataLen The size of the TLV record raw data
* * @return True if data is valid and can be assigned
*/
static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen)
{
return recordRawData != nullptr && tlvDataLen >= sizeof(NflogTLVRawData::recordLen);
}

/**
* @return True if the TLV record raw data is nullptr, false otherwise
*/
Expand Down
34 changes: 28 additions & 6 deletions Packet++/header/TLVData.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,18 @@ namespace pcpp
*/
void assign(uint8_t* recordRawData)
{
if(recordRawData == NULL)
m_Data = NULL;
else
m_Data = (TLVRawData*)recordRawData;
m_Data = (TLVRawData*)recordRawData;
}

/**
* Check if a pointer can be assigned to the TLV record data
* @param[in] recordRawData A pointer to the TLV record raw data
* @param[in] tlvDataLen The size of the TLV record raw data
* @return True if data is valid and can be assigned
*/
static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen)
{
return recordRawData != nullptr && tlvDataLen >= (sizeof(TLVRawData::recordType) + sizeof(TLVRawData::recordLen));
}

/**
Expand Down Expand Up @@ -155,7 +163,14 @@ namespace pcpp
/**
* Free the memory of the TLV record raw data
*/
void purgeRecordData() { if (!isNull()) delete [] m_Data; }
void purgeRecordData()
{
if (!isNull())
{
delete [] m_Data;
m_Data = nullptr;
}
}

/**
* A templated method to retrieve the record data as a certain type T. For example, if record data is 4B long
Expand Down Expand Up @@ -259,8 +274,11 @@ namespace pcpp
*/
TLVRecordType getFirstTLVRecord(uint8_t* tlvDataBasePtr, size_t tlvDataLen) const
{
TLVRecordType resRec(tlvDataBasePtr); // for NRVO optimization
TLVRecordType resRec(NULL); // for NRVO optimization
if (!TLVRecordType::canAssign(tlvDataBasePtr, tlvDataLen))
return resRec;

resRec.assign(tlvDataBasePtr);
// resRec pointer is out-bounds of the TLV records memory
if (resRec.getRecordBasePtr() + resRec.getTotalSize() > tlvDataBasePtr + tlvDataLen)
resRec.assign(NULL);
Expand Down Expand Up @@ -288,7 +306,11 @@ namespace pcpp
if (record.isNull())
return resRec;

if (!TLVRecordType::canAssign(record.getRecordBasePtr() + record.getTotalSize(), tlvDataBasePtr - record.getRecordBasePtr() + tlvDataLen - record.getTotalSize()))
return resRec;

resRec.assign(record.getRecordBasePtr() + record.getTotalSize());

if (resRec.getTotalSize() == 0)
resRec.assign(NULL);

Expand Down
21 changes: 21 additions & 0 deletions Packet++/header/TcpLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,27 @@ namespace pcpp
return (TcpOptionType)m_Data->recordType;
}

/**
* Check if a pointer can be assigned to the TLV record data
* @param[in] recordRawData A pointer to the TLV record raw data
* @param[in] tlvDataLen The size of the TLV record raw data
* @return True if data is valid and can be assigned
*/
static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen)
{
auto data = (TLVRawData*)recordRawData;
if (data == nullptr)
return false;

if (tlvDataLen < sizeof(TLVRawData::recordType))
return false;

if (data->recordType == (uint8_t)PCPP_TCPOPT_NOP || data->recordType == (uint8_t)PCPP_TCPOPT_EOL)
return true;

return TLVRecord<uint8_t, uint8_t>::canAssign(recordRawData, tlvDataLen);
}

// implement abstract methods

size_t getTotalSize() const
Expand Down
2 changes: 1 addition & 1 deletion Packet++/src/NflogLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ size_t NflogLayer::getHeaderLen() const
headerLen += currentTLV.getTotalSize();
currentTLV = m_TlvReader.getNextTLVRecord(currentTLV, getTlvsBasePtr(), m_DataLen - sizeof(nflog_header));
}
if (currentTLV.getType() == static_cast<uint16_t> (NflogTlvType::NFULA_PAYLOAD))
if (!currentTLV.isNull() && currentTLV.getType() == static_cast<uint16_t> (NflogTlvType::NFULA_PAYLOAD))
{
// for the length and type of the payload TLV
headerLen += 2 * sizeof (uint16_t);
Expand Down

0 comments on commit f112d0a

Please sign in to comment.