Skip to content

Commit ec15b24

Browse files
authored
Fix heap-buffer-overflow in IPv4Layer::computeCalculateFields with invalid IHL (#1866) (#2179)
1 parent ead1dc8 commit ec15b24

4 files changed

Lines changed: 36 additions & 5 deletions

File tree

Packet++/src/IPv4Layer.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
#include "IPSecLayer.h"
1212
#include "VrrpLayer.h"
1313
#include "PacketUtils.h"
14-
#include <sstream>
1514
#include "Logger.h"
1615
#include "EndianPortable.h"
16+
#include <sstream>
17+
#include <algorithm>
1718

1819
namespace pcpp
1920
{
@@ -188,9 +189,9 @@ namespace pcpp
188189
// value of totalLen and look at the data captured on the wire
189190
if ((totalLen < m_DataLen) && (totalLen != 0))
190191
{
191-
auto headerLen = getHeaderLen();
192+
auto headerLen = (std::min)(getHeaderLen(), m_DataLen);
192193
// Make sure totalLen is larger than header len, otherwise it's a malformed packet
193-
m_DataLen = totalLen > headerLen ? totalLen : headerLen;
194+
m_DataLen = (std::max)(totalLen, headerLen);
194195
}
195196
}
196197
}
@@ -370,7 +371,7 @@ namespace pcpp
370371

371372
void IPv4Layer::computeCalculateFields()
372373
{
373-
iphdr* ipHdr = getIPv4Header();
374+
auto* ipHdr = getIPv4Header();
374375
ipHdr->ipVersion = (4 & 0x0f);
375376
ipHdr->totalLength = htobe16(m_DataLen);
376377
ipHdr->headerChecksum = 0;
@@ -406,7 +407,8 @@ namespace pcpp
406407
}
407408
}
408409

409-
ScalarBuffer<uint16_t> scalar = { (uint16_t*)ipHdr, (size_t)(ipHdr->internetHeaderLength * 4) };
410+
auto headerLen = (std::min)(static_cast<size_t>(ipHdr->internetHeaderLength * 4), m_DataLen);
411+
ScalarBuffer<uint16_t> scalar = { reinterpret_cast<uint16_t*>(ipHdr), headerLen };
410412
ipHdr->headerChecksum = htobe16(computeChecksum(&scalar, 1));
411413
}
412414

Tests/Packet++Test/TestDefinition.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ PTF_TEST_CASE(IPv4FragmentationTest);
2424
PTF_TEST_CASE(IPv4OptionsParsingTest);
2525
PTF_TEST_CASE(IPv4OptionsEditTest);
2626
PTF_TEST_CASE(IPv4UdpChecksum);
27+
PTF_TEST_CASE(IPv4ComputeFieldsInvalidIhl);
2728

2829
// Implemented in IPv6Tests.cpp
2930
PTF_TEST_CASE(IPv6UdpPacketParseAndCreate);

Tests/Packet++Test/Tests/IPv4Tests.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,30 @@ PTF_TEST_CASE(IPv4UdpChecksum)
528528
PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, packetChecksum, hex);
529529
}
530530
} // Ipv4UdpChecksum
531+
532+
PTF_TEST_CASE(IPv4ComputeFieldsInvalidIhl)
533+
{
534+
uint8_t data[60]{};
535+
536+
data[12] = 0x08;
537+
data[13] = 0x00;
538+
539+
constexpr size_t ipOffset = sizeof(pcpp::ether_header);
540+
data[ipOffset] = 0x4d; // IPv4, IHL = 13 => 52 bytes.
541+
data[ipOffset + 2] = 0x00;
542+
data[ipOffset + 3] = 0x1c; // totalLength = 28.
543+
544+
timeval time{};
545+
pcpp::RawPacket rawPacket(data, sizeof(data), time, false, pcpp::LINKTYPE_ETHERNET);
546+
pcpp::Packet packet(&rawPacket);
547+
548+
auto ipv4Layer = packet.getLayerOfType<pcpp::IPv4Layer>();
549+
PTF_ASSERT_NOT_NULL(ipv4Layer);
550+
PTF_ASSERT_EQUAL(ipv4Layer->getHeaderLen(), 52);
551+
PTF_ASSERT_EQUAL(ipv4Layer->getDataLen(), 46);
552+
PTF_ASSERT_NULL(ipv4Layer->getNextLayer());
553+
554+
packet.computeCalculateFields();
555+
556+
PTF_ASSERT_EQUAL(ipv4Layer->getDataLen(), 46);
557+
} // IPv4ComputeFieldsInvalidIhl

Tests/Packet++Test/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ int main(int argc, char* argv[])
137137
PTF_RUN_TEST(IPv4OptionsParsingTest, "ipv4");
138138
PTF_RUN_TEST(IPv4OptionsEditTest, "ipv4");
139139
PTF_RUN_TEST(IPv4UdpChecksum, "ipv4");
140+
PTF_RUN_TEST(IPv4ComputeFieldsInvalidIhl, "ipv4");
140141

141142
PTF_RUN_TEST(IPv6UdpPacketParseAndCreate, "ipv6");
142143
PTF_RUN_TEST(IPv6FragmentationTest, "ipv6");

0 commit comments

Comments
 (0)