~ chicken-core (chicken-5) 2cebcd70d4ac3258600410c771108dadee91fee0
commit 2cebcd70d4ac3258600410c771108dadee91fee0 Author: felix <felix@call-with-current-continuation.org> AuthorDate: Mon Dec 30 22:21:07 2024 +0100 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Mon Dec 30 22:21:07 2024 +0100 Use wide-char win32 API for retrieving command line (to avoid security issues pointed out by wasamasa) diff --git a/chicken.h b/chicken.h index ccdefe87..49e38d75 100644 --- a/chicken.h +++ b/chicken.h @@ -1610,7 +1610,11 @@ typedef void (C_ccall *C_proc)(C_word, C_word *) C_noret; * "/proc/<pid>/exe" or some similar trick). */ #ifdef SEARCH_EXE_PATH -# define C_set_main_exe(fname) C_main_exe = C_resolve_executable_pathname(fname) +# if defined(_WIN32) && !defined(__CYGWIN__) +# define C_set_main_exe(fname) C_main_exe = C_resolve_executable_pathname(C_utf8(fname)) +# else +# define C_set_main_exe(fname) C_main_exe = C_resolve_executable_pathname(fname) +# endif #else # define C_set_main_exe(fname) #endif @@ -1625,10 +1629,19 @@ typedef void (C_ccall *C_proc)(C_word, C_word *) C_noret; C_private_repository(); \ return CHICKEN_main(0, NULL, (void *)C_toplevel); \ } +# elif defined(_WIN32) && !defined(__CYGWIN__) +# define C_main_entry_point \ + int wmain(int argc, wchar_t *argv[]) \ + { \ + C_set_gui_mode; \ + C_set_main_exe(argv[0]); \ + C_private_repository(); \ + return CHICKEN_main(argc, argv, (void*)C_toplevel); \ + } # else # define C_main_entry_point \ int main(int argc, char *argv[]) \ - { \ + { \ C_set_gui_mode; \ C_set_main_exe(argv[0]); \ C_private_repository(); \ @@ -1758,7 +1771,7 @@ C_varextern int C_varextern C_uword C_heap_growth, C_heap_shrinkage; -C_varextern char +C_varextern C_WCHAR **C_main_argv, #ifdef SEARCH_EXE_PATH *C_main_exe, @@ -1775,7 +1788,7 @@ C_varextern C_word (*C_get_unbound_variable_value_hook)(C_word sym); C_BEGIN_C_DECLS C_fctexport void C_register_debug_info(C_DEBUG_INFO *); -C_fctexport int CHICKEN_main(int argc, char *argv[], void *toplevel); +C_fctexport int CHICKEN_main(int argc, C_WCHAR *argv[], void *toplevel); C_fctexport int CHICKEN_initialize(int heap, int stack, int symbols, void *toplevel); C_fctexport C_word CHICKEN_run(void *toplevel); C_fctexport C_word CHICKEN_continue(C_word k); diff --git a/runtime.c b/runtime.c index ec40f219..0efc4f13 100644 --- a/runtime.c +++ b/runtime.c @@ -604,19 +604,44 @@ C_dbg(C_char *prefix, C_char *fstr, ...) /* Startup code: */ -int CHICKEN_main(int argc, char *argv[], void *toplevel) +int CHICKEN_main(int argc, C_WCHAR *argv[], void *toplevel) { C_word h, s, n; if(C_gui_mode) { #ifdef _WIN32 - parse_argv(GetCommandLine()); + parse_argv(C_utf8(GetCommandLineW())); argc = C_main_argc; argv = C_main_argv; #else /* ??? */ #endif } +#if defined(_WIN32) && !defined(__CYGWIN__) + else { + int i, n; + C_char *aptr, *arg; + C_main_argv = (C_char **)malloc((MAXIMAL_NUMBER_OF_COMMAND_LINE_ARGUMENTS + 1) * sizeof(C_char *)); + + if(C_main_argv == NULL) + panic(C_text("cannot allocate argument-list buffer")); + + for(i = 0; i < argc; ++i) { + arg = C_utf8(argv[ i ]); + n = strlen(arg); + aptr = (C_char *)malloc(n + 1); + + if(!aptr) panic(C_text("cannot allocate argument buffer")); + + C_strlcpy(aptr, arg, n + 1); + C_main_argv[ i ] = aptr; + } + + C_main_argc = argc; + C_main_argv[ argc ] = NULL; + argv = C_main_argv; + } +#endif pass_serious_signals = 0; CHICKEN_parse_command_line(argc, argv, &h, &s, &n); @@ -629,22 +654,20 @@ int CHICKEN_main(int argc, char *argv[], void *toplevel) } -/* Custom argv parser for Windoze: */ +/* Custom argv parser for Windowz: */ void parse_argv(C_char *cmds) { - C_char *ptr = cmds, - *bptr0, *bptr, *aptr; + C_char *ptr = cmds, *bptr0, *bptr, *aptr; int n = 0; - - C_main_argv = (C_char **)malloc(MAXIMAL_NUMBER_OF_COMMAND_LINE_ARGUMENTS * sizeof(C_char *)); + C_main_argv = (C_char **)malloc((MAXIMAL_NUMBER_OF_COMMAND_LINE_ARGUMENTS + 1) * sizeof(C_char *)); if(C_main_argv == NULL) panic(C_text("cannot allocate argument-list buffer")); C_main_argc = 0; - for(;;) { + while(C_main_argc < MAXIMAL_NUMBER_OF_COMMAND_LINE_ARGUMENTS) { while(C_utf_isspace((int)(*ptr))) ++ptr; if(*ptr == '\0') break; @@ -653,15 +676,15 @@ void parse_argv(C_char *cmds) ++n; *bptr = '\0'; + aptr = (C_char*)malloc(n + 1); - aptr = (C_char*) malloc(sizeof(C_char) * (n + 1)); - if (!aptr) - panic(C_text("cannot allocate argument buffer")); - - C_strlcpy(aptr, bptr0, sizeof(C_char) * (n + 1)); + if(!aptr) panic(C_text("cannot allocate argument buffer")); + C_strlcpy(aptr, bptr0, n + 1); C_main_argv[ C_main_argc++ ] = aptr; } + + C_main_argv[ C_main_argc ] = NULL; } /* simple linear congruential PRNG, to avoid OpenBSD warnings.Trap