Subversion command line argument injection on Windows platforms Summary: ======== On Windows platforms, a "best fit" character encoding conversion of command line arguments to Subversion's executables (e.g., svn.exe, etc.) may lead to unexpected command line argument interpretation, including argument injection and execution of other programs, if a specially crafted command line argument string is processed. UNIX-like platforms are not affected. Known vulnerable: ================= Subversion up to 1.14.3 (inclusive). Known fixed: ============ Subversion 1.14.4. Details: ======== On Windows platforms, command line arguments are passed to a program as a single string. It is up to the program to separate command line arguments. In many cases, such as when a C-language program has a main() function as its entry point, this command line argument separation functionality is provided by a library and is more or less transparent to the program's developer. Furthermore, on Windows platforms, programs with a main() function receive their command line arguments in an "ANSI" (MultiByte) string by default, though the Windows system natively uses Unicode UTF-16 (WideChar). This may necessitate a character encoding conversion. The use of certain Unicode characters on the command line may trigger a "best fit" algorithm to perform the conversion. An attacker who can run one of Subversion's executables (svn.exe, etc.) with a specially crafted command line argument string could take advantage of the character encoding conversion process to cause unexpected command line argument interpretation, leading to argument injection and execution of other programs. Subversion is known to be affected on Windows 10 and 11; it may be affected on most other versions of Windows as well. This issue affects Subversion on Windows platforms only. UNIX-like platforms are not affected. Severity: ========= CVSSv3.1 Base Score: 8.2 (High) CVSSv3.1 Base Vector: CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H Exploitation may result in unexpected command line argument interpretation, argument injection, and execution of other programs. Recommendations: ================ We recommend all users to upgrade to a known fixed release of Subversion. Users who are unable to upgrade may apply the patch included below. References: =========== CVE-2024-45720 (Subversion) Reported by: ============ Orange Tsai (@orange_8361) from DEVCORE Research Team splitline (@_splitline_) from DEVCORE Research Team Patch: ====== Patch against Subversion 1.14.3: [[[ Index: build.conf =================================================================== --- build.conf (revision 1920475) +++ build.conf (working copy) @@ -153,7 +153,7 @@ libs = libsvn_client libsvn_wc libsvn_ra libsvn_de apriconv apr manpages = subversion/svn/svn.1 install = bin -msvc-libs = setargv.obj +msvc-libs = wsetargv.obj # The subversion repository administration tool [svnadmin] @@ -163,7 +163,7 @@ path = subversion/svnadmin install = bin manpages = subversion/svnadmin/svnadmin.1 libs = libsvn_repos libsvn_fs libsvn_delta libsvn_subr apriconv apr -msvc-libs = setargv.obj +msvc-libs = wsetargv.obj # The subversion repository dump filtering tool [svndumpfilter] Index: subversion/include/private/svn_cmdline_private.h =================================================================== --- subversion/include/private/svn_cmdline_private.h (revision 1920475) +++ subversion/include/private/svn_cmdline_private.h (working copy) @@ -278,6 +278,34 @@ svn_cmdline__stdin_readline(const char **result, apr_pool_t *result_pool, apr_pool_t *scratch_pool); +#if defined(WIN32) +/* Normalizes Windows-specific command line arguments, such as those passed + to wmain(), to the environment-specific code page. */ +svn_error_t * +svn_cmdline__win32_get_cstring_argv(const char **cstring_argv_p[], + int argc, + const wchar_t *argv[], + apr_pool_t *result_pool); +#endif + +/* Default platform-agnostic handler that normalizes command line arguments + to the environment-specific code page. */ +svn_error_t * +svn_cmdline__default_get_cstring_argv(const char **cstring_argv_p[], + int argc, + const char *argv[], + apr_pool_t *result_pool); + +#if defined(WIN32) && defined(_MSC_VER) +typedef wchar_t svn_cmdline__argv_char_t; +#define SVN_CMDLINE__MAIN wmain +#define svn_cmdline__get_cstring_argv svn_cmdline__win32_get_cstring_argv +#else +typedef char svn_cmdline__argv_char_t; +#define SVN_CMDLINE__MAIN main +#define svn_cmdline__get_cstring_argv svn_cmdline__default_get_cstring_argv +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ Index: subversion/libsvn_subr/cmdline.c =================================================================== --- subversion/libsvn_subr/cmdline.c (revision 1920475) +++ subversion/libsvn_subr/cmdline.c (working copy) @@ -1898,3 +1898,60 @@ svn_cmdline__cancellation_exit(void) #endif } } + +#if defined(WIN32) + +svn_error_t * +svn_cmdline__win32_get_cstring_argv(const char **cstring_argv_p[], + int argc, + const wchar_t *argv[], + apr_pool_t *result_pool) +{ + apr_array_header_t *cstring_argv; + int i; + + cstring_argv = apr_array_make(result_pool, argc + 1, sizeof(const char *)); + + for (i = 0; i < argc; i++) + { + const wchar_t *arg = argv[i]; + char *cstring_arg; + int rv; + + /* Passing -1 for the string length guarantees that the returned length + will account for a terminating null character. */ + rv = WideCharToMultiByte(CP_ACP, 0, arg, -1, NULL, 0, NULL, NULL); + if (rv <= 0) + { + return svn_error_wrap_apr(apr_get_os_error(), + _("Conversion from UTF-16 failed")); + } + + cstring_arg = apr_palloc(result_pool, rv); + rv = WideCharToMultiByte(CP_ACP, 0, arg, -1, cstring_arg, rv, NULL, NULL); + if (rv <= 0) + { + return svn_error_wrap_apr(apr_get_os_error(), + _("Conversion from UTF-16 failed")); + } + + APR_ARRAY_PUSH(cstring_argv, const char *) = cstring_arg; + } + + APR_ARRAY_PUSH(cstring_argv, const char *) = NULL; + + *cstring_argv_p = (const char **)cstring_argv->elts; + return SVN_NO_ERROR; +} + +#endif + +svn_error_t * +svn_cmdline__default_get_cstring_argv(const char **cstring_argv_p[], + int argc, + const char *argv[], + apr_pool_t *result_pool) +{ + *cstring_argv_p = argv; + return SVN_NO_ERROR; +} Index: subversion/svn/svn.c =================================================================== --- subversion/svn/svn.c (revision 1920475) +++ subversion/svn/svn.c (working copy) @@ -2019,7 +2019,10 @@ add_commands(const svn_opt_subcommand_desc3_t *cmd * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; int opt_id; @@ -2045,6 +2048,7 @@ static svn_error_t * apr_hash_t *cfg_hash; svn_membuf_t buf; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -2051,6 +2055,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -3324,7 +3330,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnadmin/svnadmin.c =================================================================== --- subversion/svnadmin/svnadmin.c (revision 1920475) +++ subversion/svnadmin/svnadmin.c (working copy) @@ -3048,7 +3048,10 @@ subcommand_build_repcache(apr_getopt_t *os, void * * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; apr_status_t apr_err; @@ -3060,6 +3063,7 @@ static svn_error_t * apr_array_header_t *received_opts; int i; svn_boolean_t dash_F_arg = FALSE; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -3066,6 +3070,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); @@ -3445,7 +3451,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnbench/svnbench.c =================================================================== --- subversion/svnbench/svnbench.c (revision 1920475) +++ subversion/svnbench/svnbench.c (working copy) @@ -386,7 +386,10 @@ add_search_pattern_group(svn_cl__opt_state_t *opt_ * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; int opt_id; @@ -405,6 +408,7 @@ static svn_error_t * ra_progress_baton_t ra_progress_baton = {0}; svn_membuf_t buf; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -414,6 +418,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -1039,7 +1045,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svndumpfilter/svndumpfilter.c =================================================================== --- subversion/svndumpfilter/svndumpfilter.c (revision 1920475) +++ subversion/svndumpfilter/svndumpfilter.c (working copy) @@ -1291,7 +1291,10 @@ subcommand_include(apr_getopt_t *os, void *baton, * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; apr_status_t apr_err; @@ -1302,10 +1305,13 @@ static svn_error_t * int opt_id; apr_array_header_t *received_opts; int i; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); /* Initialize the FS library. */ @@ -1564,7 +1570,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnfsfs/svnfsfs.c =================================================================== --- subversion/svnfsfs/svnfsfs.c (revision 1920475) +++ subversion/svnfsfs/svnfsfs.c (working copy) @@ -228,7 +228,10 @@ subcommand__help(apr_getopt_t *os, void *baton, ap * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; apr_status_t apr_err; @@ -239,6 +242,7 @@ static svn_error_t * int opt_id; apr_array_header_t *received_opts; int i; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -245,6 +249,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); @@ -473,7 +479,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnlook/svnlook.c =================================================================== --- subversion/svnlook/svnlook.c (revision 1920475) +++ subversion/svnlook/svnlook.c (working copy) @@ -2466,7 +2466,10 @@ subcommand_uuid(apr_getopt_t *os, void *baton, apr * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; apr_status_t apr_err; @@ -2477,6 +2480,7 @@ static svn_error_t * int opt_id; apr_array_header_t *received_opts; int i; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -2483,6 +2487,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); @@ -2849,7 +2855,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnmucc/svnmucc.c =================================================================== --- subversion/svnmucc/svnmucc.c (revision 1920475) +++ subversion/svnmucc/svnmucc.c (working copy) @@ -467,7 +467,10 @@ log_message_func(const char **log_msg, * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { apr_array_header_t *actions = apr_array_make(pool, 1, sizeof(struct action *)); @@ -533,10 +536,13 @@ static svn_error_t * struct log_message_baton lmb; int i; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the RA library. */ SVN_ERR(svn_ra_initialize(pool)); @@ -980,7 +986,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnrdump/svnrdump.c =================================================================== --- subversion/svnrdump/svnrdump.c (revision 1920475) +++ subversion/svnrdump/svnrdump.c (working copy) @@ -784,7 +784,10 @@ validate_and_resolve_revisions(opt_baton_t *opt_ba * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err = SVN_NO_ERROR; const svn_opt_subcommand_desc3_t *subcommand = NULL; @@ -806,7 +809,10 @@ static svn_error_t * apr_array_header_t *received_opts; int i; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + opt_baton = apr_pcalloc(pool, sizeof(*opt_baton)); opt_baton->start_revision.kind = svn_opt_revision_unspecified; opt_baton->end_revision.kind = svn_opt_revision_unspecified; @@ -1155,7 +1161,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnserve/svnserve.c =================================================================== --- subversion/svnserve/svnserve.c (revision 1920475) +++ subversion/svnserve/svnserve.c (working copy) @@ -703,7 +703,10 @@ check_lib_versions(void) * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { enum run_mode run_mode = run_mode_unspecified; svn_boolean_t foreground = FALSE; @@ -742,6 +745,8 @@ static svn_error_t * svn_node_kind_t kind; apr_size_t min_thread_count = THREADPOOL_MIN_SIZE; apr_size_t max_thread_count = THREADPOOL_MAX_SIZE; + const char **argv; + #ifdef SVN_HAVE_SASL SVN_ERR(cyrus_init(pool)); #endif @@ -749,6 +754,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); @@ -1395,7 +1402,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnsync/svnsync.c =================================================================== --- subversion/svnsync/svnsync.c (revision 1920475) +++ subversion/svnsync/svnsync.c (working copy) @@ -1963,7 +1963,10 @@ help_cmd(apr_getopt_t *os, void *baton, apr_pool_t * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { const svn_opt_subcommand_desc3_t *subcommand = NULL; apr_array_header_t *received_opts; @@ -1978,10 +1981,13 @@ static svn_error_t * apr_array_header_t *config_options = NULL; const char *source_prop_encoding = NULL; svn_boolean_t force_interactive = FALSE; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + SVN_ERR(svn_ra_initialize(pool)); /* Initialize the option baton. */ @@ -2402,7 +2408,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnversion/svnversion.c =================================================================== --- subversion/svnversion/svnversion.c (revision 1920475) +++ subversion/svnversion/svnversion.c (working copy) @@ -124,7 +124,10 @@ check_lib_versions(void) * program. Obviously we don't want to have to run svn when building svn. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { const char *wc_path, *trail_url; const char *local_abspath; @@ -146,10 +149,13 @@ static svn_error_t * N_("no progress (only errors) to stderr")}, {0, 0, 0, 0} }; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -289,7 +295,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c =================================================================== --- tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c (revision 1920475) +++ tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c (working copy) @@ -408,7 +408,10 @@ svn_min__check_cancel(void *baton) * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; int opt_id; @@ -425,6 +428,7 @@ static svn_error_t * svn_boolean_t force_interactive = FALSE; apr_hash_t *cfg_hash; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -431,6 +435,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -946,7 +952,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: tools/client-side/svnconflict/svnconflict.c =================================================================== --- tools/client-side/svnconflict/svnconflict.c (revision 1920475) +++ tools/client-side/svnconflict/svnconflict.c (working copy) @@ -632,7 +632,10 @@ svnconflict_resolve_tree(apr_getopt_t *os, void *b * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; int opt_id; @@ -647,6 +650,7 @@ static svn_error_t * svn_config_t *cfg_config; apr_hash_t *cfg_hash; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -653,6 +657,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -949,7 +955,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: tools/dev/svnraisetreeconflict/svnraisetreeconflict.c =================================================================== --- tools/dev/svnraisetreeconflict/svnraisetreeconflict.c (revision 1920475) +++ tools/dev/svnraisetreeconflict/svnraisetreeconflict.c (working copy) @@ -302,7 +302,10 @@ check_lib_versions(void) * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { apr_getopt_t *os; const apr_getopt_option_t options[] = @@ -313,10 +316,13 @@ static svn_error_t * {0, 0, 0, 0} }; apr_array_header_t *remaining_argv; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -383,7 +389,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: tools/dev/wc-ng/svn-wc-db-tester.c =================================================================== --- tools/dev/wc-ng/svn-wc-db-tester.c (revision 1920475) +++ tools/dev/wc-ng/svn-wc-db-tester.c (working copy) @@ -156,7 +156,10 @@ check_lib_versions(void) * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { apr_getopt_t *os; const apr_getopt_option_t options[] = @@ -167,10 +170,13 @@ static svn_error_t * {0, 0, 0, 0} }; apr_array_header_t *remaining_argv; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -237,7 +243,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: tools/server-side/svnauthz.c =================================================================== --- tools/server-side/svnauthz.c (revision 1920475) +++ tools/server-side/svnauthz.c (working copy) @@ -490,7 +490,10 @@ canonicalize_access_file(const char **canonicalize * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; @@ -499,7 +502,10 @@ static svn_error_t * apr_getopt_t *os; apr_array_header_t *received_opts; int i; + const char **argv; + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); @@ -752,7 +758,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; @@ -759,7 +765,7 @@ int svn_error_t *err; /* Initialize the app. Send all error messages to 'stderr'. */ - if (svn_cmdline_init(argv[0], stderr) != EXIT_SUCCESS) + if (svn_cmdline_init("svnauthz", stderr) != EXIT_SUCCESS) return EXIT_FAILURE; pool = svn_pool_create(NULL); ]]] Patches: ======== Patch for Subversion 1.14.3: [[[ Index: build.conf =================================================================== --- build.conf (revision 1920475) +++ build.conf (working copy) @@ -153,7 +153,7 @@ libs = libsvn_client libsvn_wc libsvn_ra libsvn_de apriconv apr manpages = subversion/svn/svn.1 install = bin -msvc-libs = setargv.obj +msvc-libs = wsetargv.obj # The subversion repository administration tool [svnadmin] @@ -163,7 +163,7 @@ path = subversion/svnadmin install = bin manpages = subversion/svnadmin/svnadmin.1 libs = libsvn_repos libsvn_fs libsvn_delta libsvn_subr apriconv apr -msvc-libs = setargv.obj +msvc-libs = wsetargv.obj # The subversion repository dump filtering tool [svndumpfilter] Index: subversion/include/private/svn_cmdline_private.h =================================================================== --- subversion/include/private/svn_cmdline_private.h (revision 1920475) +++ subversion/include/private/svn_cmdline_private.h (working copy) @@ -278,6 +278,34 @@ svn_cmdline__stdin_readline(const char **result, apr_pool_t *result_pool, apr_pool_t *scratch_pool); +#if defined(WIN32) +/* Normalizes Windows-specific command line arguments, such as those passed + to wmain(), to the environment-specific code page. */ +svn_error_t * +svn_cmdline__win32_get_cstring_argv(const char **cstring_argv_p[], + int argc, + const wchar_t *argv[], + apr_pool_t *result_pool); +#endif + +/* Default platform-agnostic handler that normalizes command line arguments + to the environment-specific code page. */ +svn_error_t * +svn_cmdline__default_get_cstring_argv(const char **cstring_argv_p[], + int argc, + const char *argv[], + apr_pool_t *result_pool); + +#if defined(WIN32) && defined(_MSC_VER) +typedef wchar_t svn_cmdline__argv_char_t; +#define SVN_CMDLINE__MAIN wmain +#define svn_cmdline__get_cstring_argv svn_cmdline__win32_get_cstring_argv +#else +typedef char svn_cmdline__argv_char_t; +#define SVN_CMDLINE__MAIN main +#define svn_cmdline__get_cstring_argv svn_cmdline__default_get_cstring_argv +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ Index: subversion/libsvn_subr/cmdline.c =================================================================== --- subversion/libsvn_subr/cmdline.c (revision 1920475) +++ subversion/libsvn_subr/cmdline.c (working copy) @@ -1898,3 +1898,60 @@ svn_cmdline__cancellation_exit(void) #endif } } + +#if defined(WIN32) + +svn_error_t * +svn_cmdline__win32_get_cstring_argv(const char **cstring_argv_p[], + int argc, + const wchar_t *argv[], + apr_pool_t *result_pool) +{ + apr_array_header_t *cstring_argv; + int i; + + cstring_argv = apr_array_make(result_pool, argc + 1, sizeof(const char *)); + + for (i = 0; i < argc; i++) + { + const wchar_t *arg = argv[i]; + char *cstring_arg; + int rv; + + /* Passing -1 for the string length guarantees that the returned length + will account for a terminating null character. */ + rv = WideCharToMultiByte(CP_ACP, 0, arg, -1, NULL, 0, NULL, NULL); + if (rv <= 0) + { + return svn_error_wrap_apr(apr_get_os_error(), + _("Conversion from UTF-16 failed")); + } + + cstring_arg = apr_palloc(result_pool, rv); + rv = WideCharToMultiByte(CP_ACP, 0, arg, -1, cstring_arg, rv, NULL, NULL); + if (rv <= 0) + { + return svn_error_wrap_apr(apr_get_os_error(), + _("Conversion from UTF-16 failed")); + } + + APR_ARRAY_PUSH(cstring_argv, const char *) = cstring_arg; + } + + APR_ARRAY_PUSH(cstring_argv, const char *) = NULL; + + *cstring_argv_p = (const char **)cstring_argv->elts; + return SVN_NO_ERROR; +} + +#endif + +svn_error_t * +svn_cmdline__default_get_cstring_argv(const char **cstring_argv_p[], + int argc, + const char *argv[], + apr_pool_t *result_pool) +{ + *cstring_argv_p = argv; + return SVN_NO_ERROR; +} Index: subversion/svn/svn.c =================================================================== --- subversion/svn/svn.c (revision 1920475) +++ subversion/svn/svn.c (working copy) @@ -2019,7 +2019,10 @@ add_commands(const svn_opt_subcommand_desc3_t *cmd * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; int opt_id; @@ -2045,6 +2048,7 @@ static svn_error_t * apr_hash_t *cfg_hash; svn_membuf_t buf; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -2051,6 +2055,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -3324,7 +3330,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnadmin/svnadmin.c =================================================================== --- subversion/svnadmin/svnadmin.c (revision 1920475) +++ subversion/svnadmin/svnadmin.c (working copy) @@ -3048,7 +3048,10 @@ subcommand_build_repcache(apr_getopt_t *os, void * * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; apr_status_t apr_err; @@ -3060,6 +3063,7 @@ static svn_error_t * apr_array_header_t *received_opts; int i; svn_boolean_t dash_F_arg = FALSE; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -3066,6 +3070,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); @@ -3445,7 +3451,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnbench/svnbench.c =================================================================== --- subversion/svnbench/svnbench.c (revision 1920475) +++ subversion/svnbench/svnbench.c (working copy) @@ -386,7 +386,10 @@ add_search_pattern_group(svn_cl__opt_state_t *opt_ * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; int opt_id; @@ -405,6 +408,7 @@ static svn_error_t * ra_progress_baton_t ra_progress_baton = {0}; svn_membuf_t buf; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -414,6 +418,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -1039,7 +1045,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svndumpfilter/svndumpfilter.c =================================================================== --- subversion/svndumpfilter/svndumpfilter.c (revision 1920475) +++ subversion/svndumpfilter/svndumpfilter.c (working copy) @@ -1291,7 +1291,10 @@ subcommand_include(apr_getopt_t *os, void *baton, * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; apr_status_t apr_err; @@ -1302,10 +1305,13 @@ static svn_error_t * int opt_id; apr_array_header_t *received_opts; int i; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); /* Initialize the FS library. */ @@ -1564,7 +1570,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnfsfs/svnfsfs.c =================================================================== --- subversion/svnfsfs/svnfsfs.c (revision 1920475) +++ subversion/svnfsfs/svnfsfs.c (working copy) @@ -228,7 +228,10 @@ subcommand__help(apr_getopt_t *os, void *baton, ap * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; apr_status_t apr_err; @@ -239,6 +242,7 @@ static svn_error_t * int opt_id; apr_array_header_t *received_opts; int i; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -245,6 +249,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); @@ -473,7 +479,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnlook/svnlook.c =================================================================== --- subversion/svnlook/svnlook.c (revision 1920475) +++ subversion/svnlook/svnlook.c (working copy) @@ -2466,7 +2466,10 @@ subcommand_uuid(apr_getopt_t *os, void *baton, apr * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; apr_status_t apr_err; @@ -2477,6 +2480,7 @@ static svn_error_t * int opt_id; apr_array_header_t *received_opts; int i; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -2483,6 +2487,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); @@ -2849,7 +2855,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnmucc/svnmucc.c =================================================================== --- subversion/svnmucc/svnmucc.c (revision 1920475) +++ subversion/svnmucc/svnmucc.c (working copy) @@ -467,7 +467,10 @@ log_message_func(const char **log_msg, * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { apr_array_header_t *actions = apr_array_make(pool, 1, sizeof(struct action *)); @@ -533,10 +536,13 @@ static svn_error_t * struct log_message_baton lmb; int i; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the RA library. */ SVN_ERR(svn_ra_initialize(pool)); @@ -980,7 +986,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnrdump/svnrdump.c =================================================================== --- subversion/svnrdump/svnrdump.c (revision 1920475) +++ subversion/svnrdump/svnrdump.c (working copy) @@ -784,7 +784,10 @@ validate_and_resolve_revisions(opt_baton_t *opt_ba * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err = SVN_NO_ERROR; const svn_opt_subcommand_desc3_t *subcommand = NULL; @@ -806,7 +809,10 @@ static svn_error_t * apr_array_header_t *received_opts; int i; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + opt_baton = apr_pcalloc(pool, sizeof(*opt_baton)); opt_baton->start_revision.kind = svn_opt_revision_unspecified; opt_baton->end_revision.kind = svn_opt_revision_unspecified; @@ -1155,7 +1161,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnserve/svnserve.c =================================================================== --- subversion/svnserve/svnserve.c (revision 1920475) +++ subversion/svnserve/svnserve.c (working copy) @@ -703,7 +703,10 @@ check_lib_versions(void) * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { enum run_mode run_mode = run_mode_unspecified; svn_boolean_t foreground = FALSE; @@ -742,6 +745,8 @@ static svn_error_t * svn_node_kind_t kind; apr_size_t min_thread_count = THREADPOOL_MIN_SIZE; apr_size_t max_thread_count = THREADPOOL_MAX_SIZE; + const char **argv; + #ifdef SVN_HAVE_SASL SVN_ERR(cyrus_init(pool)); #endif @@ -749,6 +754,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); @@ -1395,7 +1402,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnsync/svnsync.c =================================================================== --- subversion/svnsync/svnsync.c (revision 1920475) +++ subversion/svnsync/svnsync.c (working copy) @@ -1963,7 +1963,10 @@ help_cmd(apr_getopt_t *os, void *baton, apr_pool_t * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { const svn_opt_subcommand_desc3_t *subcommand = NULL; apr_array_header_t *received_opts; @@ -1978,10 +1981,13 @@ static svn_error_t * apr_array_header_t *config_options = NULL; const char *source_prop_encoding = NULL; svn_boolean_t force_interactive = FALSE; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + SVN_ERR(svn_ra_initialize(pool)); /* Initialize the option baton. */ @@ -2402,7 +2408,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: subversion/svnversion/svnversion.c =================================================================== --- subversion/svnversion/svnversion.c (revision 1920475) +++ subversion/svnversion/svnversion.c (working copy) @@ -124,7 +124,10 @@ check_lib_versions(void) * program. Obviously we don't want to have to run svn when building svn. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { const char *wc_path, *trail_url; const char *local_abspath; @@ -146,10 +149,13 @@ static svn_error_t * N_("no progress (only errors) to stderr")}, {0, 0, 0, 0} }; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -289,7 +295,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c =================================================================== --- tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c (revision 1920475) +++ tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c (working copy) @@ -408,7 +408,10 @@ svn_min__check_cancel(void *baton) * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; int opt_id; @@ -425,6 +428,7 @@ static svn_error_t * svn_boolean_t force_interactive = FALSE; apr_hash_t *cfg_hash; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -431,6 +435,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -946,7 +952,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: tools/client-side/svnconflict/svnconflict.c =================================================================== --- tools/client-side/svnconflict/svnconflict.c (revision 1920475) +++ tools/client-side/svnconflict/svnconflict.c (working copy) @@ -632,7 +632,10 @@ svnconflict_resolve_tree(apr_getopt_t *os, void *b * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; int opt_id; @@ -647,6 +650,7 @@ static svn_error_t * svn_config_t *cfg_config; apr_hash_t *cfg_hash; svn_boolean_t read_pass_from_stdin = FALSE; + const char **argv; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -653,6 +657,8 @@ static svn_error_t * /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -949,7 +955,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: tools/dev/svnraisetreeconflict/svnraisetreeconflict.c =================================================================== --- tools/dev/svnraisetreeconflict/svnraisetreeconflict.c (revision 1920475) +++ tools/dev/svnraisetreeconflict/svnraisetreeconflict.c (working copy) @@ -302,7 +302,10 @@ check_lib_versions(void) * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { apr_getopt_t *os; const apr_getopt_option_t options[] = @@ -313,10 +316,13 @@ static svn_error_t * {0, 0, 0, 0} }; apr_array_header_t *remaining_argv; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -383,7 +389,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: tools/dev/wc-ng/svn-wc-db-tester.c =================================================================== --- tools/dev/wc-ng/svn-wc-db-tester.c (revision 1920475) +++ tools/dev/wc-ng/svn-wc-db-tester.c (working copy) @@ -156,7 +156,10 @@ check_lib_versions(void) * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { apr_getopt_t *os; const apr_getopt_option_t options[] = @@ -167,10 +170,13 @@ static svn_error_t * {0, 0, 0, 0} }; apr_array_header_t *remaining_argv; + const char **argv; /* Check library versions */ SVN_ERR(check_lib_versions()); + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + #if defined(WIN32) || defined(__CYGWIN__) /* Set the working copy administrative directory name. */ if (getenv("SVN_ASP_DOT_NET_HACK")) @@ -237,7 +243,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; Index: tools/server-side/svnauthz.c =================================================================== --- tools/server-side/svnauthz.c (revision 1920475) +++ tools/server-side/svnauthz.c (working copy) @@ -490,7 +490,10 @@ canonicalize_access_file(const char **canonicalize * return SVN_NO_ERROR. */ static svn_error_t * -sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) +sub_main(int *exit_code, + int argc, + const svn_cmdline__argv_char_t *cmdline_argv[], + apr_pool_t *pool) { svn_error_t *err; @@ -499,7 +502,10 @@ static svn_error_t * apr_getopt_t *os; apr_array_header_t *received_opts; int i; + const char **argv; + SVN_ERR(svn_cmdline__get_cstring_argv(&argv, argc, cmdline_argv, pool)); + /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); @@ -752,7 +758,7 @@ static svn_error_t * } int -main(int argc, const char *argv[]) +SVN_CMDLINE__MAIN(int argc, const svn_cmdline__argv_char_t *argv[]) { apr_pool_t *pool; int exit_code = EXIT_SUCCESS; @@ -759,7 +765,7 @@ int svn_error_t *err; /* Initialize the app. Send all error messages to 'stderr'. */ - if (svn_cmdline_init(argv[0], stderr) != EXIT_SUCCESS) + if (svn_cmdline_init("svnauthz", stderr) != EXIT_SUCCESS) return EXIT_FAILURE; pool = svn_pool_create(NULL); ]]]