@@ -255,6 +255,40 @@ PTF_TEST_CASE(TelnetCommandParsingTests)
255255 }
256256}
257257
258+ PTF_TEST_CASE (TelentCommandInvalidDataTests)
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+ auto * 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+ auto * 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+
258292PTF_TEST_CASE (TelnetDataParsingTests)
259293{
260294
0 commit comments