[PATCH] bfd: fix filename encoding for Win32

Jan Beulich jbeulich@suse.com
Mon Mar 2 07:36:27 GMT 2026


On 02.03.2026 07:12, ZENG Hao wrote:
> MSVCRT's ___lc_codepage_func() returns "default ACP for Windows display
> language". i.e. 1252 for English, no matter how "Language for non-Unicode
> programs" (system code page) is set, or whether the application manifest sets
> activeCodePage to UTF-8. Thus non-ASCII path would get corrupted if user's
> Windows display language does not match system code page, or downstream adds
> UTF-8 manifest.
> 
> In our use case, the filename is encoded in CP_ACP.
> 
> There are some conner cases that are impossible to handle on our side (read
> from file, console, pipe, socket, etc.). It is possible for downstream
> distributor to ensure all tools are consistently encoded, by removing UTF-8
> manifest from GCC, or adding it to all tools.
> ---
> 
> Note: here are some detailed comparation of MSVCRT and UCRT
> ___lc_codepage_func(): https://github.com/niXman/mingw-builds/issues/649
> 
>  bfd/bfdio.c      | 19 ++++++++++++++-----
>  bfd/config.in    |  4 ----
>  bfd/configure    | 12 ------------
>  bfd/configure.ac |  1 -
>  4 files changed, 14 insertions(+), 22 deletions(-)
> 
> diff --git a/bfd/bfdio.c b/bfd/bfdio.c
> index ea0d1389cd1..2d8d1d90989 100644
> --- a/bfd/bfdio.c
> +++ b/bfd/bfdio.c
> @@ -189,11 +189,20 @@ _bfd_real_fopen (const char *filename, const char *modes)
>      }
>  
>  #ifdef __MINGW32__
> -#if !HAVE_DECL____LC_CODEPAGE_FUNC
> -  /* This prototype was added to locale.h in version 9.0 of MinGW-w64.  */
> -  _CRTIMP unsigned int __cdecl ___lc_codepage_func (void);
> -#endif
> -  const unsigned int cp = ___lc_codepage_func ();
> +  /* The filename is retrieved from argv, Win32 API, CRT function, or files
> +     (incl. console, pipe, socket, etc.).
> +     1) argv is always encoded in ACP.

Aren't there also cases where we read a text-ish file to fetch, among other
things, filenames from it? Their encoding won't necessarily be ACP. That
could easily be UTF-8, for example. IOW ...

> +     2) Win32 file APIs uses ACP or OEMCP, depending on return value of
> +        AreFileApisANSI().
> +     3) UCRT filesystem functions internally converts strings from/to wchar_t
> +        and call wide variants. It uses CP_UTF8 (if C locale set to ".utf8"),
> +        CP_ACP or CP_OEMCP (depending on AreFileApisANSI()).
> +     4) MSVCRT filesystem functions simply pass strings to Win32 file APIs.
> +     5) file can be encoded in any encoding, depending on the writer.
> +
> +     Ignoring case 5, which is impossible to handle, CP_ACP is the only choice
> +     (and don't call SetFileApisToOEM() or setlocale(".utf8")). */
> +  const unsigned int cp = CP_ACP;

... there may not be a single, uniform code page that we can use. Which
effectively looks to mean that case 5 needs handling, one way or another.

Jan


More information about the Binutils mailing list