~ 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