fix(console): don't coerce quoted or malformed numeric args to JSON numbers

BuildConsoleRpcCall pushed any bare token that "looked numeric" as a JSON
number, and lost the tokenizer's quoting decision — so a genuinely-string
argument that happened to be all digits (e.g. a label) was sent with the wrong
type. std::stoll also silently truncated "1e999" to 1 (stops at the first
non-digit) and std::stod could yield inf/subnormal.

- ParseConsoleCommandArgsTagged returns {text, quoted}; quoted tokens are sent
  verbatim as JSON strings, never coerced. (ParseConsoleCommandArgs kept as a
  text-only wrapper so existing callers/tests are unchanged.)
- Bare tokens become a number only when the WHOLE token parses to a finite
  int/double; otherwise they're sent as a string.

Adds test coverage for quoted-numeric-string, bare-number, 1e999, and 123abc.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-12 17:49:02 -05:00
co-authored by Claude Opus 4.8
parent 4f71c18884
commit 48eceb6593
3 changed files with 76 additions and 19 deletions
+7
View File
@@ -46,6 +46,13 @@ std::string ConsoleHistoryEntry(const std::vector<std::string>& history,
ConsoleCompletionResult CompleteConsoleCommand(const std::string& input);
std::vector<std::string> FormatConsoleCompletionLines(const std::vector<std::string>& matches,
std::size_t maxLineLength = 60);
// A tokenized console argument. `quoted` is true when the token came from a "..."/'...' literal,
// so BuildConsoleRpcCall must send it verbatim as a JSON string (never coerce it to a number/bool).
struct ConsoleArg {
std::string text;
bool quoted = false;
};
std::vector<ConsoleArg> ParseConsoleCommandArgsTagged(const std::string& command);
std::vector<std::string> ParseConsoleCommandArgs(const std::string& command);
ConsoleRpcCall BuildConsoleRpcCall(const std::string& command);
std::vector<ConsoleResultLine> FormatConsoleRpcResultLines(const std::string& result,