Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61820 #1234

Merged
merged 9 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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