From 93d7057293e32cb0c4781ba933a82341e10801de Mon Sep 17 00:00:00 2001
From: Francois Gouget <fgouget@psn.net>
Date: Sun, 9 Jan 2000 21:34:34 +0000
Subject: [PATCH] DOSFS_DoGetFullPathName would underflow (p would get past the
 beginning of buffer) if given the name "//..". Regrouped the handling of the
 directory separators. Directory separators in the returned path are now alway
 a single "\" which simplifies the handling of ".." in the name.

---
 files/dos_fs.c | 56 ++++++++++++++++++++++++++------------------------
 1 file changed, 29 insertions(+), 27 deletions(-)

diff --git a/files/dos_fs.c b/files/dos_fs.c
index ac263750af9..64fbdb4e9ba 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -1058,28 +1058,24 @@ static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
     char *p;
     DWORD ret;
     
-    /* last possible position for a char != 0 */
-    char *endchar = buffer + sizeof(buffer) - 2;
-    *endchar = '\0';
+    /* Address of the last byte in the buffer */
+    char *endbuf = buffer + sizeof(buffer) - 1;
     
     TRACE("converting '%s'\n", name );
 
     if (!name || ((drive = DOSFS_GetPathDrive( &name )) == -1) )
-    {   SetLastError( ERROR_INVALID_PARAMETER );
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
         return 0;
     }
 
     p = buffer;
     *p++ = 'A' + drive;
     *p++ = ':';
-    if (IS_END_OF_NAME(*name) && (*name))  /* Absolute path */
-    {
-        while (((*name == '\\') || (*name == '/')) && (!*endchar) )
-	    *p++ = *name++;
-    }
-    else  /* Relative path or empty path */
+    *p++ = '\\';
+    if ((*name!='/') && (*name!='\\'))
     {
-        *p++ = '\\';
+        /* Relative path or empty path */
         lstrcpynA( p, DRIVE_GetDosCwd(drive), sizeof(buffer) - 4 );
         if ( *p )
         {
@@ -1087,41 +1083,47 @@ static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
 	    *p++ = '\\';
         }
     }
-    *p = '\0';
 
     while (*name)
     {
+        while ((*name == '\\') || (*name == '/'))
+	    name++;
         if (*name == '.')
         {
             if (IS_END_OF_NAME(name[1]))
             {
                 name++;
-                while ((*name == '\\') || (*name == '/')) name++;
                 continue;
             }
             else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
             {
-                name += 2;
-                while ((*name == '\\') || (*name == '/')) name++;
-
-		if (p < buffer + 3) /* no previous dir component */
-		    continue;
-		p--; /* skip previously added '\\' */
-		while ((*p == '\\') || (*p == '/')) p--;
+		if (p == buffer + 3) {
+                    /* no previous dir component */
+                    SetLastError( ERROR_PATH_NOT_FOUND );
+                    return 0;
+                }
+                /* skip previously added '\\' */
+		p-=2;
 		/* skip previous dir component */
-                while ((*p != '\\') && (*p != '/')) p--;
+                while (*p != '\\')
+                    p--;
                 p++;
+
+                name += 2;
                 continue;
             }
         }
-        if ( *endchar )
-        {   SetLastError( ERROR_PATH_NOT_FOUND );
+        while (!IS_END_OF_NAME(*name) && (p<endbuf) )
+            *p++ = *name++;
+        if ((p<endbuf) && ((*name == '\\') || (*name == '/'))) {
+            *p++='\\';
+            name++;
+        }
+        if ( p==endbuf && *name )
+        {
+            SetLastError( ERROR_PATH_NOT_FOUND );
             return 0;
         }
-        while (!IS_END_OF_NAME(*name) && (!*endchar) )
-            *p++ = *name++;
-        while (((*name == '\\') || (*name == '/')) && (!*endchar) )
-	    *p++ = *name++;
     }
     *p = '\0';
 
-- 
GitLab