Skip to content

Parse remote protocol integers without throwing - #1166

Merged
xusheng6 merged 2 commits into
devfrom
test_safe_int_parsing
Aug 13, 2026
Merged

Parse remote protocol integers without throwing#1166
xusheng6 merged 2 commits into
devfrom
test_safe_int_parsing

Conversation

@xusheng6

@xusheng6 xusheng6 commented Aug 3, 2026

Copy link
Copy Markdown
Member

Add RspConnector::ParseInt (based on std::from_chars) and use it instead of std::stoi/stoull when parsing data from the remote debug stub, so malformed packets can no longer crash the process. Also guard short-packet substr/index accesses in PacketToUnorderedMap.

Also fixes multiprocess thread ids, which never parsed: Split takes a regex, so the "." separator matched every character and produced only empty tokens, and a pPID.TID thread id always reached the parser as an empty string.

On the zero fallback

An earlier revision of this PR made ParseInt throw a typed RspProtocolError and ended the session at a catch boundary in DebuggerController, on the grounds that defaulting to 0 lets a corrupt packet silently become a valid-looking answer. Thanks to @plafosse for the detailed review of that revision — it showed the change needed considerably more than a parsing fix to be correct: a catch boundary wider than ExecuteAdapterAndWait, real transport teardown rather than a synthetic TargetExited, RAII on the adapter-stop channel, and ignoring unrecognized stop-reply fields so that spec-conforming stubs (replaylog, exec, fork/vfork) cannot terminate a session.

That is the right end state, but it is not a feature-freeze change. This PR is therefore scoped to the crash in #1164 and keeps the non-throwing fallback. The proper handling, along with the review points and the remaining esrevenadapter.cpp / GdbMiAdapter::ReadMemory call sites, is tracked in #1176.

Fixes #1164
Refs #1176

std::stoi/stol/stoull raise std::invalid_argument or std::out_of_range
on malformed input. The RSP/GDB adapters called them directly on data
received from the remote debug stub, so a malformed packet could crash
the process with an uncaught exception. Add RspConnector::ParseInt, a
std::from_chars-based helper that returns a fallback value instead, and
use it at all unguarded call sites. Also guard the packet substr/index
accesses in PacketToUnorderedMap against short packets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@xusheng6
xusheng6 requested a review from plafosse August 3, 2026 18:44
@plafosse

plafosse commented Aug 3, 2026

Copy link
Copy Markdown
Member

Why is it ok for all these sites to just default to 0 on failure? Seems like some errors should be raised or warnings displayed when the failure conditions occur?

@xusheng6

xusheng6 commented Aug 3, 2026

Copy link
Copy Markdown
Member Author

Why is it ok for all these sites to just default to 0 on failure? Seems like some errors should be raised or warnings displayed when the failure conditions occur?

Usually when this happens, the communication already deviated from the expected way in an irrecoverable way (e.g., the GDB stub and our adapter has a different assumption of the RSP protocol), so the actual value does not matter as long we we do not crash ourselves.

I think we can add a warning when this happens so as to assist troubleshooting, do you want that to be done?

@plafosse

plafosse commented Aug 4, 2026

Copy link
Copy Markdown
Member

This kind feels like the opposite of what you should be doing. It seems like instead of just silently accepting corrupted rsp messages you need to throw and exception and you just need to have a more principled approach to what you do when this occurs. So instead of preventing exceptions you just need to catch them in the correct locations so you can do proper teardown.

@xusheng6

Copy link
Copy Markdown
Member Author

This kind feels like the opposite of what you should be doing. It seems like instead of just silently accepting corrupted rsp messages you need to throw and exception and you just need to have a more principled approach to what you do when this occurs. So instead of preventing exceptions you just need to catch them in the correct locations so you can do proper teardown.

I made the code to throw RspProtocolError with an explanation of the error. When the exception is caught and handled, the debugging is gracefully stopped and an LogError is used to communicate the error to the user

Would you please have a look at it again? @plafosse

Split takes a regex, so the "." separator matched every character and
produced only empty tokens. A "pPID.TID" thread id therefore always
reached the parser as an empty string, so the thread id was never read.
Escape it to "\\.", and guard the value[0] access for an empty value.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@xusheng6

xusheng6 commented Aug 13, 2026

Copy link
Copy Markdown
Member Author

Approved via in-person conversation. Effort to properly handle this with exception is tracked in #1176

@xusheng6
xusheng6 merged commit 295e077 into dev Aug 13, 2026
1 of 2 checks passed
@xusheng6
xusheng6 deleted the test_safe_int_parsing branch August 13, 2026 21:37
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.

Malformed remote stub data can crash via unguarded std::stoi/stoull

2 participants