The remaining std::stoi() call sites in the user-mode helpers throw on
malformed and out-of-range input. None of the callers catch, and there is
no top-level handler, so a bad command argument terminates the process
instead of being rejected with an error message.
common/common.cpp:
- IsNumber() tested against the character set "[0123456789]", so the two
square brackets were accepted as digits. It is used as the guard in
front of stoi() by several callers, which turns the mistake into a
crash: "[1]" passes validation and then throws std::invalid_argument.
Removed the brackets from the set.
- ValidateIP() called stoi() on every octet. Together with the above,
".connect [1].2.3.4 50000" aborted the process; so did an octet long
enough to overflow int, e.g. ".connect 99999999999.1.1.1". Replaced by
a strtoul() range check, which saturates instead of throwing.
- CheckAddressCanonicality() compared with a strict "<" against the start
of the higher-half canonical range, so the boundary address itself
(0xFFFF800000000000 at a 48-bit VA width) was reported as user-mode.
CheckAccessValidityAndSafety() would then probe a kernel address from
user mode rather than refusing it.
- ListDirectory() called FindNextFileA() before consuming the match that
FindFirstFileA() had already stored in FindData, so the first file of
every listing was silently dropped. Turned into a do/while.
- isxdigit()/isdigit()/isspace() were handed a plain char; passing a
negative value to the <ctype.h> functions is undefined behavior and
trips the MSVC debug CRT on any input with a byte above 0x7f. Cast to
UCHAR at the four call sites.
The same crash class at the call sites that use stoi() directly on user
input, all replaced with strtoul() so the existing range checks reject
the value instead of an exception escaping:
- connect.cpp (x2) and listen.cpp: TCP port validation.
- debug.cpp: serial baud rate.
Verified by extracting the affected functions from common.cpp and running
them under ASan/UBSan over a 316-probe corpus, before and after. The
baseline aborts with SIGABRT on three inputs; afterwards every probe
returns a defined result and exactly the seven intended lines differ.
The four modified files were also compiled with the project's own Linux
CMake build to confirm they build clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W3C1DuhHtqK64eEkHjKCHM