Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions src/nvhttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,15 @@ namespace nvhttp {
save_state() {
pt::ptree root;

if (fs::exists(config::nvhttp.file_state)) {
fs::path state_path(config::nvhttp.file_state);
if (fs::exists(state_path)) {
try {
pt::read_json(config::nvhttp.file_state, root);
std::ifstream ifs(state_path);
if (!ifs.is_open()) {
BOOST_LOG(error) << "Couldn't open "sv << config::nvhttp.file_state << " for reading";
return;
}
pt::read_json(ifs, root);
}
catch (std::exception &e) {
BOOST_LOG(error) << "Couldn't read "sv << config::nvhttp.file_state << ": "sv << e.what();
Expand All @@ -339,7 +345,12 @@ namespace nvhttp {
root.add_child("root.named_devices"s, named_cert_nodes);

try {
pt::write_json(config::nvhttp.file_state, root);
std::ofstream ofs(state_path);
if (!ofs.is_open()) {
BOOST_LOG(error) << "Couldn't open "sv << config::nvhttp.file_state << " for writing";
return;
}
pt::write_json(ofs, root);
}
catch (std::exception &e) {
BOOST_LOG(error) << "Couldn't write "sv << config::nvhttp.file_state << ": "sv << e.what();
Expand All @@ -349,15 +360,22 @@ namespace nvhttp {

void
load_state() {
if (!fs::exists(config::nvhttp.file_state)) {
fs::path state_path(config::nvhttp.file_state);
if (!fs::exists(state_path)) {
BOOST_LOG(debug) << "File "sv << config::nvhttp.file_state << " doesn't exist"sv;
http::unique_id = uuid_util::uuid_t::generate().string();
return;
}

pt::ptree tree;
try {
pt::read_json(config::nvhttp.file_state, tree);
std::ifstream ifs(state_path);
if (!ifs.is_open()) {
BOOST_LOG(error) << "Couldn't open "sv << config::nvhttp.file_state << " for reading";
http::unique_id = uuid_util::uuid_t::generate().string();
return;
}
pt::read_json(ifs, tree);
}
catch (std::exception &e) {
BOOST_LOG(error) << "Couldn't read "sv << config::nvhttp.file_state << ": "sv << e.what();
Expand Down
3 changes: 3 additions & 0 deletions src/platform/windows/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1287,6 +1287,9 @@ namespace platf {

int chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8, size, wide, size);
if (chars <= 0) {
auto winerr = GetLastError();
BOOST_LOG(warning) << "unicode(): MultiByteToWideChar failed, error=" << winerr
<< ", size=" << size;
return;
}

Expand Down
34 changes: 30 additions & 4 deletions src/platform/windows/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,7 @@ namespace platf {
*/
bp::child
run_command(bool elevated, bool interactive, const std::string &cmd, boost::filesystem::path &working_dir, const bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) {
std::wstring start_dir = from_utf8(working_dir.string());
std::wstring start_dir = working_dir.wstring();
HANDLE job = group ? group->native_handle() : nullptr;
STARTUPINFOEXW startup_info = create_startup_info(file, job ? &job : nullptr, ec);
PROCESS_INFORMATION process_info;
Expand Down Expand Up @@ -2012,12 +2012,38 @@ namespace platf {
return {};
}

// Get the output size required to store the string
// Get the output size required to store the string (strict UTF-8 validation)
auto output_size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, string.data(), string.size(), nullptr, 0);
if (output_size == 0) {
auto winerr = GetLastError();
BOOST_LOG(error) << "Failed to get UTF-16 buffer size: "sv << winerr;
return {};

// Log hex dump of the first bytes to help diagnose the invalid string
std::ostringstream hex_dump;
auto dump_len = std::min<size_t>(string.size(), 64);
for (size_t i = 0; i < dump_len; i++) {
hex_dump << std::hex << std::setfill('0') << std::setw(2)
<< (static_cast<unsigned>(string[i]) & 0xFF);
if (i + 1 < dump_len) hex_dump << ' ';
}
BOOST_LOG(error) << "Failed to get UTF-16 buffer size: "sv << winerr
<< " (len=" << string.size()
<< ", hex=[" << hex_dump.str() << "]"
<< ", str=\"" << string.substr(0, 64) << "\")";
Comment on lines +2019 to +2031
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

诊断日志可能泄露敏感信息。

记录输入字符串的十六进制转储和预览对于调试编码问题很有帮助,但需要注意:如果输入包含敏感数据(如路径中的用户名、密码或其他 PII),这些信息可能会被写入日志文件。

建议将日志级别从 error 降为 debug,或者仅在调试模式下输出完整内容:

💡 建议的改进
-      BOOST_LOG(error) << "Failed to get UTF-16 buffer size: "sv << winerr
+      BOOST_LOG(debug) << "Failed to get UTF-16 buffer size: "sv << winerr
                        << " (len=" << string.size()
                        << ", hex=[" << hex_dump.str() << "]"
                        << ", str=\"" << string.substr(0, 64) << "\")";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Log hex dump of the first bytes to help diagnose the invalid string
std::ostringstream hex_dump;
auto dump_len = std::min<size_t>(string.size(), 64);
for (size_t i = 0; i < dump_len; i++) {
hex_dump << std::hex << std::setfill('0') << std::setw(2)
<< (static_cast<unsigned>(string[i]) & 0xFF);
if (i + 1 < dump_len) hex_dump << ' ';
}
BOOST_LOG(error) << "Failed to get UTF-16 buffer size: "sv << winerr
<< " (len=" << string.size()
<< ", hex=[" << hex_dump.str() << "]"
<< ", str=\"" << string.substr(0, 64) << "\")";
// Log hex dump of the first bytes to help diagnose the invalid string
std::ostringstream hex_dump;
auto dump_len = std::min<size_t>(string.size(), 64);
for (size_t i = 0; i < dump_len; i++) {
hex_dump << std::hex << std::setfill('0') << std::setw(2)
<< (static_cast<unsigned>(string[i]) & 0xFF);
if (i + 1 < dump_len) hex_dump << ' ';
}
BOOST_LOG(debug) << "Failed to get UTF-16 buffer size: "sv << winerr
<< " (len=" << string.size()
<< ", hex=[" << hex_dump.str() << "]"
<< ", str=\"" << string.substr(0, 64) << "\")";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/windows/misc.cpp` around lines 2019 - 2031, The diagnostic log
currently writes potentially sensitive data (hex_dump, string.substr) at error
level using BOOST_LOG(error); change this to avoid leaking PII by either
lowering the log severity (e.g., use BOOST_LOG(debug) instead of
BOOST_LOG(error)) or gate the detailed output behind a debug/diagnostic flag
(check a runtime isDebug/isDiagnosticEnabled boolean) so that hex_dump, dump_len
and string preview are only emitted when debugging is enabled; keep the
surrounding message (winerr, string.size()) but ensure detailed hex_dump and
substring are suppressed at error level.


// Fallback: try converting from the system's default ANSI code page (e.g. GBK on Chinese Windows)
output_size = MultiByteToWideChar(CP_ACP, 0, string.data(), string.size(), nullptr, 0);
if (output_size == 0) {
BOOST_LOG(error) << "Fallback ANSI conversion also failed: "sv << GetLastError();
return {};
}
BOOST_LOG(warning) << "from_utf8: falling back to ANSI code page conversion for non-UTF-8 string";

std::wstring output(output_size, L'\0');
output_size = MultiByteToWideChar(CP_ACP, 0, string.data(), string.size(), output.data(), output.size());
if (output_size == 0) {
return {};
}
return output;
}

// Perform the conversion
Expand Down
Loading