Skip to content

Fix heap-buffer-overflow in TelnetLayer due to stale offset in getOption/getOptionData (#2144)#2148

Merged
seladb merged 4 commits into
seladb:devfrom
alacrity-aya:fix/telnet-getOption-stale-offset
May 26, 2026
Merged

Fix heap-buffer-overflow in TelnetLayer due to stale offset in getOption/getOptionData (#2144)#2148
seladb merged 4 commits into
seladb:devfrom
alacrity-aya:fix/telnet-getOption-stale-offset

Conversation

@alacrity-aya
Copy link
Copy Markdown
Contributor

Summary

Fixes #2144

This PR fixes a heap-buffer-overflow in TelnetLayer that occurs when
calling getOption(TelnetCommand) or getOptionData(TelnetCommand, size_t&)
on a Telnet packet where user data (escaped IAC FF FF) precedes a command field.

Root Cause

In both getOption(TelnetCommand) and getOptionData(TelnetCommand, size_t&),
the offset variable was calculated before getNextCommandField() advanced
pos, and then used unmodified when computing maxLength for the subsequent
getFieldLen() call:

// Bug: offset is stale after getNextCommandField() advances pos
size_t offset = pos - m_Data;
pos = getNextCommandField(pos, m_DataLen - offset);
if (pos && pos[1] == static_cast<int>(command))
{
    // offset still holds pre-advance value → maxLength too large
    return static_cast<TelnetOption>(getSubCommand(pos, getFieldLen(pos, m_DataLen - offset)));
}

In getOption(TelnetCommand) and getOptionData(TelnetCommand, size_t&),
the 'offset' variable was calculated before getNextCommandField() advanced
'pos', causing a stale value to be used as maxLength in subsequent
getFieldLen() calls. This allowed distanceToNextIAC() to set an endIt
pointer past the end of the allocated buffer, triggering an out-of-bounds
read in std::find() inside findNextIAC().

Fix: recalculate offset from the updated pos after getNextCommandField().

Also fix getOptionData(TelnetCommand, size_t&) which incorrectly used
m_Data instead of pos when extracting field data for the matched command.

Fixes: seladb#2144
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.
@alacrity-aya alacrity-aya requested a review from seladb as a code owner May 25, 2026 02:17
@codecov
Copy link
Copy Markdown

codecov Bot commented May 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.70%. Comparing base (851322b) to head (5d6d463).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #2148      +/-   ##
==========================================
+ Coverage   82.66%   82.70%   +0.04%     
==========================================
  Files         332      332              
  Lines       59736    59746      +10     
  Branches    12392    12332      -60     
==========================================
+ Hits        49378    49412      +34     
+ Misses       9480     8928     -552     
- Partials      878     1406     +528     
Flag Coverage Δ
23.11.6 7.28% <0.00%> (-0.06%) ⬇️
24.11.5 7.31% <0.00%> (-0.02%) ⬇️
25.11.1 7.33% <0.00%> (-0.01%) ⬇️
alpine320 76.81% <100.00%> (+0.04%) ⬆️
fedora42 76.39% <100.00%> (+0.04%) ⬆️
macos-14 82.22% <100.00%> (+0.02%) ⬆️
macos-15 82.21% <100.00%> (+0.03%) ⬆️
mingw32 71.07% <66.66%> (+0.08%) ⬆️
mingw64 71.03% <66.66%> (+0.14%) ⬆️
npcap ?
rhel94 76.20% <100.00%> (+0.04%) ⬆️
ubuntu2204 76.22% <100.00%> (+0.05%) ⬆️
ubuntu2204-icpx 59.35% <100.00%> (+0.10%) ⬆️
ubuntu2404 76.53% <100.00%> (+0.03%) ⬆️
ubuntu2404-arm64 76.50% <100.00%> (+0.04%) ⬆️
ubuntu2604 76.42% <100.00%> (+0.01%) ⬆️
unittest 82.70% <100.00%> (+0.04%) ⬆️
windows-2022 85.77% <100.00%> (+0.18%) ⬆️
windows-2025 85.80% <100.00%> (+0.18%) ⬆️
winpcap 85.80% <100.00%> (-0.01%) ⬇️
xdp 53.08% <100.00%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread Packet++/src/TelnetLayer.cpp Outdated
Comment thread Packet++/src/TelnetLayer.cpp Outdated
Comment thread Tests/Packet++Test/PacketExamples/telnetCommandAfterData.dat
Comment thread Tests/Packet++Test/Tests/TelnetTests.cpp Outdated
Comment thread Tests/Packet++Test/Tests/TelnetTests.cpp Outdated
alacrity-aya added a commit to alacrity-aya/PcapPlusPlus that referenced this pull request May 26, 2026
- Reuse offset in TelnetLayer loops instead of introducing new variables
- Rename regression test to TelentCommandInvalidDataTests
- Use auto* for telnetLayer in test code
- Add telnetCommandAfterData.pcap to PacketExamples for Wireshark inspection
- Reuse offset during Telnet command scans in TelnetLayer
- Rename invalid-data regression test and keep registrations in sync
- Use auto* in Telnet regression test code
- Add telnetCommandAfterData.pcap fixture for easier packet inspection
@alacrity-aya alacrity-aya force-pushed the fix/telnet-getOption-stale-offset branch from 70ac274 to 7eb471e Compare May 26, 2026 07:55
@alacrity-aya
Copy link
Copy Markdown
Contributor Author

@seladb I don't know why ci failed. Can you take a look?

@Dimi1010
Copy link
Copy Markdown
Collaborator

@seladb I don't know why ci failed. Can you take a look?

@alacrity-aya It happens sometimes due to the environment the CI runs on.

@seladb seladb merged commit af83983 into seladb:dev May 26, 2026
78 of 79 checks passed
@seladb
Copy link
Copy Markdown
Owner

seladb commented May 26, 2026

Thank you @alacrity-aya for working on this fix! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants