`process.execPath` uses the ANSI API on Windows, so non-ASCII paths are garbled when the ANSI code page is not UTF-8

Aperta Adatta ai principianti
#2,910 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
Mezza giornata
Idoneità per principianti
72/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
c, typescript

Direzione di ricerca

Inizia da scr_process_exec_path() in packages/runtime/src/scr_lib.c (intorno alla riga 761) e confrontala con scr_process_cwd() nello stesso file, che usa già l'API a caratteri wide e scr_fs_win_utf8(). La modifica consiste nel passare il ramo Windows a GetModuleFileNameW, convertire il risultato in UTF-8 e mantenere il fallback esistente su argv[0]. È completato quando un percorso di eseguibile con caratteri non ASCII viene restituito correttamente in una build Windows CP932, il che richiede una build cross come SCRIPTC_BUILD_CROSS=1 con SCRIPTC_TARGET=x86_64-windows-gnu.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

English is translated from the Japanese original below.

Checked against main at 0db50d64b (v0.4.7-578).

Summary

In executables built for Windows, process.execPath is garbled when the path contains non-ASCII characters and the ANSI code page is not UTF-8 (for example CP932, the default on Japanese Windows).

scr_process_exec_path() (packages/runtime/src/scr_lib.c, L761) reads the path with GetModuleFileNameA and stores the bytes in the system code page as UTF-8. Elsewhere in the same file, such as scr_process_cwd(), paths go through a Unicode API and scr_fs_win_utf8(). execPath is the one place that was missed.

The garbled value also reaches child processes. The Windows arm of fork() (scr_child.c, L2476) and scr_node_island.c (L184, L678) pass scr_process_exec_path() to the spawn code, which treats it as UTF-8 and converts it for CreateProcessW. On a CP932 machine, child_process.fork() from an executable in a path with Japanese characters should therefore fail to find the executable. I haven't verified the fork() failure on a real machine.

Observed

  • Windows with the ANSI code page set to UTF-8: not garbled.
  • Windows with CP932: garbled when the executable's path contains Japanese characters.
  • An executable built with the runtime fix below returns the path correctly on a real CP932 machine. It was cross-built from Linux with SCRIPTC_BUILD_CROSS=1 and Zig 0.16.0.

Environment: SCRIPTC_TARGET=x86_64-windows-gnu

Proposed fix

Make the Windows side of scr_process_exec_path() work like scr_process_cwd(): get the path with GetModuleFileNameW and convert it with scr_fs_win_utf8(). The result is already absolute, so it skips the ANSI _fullpath call. A failure, or a path that doesn't fit in 4096 characters, falls through to the existing argv[0] fallback. This matches Node, whose uv_exepath uses GetModuleFileNameW on Windows.

The change is about 15 lines in scr_lib.c: https://github.com/vercel-labs/scriptc/compare/main...tom96da:scriptc:fix/windows-exec-path-utf8. I can open it as a pull request.

Related calls, not verified

These calls also pass an ANSI API result or input through as UTF-8. I haven't checked any of them on a real machine.

  • scr_lib.c L796, L802: GetEnvironmentVariableA in scr_env_get (process.env reads). The variable name is passed as ANSI too.
  • scr_lib.c L1479: GetUserNameA in scr_os_user_name (os.userInfo().username).
  • scr_lib.c L1546: GetTempPathA in scr_os_tmpdir (os.tmpdir()).

scr_intl.c L78 (scr_intl_exe_dir) also uses GetModuleFileNameA, but the path goes to ICU, which opens it with an ANSI API, so it is consistent and doesn't return a value to JavaScript. It may need a separate look for non-ASCII install paths.

#321 and #323 (console output mojibake) are a separate matter.


日本語(原文)

main の 0db50d64b(v0.4.7-578)で確認しました。

概要

Windows 向けの実行ファイルで、パスに非 ASCII 文字が含まれ、ANSI コードページが UTF-8 でない場合(日本語 Windows の既定 CP932 など)に、process.execPath が文字化けします。

scr_process_exec_path()(packages/runtime/src/scr_lib.c L761)が GetModuleFileNameA でパスを取得し、システムのコードページのバイト列をそのまま UTF-8 として保持しているためです。同じファイルの scr_process_cwd() などは Unicode API と scr_fs_win_utf8() を使っており、execPath だけが漏れています。

この値は子プロセスの起動にも使われます。fork() の Windows 側(scr_child.c L2476)と scr_node_island.c(L184、L678)が scr_process_exec_path() を spawn に渡し、spawn 側はそれを UTF-8 として CreateProcessW 用に変換します。そのため CP932 環境では、日本語を含むパスにある実行ファイルからの child_process.fork() が失敗するはずです。fork() の失敗は実機では確認していません。

確認結果
  • ANSI コードページが UTF-8 の Windows: 化けない
  • CP932 の Windows: 日本語を含むパスの実行ファイルで化ける
  • 下記の修正を入れたランタイムでビルドした実行ファイルは、CP932 の実機で化けずに取得できることを確認済み(Linux から SCRIPTC_BUILD_CROSS=1 でクロスビルド、Zig 0.16.0)

環境: SCRIPTC_TARGET=x86_64-windows-gnu

修正案

scr_process_exec_path() の Windows 側を scr_process_cwd() と同じ方式にします。GetModuleFileNameW で取得し、scr_fs_win_utf8() で UTF-8 に変換します。取得したパスは既に絶対パスなので、ANSI 版の _fullpath は通しません。失敗した場合や 4096 文字に収まらない場合は、従来の argv[0] のフォールバックに進みます。Node の uv_exepath も、Windows では GetModuleFileNameW を使っています。

変更は scr_lib.c に約 15 行です: https://github.com/vercel-labs/scriptc/compare/main...tom96da:scriptc:fix/windows-exec-path-utf8 。プルリクエストとして出せます。

関連する呼び出し(未確認)

次の呼び出しも、ANSI 版 API の結果や入力を UTF-8 としてそのまま扱っています。いずれも実機では確認していません。

  • scr_lib.c L796、L802: scr_env_get の GetEnvironmentVariableA(process.env の読み取り)。変数名も ANSI として渡しています。
  • scr_lib.c L1479: scr_os_user_name の GetUserNameA(os.userInfo().username)
  • scr_lib.c L1546: scr_os_tmpdir の GetTempPathA(os.tmpdir())

scr_intl.c L78(scr_intl_exe_dir)も GetModuleFileNameA を使っていますが、パスは ICU に渡され、ICU 側も ANSI の API で開くため一貫しており、JavaScript には値を返しません。非 ASCII のインストール先については、別に確認が必要かもしれません。

#321 / #323(コンソール出力の文字化け)は別件です。

Lingua principale
TypeScript
Stelle
6.4k
Fork
204
Merge medio
7h 37m
PR unite (30g)
878

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di vercel-labs/scriptc

Tutte le issue di vercel-labs/scriptc

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.