From cf77c3eff0ddd18e9182928e346a70618064a281 Mon Sep 17 00:00:00 2001
From: Jeremy Drake <github@jdrake.com>
Date: Fri, 31 Jan 2025 12:27:42 -0800
Subject: [PATCH 51/N] fixup! Instead of creating Cygwin symlinks, use deep
 copy by default

avoid recursing into dst as well as src.  Given we only ever append to
either, their original lengths should be sufficient, rather than copies
of them.
---
 winsup/cygwin/path.cc | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 4a9d500..373aec9 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -1706,7 +1706,8 @@ recursiveCopyCheckSymlink(PUNICODE_STRING src, bool& isdirlink)
   Create a deep copy of src as dst, while avoiding descending in origpath.
 */
 static int
-recursiveCopy (PUNICODE_STRING src, PUNICODE_STRING dst, PCWSTR origpath, PWIN32_FIND_DATAW dHfile = NULL)
+recursiveCopy (PUNICODE_STRING src, PUNICODE_STRING dst, USHORT origsrclen,
+	       USHORT origdstlen, PWIN32_FIND_DATAW dHfile = NULL)
 {
   HANDLE dH = INVALID_HANDLE_VALUE;
   NTSTATUS status;
@@ -1812,11 +1813,15 @@ recursiveCopy (PUNICODE_STRING src, PUNICODE_STRING dst, PCWSTR origpath, PWIN32
       else if (dHfile->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
 	{
 	  /* Recurse into the child directory */
-	  debug_printf ("%S <-> %W", src, origpath);
-	  // avoids endless recursion
-	  if (wcsncmp (src->Buffer, origpath, src->Length / sizeof (WCHAR)))
-	    if (recursiveCopy (src, dst, origpath, dHfile))
+	  /* avoids endless recursion */
+	  if (src->Length <= origsrclen ||
+	      !wcsncmp (src->Buffer, dst->Buffer, origdstlen / sizeof (WCHAR)))
+	    {
+	      set_errno (ELOOP);
 	      goto done;
+	    }
+	  if (recursiveCopy (src, dst, origsrclen, origdstlen, dHfile))
+	    goto done;
 	}
       else
 	{
@@ -2193,13 +2198,13 @@ symlink_deepcopy (const char *oldpath, path_conv &win32_newpath)
     w_newpath->Buffer[1] = L'\\';
   if (win32_oldpath.isdir ())
     {
-      PWCHAR origpath = win32_oldpath.get_wide_win32_path (tp.w_get ());
       /* we need a larger UNICODE_STRING MaximumLength than
 	 get_nt_native_path allocates for the recursive copy */
       UNICODE_STRING u_oldpath, u_newpath;
       RtlCopyUnicodeString (tp.u_get (&u_oldpath), w_oldpath);
       RtlCopyUnicodeString (tp.u_get (&u_newpath), w_newpath);
-      return recursiveCopy (&u_oldpath, &u_newpath, origpath);
+      return recursiveCopy (&u_oldpath, &u_newpath,
+			    u_oldpath.Length, u_newpath.Length);
     }
   else
     {
