Index: /trunk/src/VBox/HostServices/SharedFolders/vbsfpath.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedFolders/vbsfpath.cpp	(revision 65992)
+++ /trunk/src/VBox/HostServices/SharedFolders/vbsfpath.cpp	(revision 65993)
@@ -363,78 +363,4 @@
 
 
-/**
- * Check the given UTF-8 path for root escapes.
- *
- * Verify that the path is within the root directory of the mapping.  Count '..'
- * and other path components and check that we do not go over the root.
- *
- * @returns VBox status code.
- * @retval  VINF_SUCCESS
- * @retval  VERR_INVALID_NAME
- *
- * @param   pszPath         The (UTF-8) path to check.  Slashes has been convert
- *                          to host slashes by this time.
- *
- * @remarks This function assumes that the path will be appended to the root
- *          directory of the shared folder mapping.  Keep that in mind when
- *          checking absolute paths!
- */
-static int vbsfPathCheckRootEscape(const char *pszPath)
-{
-    /*
-     * Walk the path, component by component and check for escapes.
-     */
-
-    int cComponents = 0; /* How many normal path components. */
-    int cParentDirs = 0; /* How many '..' components. */
-
-    for (;;)
-    {
-        char ch;
-
-        /* Skip leading path delimiters. */
-        do
-            ch = *pszPath++;
-        while (RTPATH_IS_SLASH(ch));
-        if (ch == '\0')
-            return VINF_SUCCESS;
-
-        /* Check if that is a dot component. */
-        int cDots = 0;
-        while (ch == '.')
-        {
-            cDots++;
-            ch = *pszPath++;
-        }
-
-        if (   cDots >= 1
-            && (ch == '\0' || RTPATH_IS_SLASH(ch)) )
-        {
-            if (cDots >= 2) /* Consider all multidots sequences as a 'parent dir'. */
-            {
-                cParentDirs++;
-
-                /* Escaping? */
-                if (cParentDirs > cComponents)
-                    return VERR_INVALID_NAME;
-            }
-            /* else: Single dot, nothing changes. */
-        }
-        else
-        {
-            /* Not a dot component, skip to the end of it. */
-            while (ch != '\0' && !RTPATH_IS_SLASH(ch))
-                ch = *pszPath++;
-            cComponents++;
-        }
-        Assert(cComponents >= cParentDirs);
-
-        /* The end? */
-        Assert(ch == '\0' || RTPATH_IS_SLASH(ch));
-        if (ch == '\0')
-            return VINF_SUCCESS;
-    }
-}
-
 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
 /* See MSDN "Naming Files, Paths, and Namespaces".
@@ -609,110 +535,128 @@
          * Allocate enough memory to build the host full path from the root and the relative path.
          */
-        uint32_t cbFullPathAlloc = cbRootLen + 1 + cbGuestPath + 1; /* root + possible_slash + relative + 0 */
+        const uint32_t cbFullPathAlloc = cbRootLen + 1 + cbGuestPath + 1; /* root + possible_slash + relative + 0 */
         pszFullPath = (char *)RTMemAlloc(cbFullPathAlloc);
         if (RT_LIKELY(pszFullPath != NULL))
         {
-            /* Copy the root. */
-            memcpy(pszFullPath, pszRoot, cbRootLen);
-            if (!RTPATH_IS_SLASH(pszFullPath[cbRootLen - 1]))
-            {
-                pszFullPath[cbRootLen++] = RTPATH_SLASH;
-            }
-
-            /* Init the pointer for the relative path. */
-            char *pchDst = &pszFullPath[cbRootLen];
-
-            uint32_t cbSrc = cbGuestPath;
-            const char *pchSrc = pchGuestPath;
-
-            /* Strip leading delimiters from the path the guest specified. */
-            while (   cbSrc > 0
-                   && *pchSrc == pClient->PathDelimiter)
-            {
-                ++pchSrc;
-                --cbSrc;
-            }
-
-            /*
-             * Iterate the guest path components, verify each of them
-             * and append to the host full path replacing delimiters with host slash.
-             */
-            bool fLastComponentHasWildcard = false;
-            for (; cbSrc > 0; --cbSrc, ++pchSrc)
-            {
-                if (RT_LIKELY(*pchSrc != pClient->PathDelimiter))
-                {
-                    if (RT_LIKELY(vbsfPathIsValidNameChar(*pchSrc)))
+            /* Buffer for the verified guest path. */
+            char *pchVerifiedPath = (char *)RTMemAlloc(cbGuestPath + 1);
+            if (RT_LIKELY(pchVerifiedPath != NULL))
+            {
+                /* Init the pointer for the guest relative path. */
+                uint32_t cbSrc = cbGuestPath;
+                const char *pchSrc = pchGuestPath;
+
+                /* Strip leading delimiters from the path the guest specified. */
+                while (   cbSrc > 0
+                       && *pchSrc == pClient->PathDelimiter)
+                {
+                    ++pchSrc;
+                    --cbSrc;
+                }
+
+                /*
+                 * Iterate the guest path components, verify each of them replacing delimiters with the host slash.
+                 */
+                char *pchDst = pchVerifiedPath;
+                bool fLastComponentHasWildcard = false;
+                for (; cbSrc > 0; --cbSrc, ++pchSrc)
+                {
+                    if (RT_LIKELY(*pchSrc != pClient->PathDelimiter))
                     {
-                        if (pfu32PathFlags && vbsfPathIsWildcardChar(*pchSrc))
+                        if (RT_LIKELY(vbsfPathIsValidNameChar(*pchSrc)))
                         {
-                            fLastComponentHasWildcard = true;
+                            if (pfu32PathFlags && vbsfPathIsWildcardChar(*pchSrc))
+                            {
+                                fLastComponentHasWildcard = true;
+                            }
+
+                            *pchDst++ = *pchSrc;
                         }
-
-                        *pchDst++ = *pchSrc;
+                        else
+                        {
+                            rc = VERR_INVALID_NAME;
+                            break;
+                        }
                     }
                     else
                     {
-                        rc = VERR_INVALID_NAME;
-                        break;
+                        /* Replace with the host slash. */
+                        *pchDst++ = RTPATH_SLASH;
+
+                        if (pfu32PathFlags && fLastComponentHasWildcard && cbSrc > 1)
+                        {
+                            /* Processed component has a wildcard and there are more characters in the path. */
+                            *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_PREFIX;
+                        }
+                        fLastComponentHasWildcard = false;
                     }
                 }
-                else
-                {
-                    /* Replace with the host slash. */
-                    *pchDst++ = RTPATH_SLASH;
-
-                    if (pfu32PathFlags && fLastComponentHasWildcard && cbSrc > 1)
-                    {
-                        /* Processed component has a wildcard and there are more characters in the path. */
-                        *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_PREFIX;
-                    }
-                    fLastComponentHasWildcard = false;
-                }
-            }
-
-            if (RT_SUCCESS(rc))
-            {
-                const size_t cbFullPathLength = pchDst - &pszFullPath[0]; /* As strlen(pszFullPath). */
-
-                *pchDst++ = 0;
-
-                if (pfu32PathFlags && fLastComponentHasWildcard)
-                {
-                    *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_LAST;
-                }
-
-                /* Check the appended path for root escapes. */
-                if (fu32Options & VBSF_O_PATH_CHECK_ROOT_ESCAPE)
-                {
-                    rc = vbsfPathCheckRootEscape(&pszFullPath[cbRootLen]);
-                }
+
                 if (RT_SUCCESS(rc))
                 {
-                    /*
-                     * When the host file system is case sensitive and the guest expects
-                     * a case insensitive fs, then problems can occur.
-                     */
-                    if (    vbsfIsHostMappingCaseSensitive(hRoot)
-                        && !vbsfIsGuestMappingCaseSensitive(hRoot))
-                    {
-                        bool fWildCard = RT_BOOL(fu32Options & VBSF_O_PATH_WILDCARD);
-                        bool fPreserveLastComponent = RT_BOOL(fu32Options & VBSF_O_PATH_PRESERVE_LAST_COMPONENT);
-                        rc = vbsfCorrectPathCasing(pClient, pszFullPath, cbFullPathLength, fWildCard, fPreserveLastComponent);
-                    }
-
+                    const size_t cbFullPathLength = pchDst - &pszFullPath[0]; /* As strlen(pszFullPath). */
+                    *pchDst++ = 0;
+
+                    /* Construct the full host path removing '.' and '..'. */
+                    rc = RTPathAbsEx(pszRoot, pchVerifiedPath, pszFullPath, cbFullPathAlloc);
                     if (RT_SUCCESS(rc))
                     {
-                       LogFunc(("%s\n", pszFullPath));
-
-                       /* Return the full host path. */
-                       *ppszHostPath = pszFullPath;
-
-                       if (pcbHostPathRoot)
-                       {
-                           *pcbHostPathRoot = cbRootLen - 1; /* Must index the path delimiter. */
-                       }
+                        if (pfu32PathFlags && fLastComponentHasWildcard)
+                        {
+                            *pfu32PathFlags |= VBSF_F_PATH_HAS_WILDCARD_IN_LAST;
+                        }
+
+                        /* Check if the full path is still within the shared folder. */
+                        if (fu32Options & VBSF_O_PATH_CHECK_ROOT_ESCAPE)
+                        {
+                            if (!RTPathStartsWith(pszFullPath, pszRoot))
+                            {
+                                rc = VERR_INVALID_NAME;
+                            }
+                        }
+
+                        if (RT_SUCCESS(rc))
+                        {
+                            /*
+                             * If the host file system is case sensitive and the guest expects
+                             * a case insensitive fs, then correct the path components casing.
+                             */
+                            if (    vbsfIsHostMappingCaseSensitive(hRoot)
+                                && !vbsfIsGuestMappingCaseSensitive(hRoot))
+                            {
+                                const bool fWildCard = RT_BOOL(fu32Options & VBSF_O_PATH_WILDCARD);
+                                const bool fPreserveLastComponent = RT_BOOL(fu32Options & VBSF_O_PATH_PRESERVE_LAST_COMPONENT);
+                                rc = vbsfCorrectPathCasing(pClient, pszFullPath, cbFullPathLength,
+                                                           fWildCard, fPreserveLastComponent);
+                            }
+
+                            if (RT_SUCCESS(rc))
+                            {
+                               LogFlowFunc(("%s\n", pszFullPath));
+
+                               /* Return the full host path. */
+                               *ppszHostPath = pszFullPath;
+
+                               if (pcbHostPathRoot)
+                               {
+                                   /* Return the length of the root path without the trailing slash. */
+                                   *pcbHostPathRoot = RTPATH_IS_SLASH(pszFullPath[cbRootLen - 1]) ?
+                                                          cbRootLen - 1 : /* pszRoot already had the trailing slash. */
+                                                          cbRootLen; /* pszRoot did not have the trailing slash. */
+                               }
+                            }
+                        }
                     }
-                }
+                    else
+                    {
+                        LogFunc(("RTPathAbsEx %Rrc\n", rc));
+                    }
+                }
+
+                RTMemFree(pchVerifiedPath);
+            }
+            else
+            {
+                rc = VERR_NO_MEMORY;
             }
         }
@@ -738,4 +682,5 @@
     RTMemFree(pszFullPath);
 
+    LogFunc(("%Rrc\n", rc));
     return rc;
 }
