Skip to content

Commit 96ba779

Browse files
committed
Add regression test for TelnetLayer stale offset heap-buffer-overflow
Test TelnetCommandAfterDataParsingTests verifies that getOption(TelnetCommand) and getOptionData(TelnetCommand, size_t&) work correctly when user data (escaped IAC) precedes a command field, which previously caused a heap-buffer-overflow due to stale offset calculation.
1 parent ad19b26 commit 96ba779

4 files changed

Lines changed: 37 additions & 0 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
00112233445566778899aabb08004500002e1234400040060000c0a80a01c0a80a0200173039000000000000000050187fff00000000fffffffa1700

Tests/Packet++Test/TestDefinition.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ PTF_TEST_CASE(NtpCreationTests);
236236

237237
// Implemented in TelnetTests.cpp
238238
PTF_TEST_CASE(TelnetCommandParsingTests);
239+
PTF_TEST_CASE(TelnetCommandAfterDataParsingTests);
239240
PTF_TEST_CASE(TelnetDataParsingTests);
240241

241242
// Implemented in IcmpV6Tests.cpp

Tests/Packet++Test/Tests/TelnetTests.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,40 @@ PTF_TEST_CASE(TelnetCommandParsingTests)
255255
}
256256
}
257257

258+
PTF_TEST_CASE(TelnetCommandAfterDataParsingTests)
259+
{
260+
// Regression test for heap-buffer-overflow in getOption(TelnetCommand) / getOptionData(TelnetCommand, size_t&)
261+
// when user data (escaped IAC) precedes a command. The stale offset bug caused reads past the buffer end.
262+
// Payload: FF FF (escaped IAC = user data) + FF FA 17 00 (IAC SB SendLocation 0x00)
263+
auto rawPacket1 = createPacketFromHexResource("PacketExamples/telnetCommandAfterData.dat");
264+
265+
pcpp::Packet telnetPacket(rawPacket1.get());
266+
pcpp::TelnetLayer* telnetLayer = telnetPacket.getLayerOfType<pcpp::TelnetLayer>();
267+
268+
PTF_ASSERT_NOT_NULL(telnetLayer);
269+
270+
// Total commands: 1 (the subnegotiation)
271+
PTF_ASSERT_EQUAL(telnetLayer->getTotalNumberOfCommands(), 1);
272+
273+
// getFirstCommand should find the subnegotiation
274+
PTF_ASSERT_EQUAL(telnetLayer->getFirstCommand(), pcpp::TelnetLayer::TelnetCommand::Subnegotiation, enumclass);
275+
276+
// getOption(Subnegotiation) should return SendLocation without crashing
277+
PTF_ASSERT_EQUAL(telnetLayer->getOption(pcpp::TelnetLayer::TelnetCommand::Subnegotiation),
278+
pcpp::TelnetLayer::TelnetOption::SendLocation, enumclass);
279+
280+
// getOptionData(Subnegotiation) should return the subneg data without crashing
281+
size_t length = 0;
282+
uint8_t* optData = telnetLayer->getOptionData(pcpp::TelnetLayer::TelnetCommand::Subnegotiation, length);
283+
PTF_ASSERT_NOT_NULL(optData);
284+
PTF_ASSERT_EQUAL(length, 1);
285+
PTF_ASSERT_EQUAL(optData[0], 0x00);
286+
287+
// getOption for a command that doesn't exist should return NoOption without crashing
288+
PTF_ASSERT_EQUAL(telnetLayer->getOption(pcpp::TelnetLayer::TelnetCommand::WillPerform),
289+
pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption, enumclass);
290+
}
291+
258292
PTF_TEST_CASE(TelnetDataParsingTests)
259293
{
260294

Tests/Packet++Test/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ int main(int argc, char* argv[])
325325
PTF_RUN_TEST(NtpCreationTests, "ntp");
326326

327327
PTF_RUN_TEST(TelnetCommandParsingTests, "telnet");
328+
PTF_RUN_TEST(TelnetCommandAfterDataParsingTests, "telnet");
328329
PTF_RUN_TEST(TelnetDataParsingTests, "telnet");
329330

330331
PTF_RUN_TEST(TpktLayerTest, "tpkt");

0 commit comments

Comments
 (0)