Parse remote protocol integers without throwing - #1166
Conversation
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>
|
Why is it ok for all these sites to just default to |
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? |
|
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>
f7a1961 to
3594088
Compare
|
Approved via in-person conversation. Effort to properly handle this with exception is tracked in #1176 |
Add
RspConnector::ParseInt(based onstd::from_chars) and use it instead ofstd::stoi/stoullwhen parsing data from the remote debug stub, so malformed packets can no longer crash the process. Also guard short-packetsubstr/index accesses inPacketToUnorderedMap.Also fixes multiprocess thread ids, which never parsed:
Splittakes a regex, so the"."separator matched every character and produced only empty tokens, and apPID.TIDthread id always reached the parser as an empty string.On the zero fallback
An earlier revision of this PR made
ParseIntthrow a typedRspProtocolErrorand ended the session at a catch boundary inDebuggerController, on the grounds that defaulting to0lets 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 thanExecuteAdapterAndWait, real transport teardown rather than a syntheticTargetExited, 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::ReadMemorycall sites, is tracked in #1176.Fixes #1164
Refs #1176