From 5612358c16c33ca45c02c968de1f9b60398011d3 Mon Sep 17 00:00:00 2001 From: 3304711297 <3304711297@qq.com> Date: Tue, 20 Oct 2026 17:18:53 +0800 Subject: [PATCH] fix(tokeer): escape JSON string values in the redeem request body The redeem code is taken verbatim from the bst:// URL and concatenated into a JSON request body without escaping. A value containing a double quote ends the JSON string early and changes the structure of the request, so the value can not be represented correctly. Escape the value per RFC 8259 before embedding it: double quote, backslash and the control characters (using \u00XX for the remaining ones). This is the same shape as the existing hand-rolled JSON helpers in this file. --- src/Utils/Tokeer/TokeerBridge.cpp | 33 ++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/Utils/Tokeer/TokeerBridge.cpp b/src/Utils/Tokeer/TokeerBridge.cpp index e9e73d19..b4b0883e 100644 --- a/src/Utils/Tokeer/TokeerBridge.cpp +++ b/src/Utils/Tokeer/TokeerBridge.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -48,6 +49,36 @@ namespace { return out; } + // Minimal JSON string escaping for a value that is embedded into a request + // body. JSON requires that ", \\ and control characters are escaped; without + // this a bare quote in the value would terminate the string early and change + // the structure of the request. + std::string JsonEscape(std::string_view s) { + std::string out; + out.reserve(s.size() + 8); + for (const char c : s) { + switch (c) { + case '"': out += "\\\""; break; + case '\\': out += "\\\\"; break; + case '\b': out += "\\b"; break; + case '\f': out += "\\f"; break; + case '\n': out += "\\n"; break; + case '\r': out += "\\r"; break; + case '\t': out += "\\t"; break; + default: + if (static_cast(c) < 0x20) { + char buf[7]; + std::snprintf(buf, sizeof(buf), "\\u%04x", + static_cast(c)); + out += buf; + } else { + out += c; + } + } + } + return out; + } + // Minimal "key":"value" string extraction from the server's flat JSON reply. bool JsonString(std::string_view body, std::string_view key, std::string& out) { const std::string needle = "\"" + std::string(key) + "\""; @@ -90,7 +121,7 @@ void Redeem(const std::string& code) { namespace CS = OSTPlatform::SteamCredentialStore; const std::string url = TokeerBaseUrl() + "/drm/redeem"; - const std::string reqBody = "{\"code\":\"" + code + "\"}"; + const std::string reqBody = "{\"code\":\"" + JsonEscape(code) + "\"}"; OSTPlatform::Http::Result r = OSTPlatform::Http::Execute( L"POST", url.c_str(), reqBody.data(), static_cast(reqBody.size()),