From 8ef78d53b7cb08413ba31dfa29384f9f53f69b9f Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 17 Apr 2024 10:21:29 +0200 Subject: [PATCH 1/3] fixup! Add functionality for converting UNIX paths in arguments and environment variables to Windows form for native Win32 applications. When we fixed MSYS2's automatic Unix <-> Windows path conversion to identify and skip Git-style `:` arguments (and incidentally also scp-style `:` ones), we assumed that path lists containing relative paths would be a rare scenario. My, was this assumption wrong! Let's add another heuristic that detects absolute paths at the beginning of path lists, and relative ones starting with either `./` or `../`, neither of which match those Git-style nor scp-style arguments, and then prevent the detection of the latter style from kicking in. This addresses https://github.com/msys2/msys2-runtime/issues/208 Signed-off-by: Johannes Schindelin --- winsup/cygwin/msys2_path_conv.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/msys2_path_conv.cc b/winsup/cygwin/msys2_path_conv.cc index 4c0cc82cf2..0902dff3fd 100644 --- a/winsup/cygwin/msys2_path_conv.cc +++ b/winsup/cygwin/msys2_path_conv.cc @@ -358,6 +358,18 @@ path_type find_path_start_and_type(const char** src, int recurse, const char* en return NONE; } + /* + * Discern between Git's `:`, SCP's `:` pattern + * (which is not a path list but may naïvely look like one) on the one + * hand, and path lists starting with `/`, `./` or `../` + * on the other hand. + */ + bool potential_path_list = *it == '/' || + (*it == '.' && + (it[1] == ':' || it[1] == '/' || + (it[1] == '.' && + (it[2] == ':' || it[2] == '/')))); + /* * Prevent Git's :file.txt and :/message syntax from beeing modified. */ @@ -383,7 +395,7 @@ path_type find_path_start_and_type(const char** src, int recurse, const char* en goto skip_p2w; // Leave Git's :./name syntax alone - if (it + 1 < end && it[1] == '.') { + if (!potential_path_list && it + 1 < end && it[1] == '.') { if (it + 2 < end && it[2] == '/') goto skip_p2w; if (it + 3 < end && it[2] == '.' && it[3] == '/') From 222fa6ee58f3535c66d88215e2f5a11366992b5a Mon Sep 17 00:00:00 2001 From: Reinhard Biegel Date: Mon, 29 Apr 2024 09:55:43 +0200 Subject: [PATCH 2/3] pathconv: Also skip git/scp path list conversion for environment variables assigned on command line This restores parts of the previous behavior of path_conv, fixing an issue where the paths of the path list in `VARIABLE=.:../foo/bar ./my-script.sh` weren't convertet to windows paths. The path conversion was skipped due to interpretation as a Git style reference. The Git detection is now excluded for this kind of variable assignments. --- winsup/cygwin/msys2_path_conv.cc | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/winsup/cygwin/msys2_path_conv.cc b/winsup/cygwin/msys2_path_conv.cc index 0902dff3fd..1cec32bec8 100644 --- a/winsup/cygwin/msys2_path_conv.cc +++ b/winsup/cygwin/msys2_path_conv.cc @@ -238,7 +238,7 @@ void find_end_of_rooted_path(const char** from, const char** to, int* in_string) void sub_convert(const char** from, const char** to, char** dst, const char* dstend, int* in_string) { const char* copy_from = *from; path_type type = find_path_start_and_type(from, false, *to); - debug_printf("found type %d for path %s", type, copy_from); + debug_printf("found type %d for path %s\n", type, copy_from); if (type == POSIX_PATH_LIST) { find_end_of_posix_list(to, in_string); @@ -370,6 +370,28 @@ path_type find_path_start_and_type(const char** src, int recurse, const char* en (it[1] == '.' && (it[2] == ':' || it[2] == '/')))); + /* + * Determine if assignment to an environment variable takes place (and + * skip Git/SCP handling if so) + */ + bool potential_command_scope_env = false; + if (isalpha(*it) || *it == '_' || *it == '-') { + ++it; + + if (it != end) { + if (*it == '-') + ++it; + + while (it != end && *it && (isalnum(*it) || *it == '_')) { + ++it; + } + + if (*it == '=') + potential_command_scope_env = true; + } + it = *src; + } + /* * Prevent Git's :file.txt and :/message syntax from beeing modified. */ @@ -395,7 +417,7 @@ path_type find_path_start_and_type(const char** src, int recurse, const char* en goto skip_p2w; // Leave Git's :./name syntax alone - if (!potential_path_list && it + 1 < end && it[1] == '.') { + if (!potential_path_list && !potential_command_scope_env && it + 1 < end && it[1] == '.') { if (it + 2 < end && it[2] == '/') goto skip_p2w; if (it + 3 < end && it[2] == '.' && it[3] == '/') @@ -718,4 +740,3 @@ void posix_to_win32_path(const char* from, const char* to, char** dst, const cha } } } - From a907109ef7028b91e1cda849908c87d9dcf408a8 Mon Sep 17 00:00:00 2001 From: Reinhard Biegel Date: Tue, 2 Jul 2024 09:50:22 +0200 Subject: [PATCH 3/3] pathconv: Check for end of input when determining potential path list Suggested-by: Richard Copley --- winsup/cygwin/msys2_path_conv.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/winsup/cygwin/msys2_path_conv.cc b/winsup/cygwin/msys2_path_conv.cc index 1cec32bec8..49caac99a6 100644 --- a/winsup/cygwin/msys2_path_conv.cc +++ b/winsup/cygwin/msys2_path_conv.cc @@ -360,15 +360,15 @@ path_type find_path_start_and_type(const char** src, int recurse, const char* en /* * Discern between Git's `:`, SCP's `:` pattern - * (which is not a path list but may naïvely look like one) on the one + * (which is not a path list but may naively look like one) on the one * hand, and path lists starting with `/`, `./` or `../` * on the other hand. */ bool potential_path_list = *it == '/' || - (*it == '.' && - (it[1] == ':' || it[1] == '/' || - (it[1] == '.' && - (it[2] == ':' || it[2] == '/')))); + (*it == '.' && + (it + 1 == end || it[1] == '\0' || it[1] == ':' || it[1] == '/' || + (it[1] == '.' && + (it + 2 == end || it[2] == '\0' || it[2] == ':' || it[2] == '/')))); /* * Determine if assignment to an environment variable takes place (and