cmake: Set process code page to UTF-8 on Windows
What changed, and why it matters
This commit changes how Bitcoin Core handles text encoding on Windows. It tells Windows programs to use UTF-8 (a universal character encoding) instead of older regional code pages, and adds the same declaration to several helper programs that were missing it. It also makes the main bitcoin program run a setup routine that was previously only used by other entry points. The change is primarily a robustness/correctness fix; it does not by itself create a vulnerability, but it removes a class of bugs where non-English characters in file paths, command-line arguments, or log messages could be misinterpreted. Those misinterpretations could, in some situations, contribute to security-relevant behavior such as wrong file access or corrupted data.
Treat as a hardening/correctness improvement rather than an active vulnerability. Review whether any existing Windows-specific code assumes the legacy ANSI code page, because UTF-8 mode can change behavior of MultiByteToWideChar, std::filesystem paths, and console output. Ensure CI tests Windows builds with non-ASCII paths and arguments. No urgent patch or advisory is indicated by the diff alone.
Security signals we found
Windows code-page mismatch historically causes path/argument encoding bugs
Adds assert that could abort on misconfigured builds, reducing silent failure modes
Expands manifest coverage to auxiliary binaries, reducing inconsistency
No direct memory-safety, cryptographic, or network flaw visible in diff
Evidence from the diff
The patch updates cmake/windows-app.manifest.in to add an activeCodePage UTF-8 directive under the SMI 2019 namespace, forcing the process code page to UTF-8 on modern Windows. It also calls add_windows_application_manifest() for bitcoin-chainstate, bench_bitcoin, test_bitcoin-qt, and fuzz, which previously lacked manifests. In src/bitcoin.cpp, SetupEnvironment() is now invoked at program start. In src/common/system.cpp, SetupEnvironment() gains an assert(GetACP() == CP_UTF8) on Windows before setting console input/output code pages to UTF-8. The assert will abort debug builds if the manifest did not take effect, making the dependency explicit.
Changed components
Windows build manifests (cmake/windows-app.manifest.in)src/bitcoin.cpp main entry pointsrc/common/system.cpp SetupEnvironment()bitcoin-chainstate, bench_bitcoin, test_bitcoin-qt, fuzz Windows executablesInspect captured patch +19 / −1
diff --git a/cmake/windows-app.manifest.in b/cmake/windows-app.manifest.in
index c3bd333a..e0dc2eb8 100644
--- a/cmake/windows-app.manifest.in
+++ b/cmake/windows-app.manifest.in
@@ -1,10 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity
type="win32"
name="org.bitcoincore.${target}"
version="${CLIENT_VERSION_MAJOR}.${CLIENT_VERSION_MINOR}.${CLIENT_VERSION_BUILD}.0"
/>
+ <asmv3:application>
+ <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">
+ <activeCodePage>UTF-8</activeCodePage>
+ </asmv3:windowsSettings>
+ </asmv3:application>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f9934bb5..fdf8799d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -410,6 +410,7 @@ if(BUILD_UTIL_CHAINSTATE)
add_executable(bitcoin-chainstate
bitcoin-chainstate.cpp
)
+ add_windows_application_manifest(bitcoin-chainstate)
# TODO: The `SKIP_BUILD_RPATH` property setting can be deleted
# in the future after reordering Guix script commands to
# perform binary checks after the installation step.
diff --git a/src/bench/CMakeLists.txt b/src/bench/CMakeLists.txt
index 0bf469c7..e0e03b1d 100644
--- a/src/bench/CMakeLists.txt
+++ b/src/bench/CMakeLists.txt
@@ -56,6 +56,8 @@ add_executable(bench_bitcoin
verify_script.cpp
)
+add_windows_application_manifest(bench_bitcoin)
+
include(TargetDataSources)
target_raw_data_sources(bench_bitcoin NAMESPACE benchmark::data
data/block413567.raw
diff --git a/src/bitcoin.cpp b/src/bitcoin.cpp
index c1a5fce3..5d2b145b 100644
--- a/src/bitcoin.cpp
+++ b/src/bitcoin.cpp
@@ -6,6 +6,7 @@
#include <clientversion.h>
#include <common/args.h>
+#include <common/system.h>
#include <util/fs.h>
#include <util/exec.h>
#include <util/strencodings.h>
@@ -61,6 +62,8 @@ static void ExecCommand(const std::vector<const char*>& args, std::string_view a
int main(int argc, char* argv[])
{
+ SetupEnvironment();
+
try {
CommandLine cmd{ParseCommandLine(argc, argv)};
if (cmd.show_version) {
diff --git a/src/common/system.cpp b/src/common/system.cpp
index 35a6f441..38337633 100644
--- a/src/common/system.cpp
+++ b/src/common/system.cpp
@@ -12,6 +12,7 @@
#include <util/time.h>
#ifdef WIN32
+#include <cassert>
#include <codecvt>
#include <compat/compat.h>
#include <windows.h>
@@ -83,6 +84,7 @@ void SetupEnvironment()
setenv("LC_ALL", "C.UTF-8", 1);
}
#elif defined(WIN32)
+ assert(GetACP() == CP_UTF8);
// Set the default input/output charset is utf-8
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
diff --git a/src/qt/test/CMakeLists.txt b/src/qt/test/CMakeLists.txt
index 8fe4ea68..af282713 100644
--- a/src/qt/test/CMakeLists.txt
+++ b/src/qt/test/CMakeLists.txt
@@ -14,6 +14,8 @@ add_executable(test_bitcoin-qt
../../init/bitcoin-qt.cpp
)
+add_windows_application_manifest(test_bitcoin-qt)
+
target_link_libraries(test_bitcoin-qt
core_interface
bitcoinqt
diff --git a/src/test/fuzz/CMakeLists.txt b/src/test/fuzz/CMakeLists.txt
index 4d649a73..d32d72d8 100644
--- a/src/test/fuzz/CMakeLists.txt
+++ b/src/test/fuzz/CMakeLists.txt
@@ -134,6 +134,9 @@ add_executable(fuzz
vecdeque.cpp
versionbits.cpp
)
+
+add_windows_application_manifest(fuzz)
+
target_link_libraries(fuzz
core_interface
fuzzer_interface
Why this scored 32/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.