[ros-diffs] [fireball] 50954: [RTL/PATH] - Update path.c code to Wine 1.3.14. Fixes a buffer overwrite happening in RtlDosSearchPath_U() when invoked by "shell32_winetest.exe shlexec". - RtlDosPathNameToNtPath...

fireball at svn.reactos.org fireball at svn.reactos.org
Wed Mar 2 11:42:31 UTC 2011


Author: fireball
Date: Wed Mar  2 11:42:30 2011
New Revision: 50954

URL: http://svn.reactos.org/svn/reactos?rev=50954&view=rev
Log:
[RTL/PATH]
- Update path.c code to Wine 1.3.14. Fixes a buffer overwrite happening in RtlDosSearchPath_U() when invoked by "shell32_winetest.exe shlexec".
- RtlDosPathNameToNtPathName_U remains unsynced.
- Author names added to the header of the file.
See issue #5964 for more details.

Modified:
    trunk/reactos/lib/rtl/path.c

Modified: trunk/reactos/lib/rtl/path.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/path.c?rev=50954&r1=50953&r2=50954&view=diff
==============================================================================
--- trunk/reactos/lib/rtl/path.c [iso-8859-1] (original)
+++ trunk/reactos/lib/rtl/path.c [iso-8859-1] Wed Mar  2 11:42:30 2011
@@ -3,7 +3,9 @@
  * PROJECT:         ReactOS system libraries
  * FILE:            lib/rtl/path.c
  * PURPOSE:         Path and current directory functions
- * PROGRAMMERS:
+ * PROGRAMMERS:     Wine team
+ *                  Thomas Weidenmueller
+ *                  Gunnar Dalsnes
  */
 
 /* INCLUDES *****************************************************************/
@@ -112,30 +114,24 @@
         if (!_wcsicmp( dos_name, consoleW ))
             return MAKELONG( sizeof(conW), 4 * sizeof(WCHAR) );  /* 4 is length of \\.\ prefix */
         return 0;
+    case RtlPathTypeDriveAbsolute:
+    case RtlPathTypeDriveRelative:
+        start = dos_name + 2;  /* skip drive letter */
+        break;
     default:
+        start = dos_name;
         break;
     }
 
-    end = dos_name + wcslen(dos_name) - 1;
-    while (end >= dos_name && *end == ':') end--;  /* remove all trailing ':' */
-
     /* find start of file name */
-    for (start = end; start >= dos_name; start--)
-    {
-        if (IS_PATH_SEPARATOR(start[0])) break;
-        /* check for ':' but ignore if before extension (for things like NUL:.txt) */
-        if (start[0] == ':' && start[1] != '.') break;
-    }
-    start++;
-
-    /* remove extension */
-    if ((p = wcschr( start, '.' )))
-    {
-        end = p - 1;
-        if (end >= dos_name && *end == ':') end--;  /* remove trailing ':' before extension */
-    }
+    for (p = start; *p; p++) if (IS_PATH_SEPARATOR(*p)) start = p + 1;
+
+    /* truncate at extension and ':' */
+    for (end = start; *end; end++) if (*end == '.' || *end == ':') break;
+    end--;
+
     /* remove trailing spaces */
-    while (end >= dos_name && *end == ' ') end--;
+    while (end >= start && *end == ' ') end--;
 
     /* now we have a potential device name between start and end, check it */
     switch(end - start + 1)
@@ -218,6 +214,8 @@
 
    DPRINT("RtlSetCurrentDirectory %wZ\n", dir);
 
+   full.Buffer = NULL;
+
    RtlAcquirePebLock ();
 
    cd = (PCURDIR)&NtCurrentPeb ()->ProcessParameters->CurrentDirectory.DosPath;
@@ -287,16 +285,13 @@
 }
 
 
-
 /******************************************************************
- *    collapse_path
+ *		collapse_path
  *
  * Helper for RtlGetFullPathName_U.
- * 1) Convert slashes into backslashes
- * 2) Get rid of duplicate backslashes
- * 3) Get rid of . and .. components in the path.
- */
-static __inline void collapse_path( WCHAR *path, UINT mark )
+ * Get rid of . and .. components in the path.
+ */
+void FORCEINLINE collapse_path( WCHAR *path, UINT mark )
 {
     WCHAR *p, *next;
 
@@ -469,9 +464,11 @@
                 tmp[1] = ':';
                 tmp[2] = '\\';
                 ins_str = tmp;
+                RtlFreeHeap(RtlGetProcessHeap(), 0, val.Buffer);
                 break;
             default:
                 DPRINT1("Unsupported status code\n");
+                RtlFreeHeap(RtlGetProcessHeap(), 0, val.Buffer);
                 break;
             }
             mark = 3;
@@ -554,7 +551,7 @@
     if (reqsize) memcpy(buffer, ins_str, reqsize);
     reqsize += deplen;
 
-    if (ins_str && ins_str != tmp && ins_str != cd->Buffer)
+    if (ins_str != tmp && ins_str != cd->Buffer)
         RtlFreeHeap(RtlGetProcessHeap(), 0, ins_str);
 
     collapse_path( buffer, mark );
@@ -614,10 +611,9 @@
     if (reqsize > size)
     {
         LPWSTR tmp = RtlAllocateHeap(RtlGetProcessHeap(), 0, reqsize);
-        if (tmp == NULL)
-            return 0;
+        if (tmp == NULL) return 0;
         reqsize = get_full_path_helper(name, tmp, reqsize);
-        if (reqsize > size)  /* it may have worked the second time */
+        if (reqsize + sizeof(WCHAR) > size)  /* it may have worked the second time */
         {
             RtlFreeHeap(RtlGetProcessHeap(), 0, tmp);
             return reqsize + sizeof(WCHAR);
@@ -799,77 +795,79 @@
 /*
  * @implemented
  */
+/******************************************************************
+ *		RtlDosSearchPath_U
+ *
+ * Searches a file of name 'name' into a ';' separated list of paths
+ * (stored in paths)
+ * Doesn't seem to search elsewhere than the paths list
+ * Stores the result in buffer (file_part will point to the position
+ * of the file name in the buffer)
+ * FIXME:
+ * - how long shall the paths be ??? (MAX_PATH or larger with \\?\ constructs ???)
+ */
 ULONG
 NTAPI
-RtlDosSearchPath_U (
-	PCWSTR sp,
-	PCWSTR name,
-	PCWSTR ext,
-	ULONG buf_sz,
-	WCHAR *buffer,
-	PWSTR *FilePart
-	)
-{
-	ULONG Type;
-	ULONG Length = 0;
-	PWSTR full_name;
-	PWSTR wcs;
-	PCWSTR path;
-
-	Type = RtlDetermineDosPathNameType_U (name);
-
-	if (Type == 5)
-	{
-		Length = wcslen (sp);
-		Length += wcslen (name);
-		if (wcschr (name, L'.'))
-			ext = NULL;
-		if (ext != NULL)
-			Length += wcslen (ext);
-
-		full_name = (WCHAR*)RtlAllocateHeap (RtlGetProcessHeap (),
-		                                     0,
-		                                     (Length + 1) * sizeof(WCHAR));
-		Length = 0;
-		if (full_name != NULL)
-		{
-			path = sp;
-			while (*path)
-			{
-				wcs = full_name;
-				while (*path && *path != L';')
-					*wcs++ = *path++;
-				if (*path)
-					path++;
-				if (wcs != full_name && *(wcs - 1) != L'\\')
-					*wcs++ = L'\\';
-				wcscpy (wcs, name);
-				if (ext)
-					wcscat (wcs, ext);
-				if (RtlDoesFileExists_U (full_name))
-				{
-					Length = RtlGetFullPathName_U (full_name,
-					                               buf_sz,
-					                               buffer,
-					                               FilePart);
-					break;
-				}
-			}
-
-			RtlFreeHeap (RtlGetProcessHeap (),
-			             0,
-			             full_name);
-		}
-	}
-	else if (RtlDoesFileExists_U (name))
-	{
-		Length = RtlGetFullPathName_U (name,
-		                               buf_sz,
-		                               buffer,
-		                               FilePart);
-	}
-
-	return Length;
+RtlDosSearchPath_U(PCWSTR paths,
+                   PCWSTR search,
+                   PCWSTR ext,
+                   ULONG buffer_size,
+                   PWSTR buffer,
+                   PWSTR* file_part)
+{
+    RTL_PATH_TYPE type = RtlDetermineDosPathNameType_U(search);
+    ULONG len = 0;
+
+    if (type == RtlPathTypeRelative)
+    {
+        ULONG allocated = 0, needed, filelen;
+        WCHAR *name = NULL;
+
+        filelen = 1 /* for \ */ + wcslen(search) + 1 /* \0 */;
+
+        /* Windows only checks for '.' without worrying about path components */
+        if (wcschr( search, '.' )) ext = NULL;
+        if (ext != NULL) filelen += wcslen(ext);
+
+        while (*paths)
+        {
+            LPCWSTR ptr;
+
+            for (needed = 0, ptr = paths; *ptr != 0 && *ptr++ != ';'; needed++);
+            if (needed + filelen > allocated)
+            {
+                if (!name) name = RtlAllocateHeap(RtlGetProcessHeap(), 0,
+                                                  (needed + filelen) * sizeof(WCHAR));
+                else
+                {
+                    WCHAR *newname = RtlReAllocateHeap(RtlGetProcessHeap(), 0, name,
+                                                       (needed + filelen) * sizeof(WCHAR));
+                    if (!newname) RtlFreeHeap(RtlGetProcessHeap(), 0, name);
+                    name = newname;
+                }
+                if (!name) return 0;
+                allocated = needed + filelen;
+            }
+            memmove(name, paths, needed * sizeof(WCHAR));
+            /* append '\\' if none is present */
+            if (needed > 0 && name[needed - 1] != '\\') name[needed++] = '\\';
+            wcscpy(&name[needed], search);
+            if (ext) wcscat(&name[needed], ext);
+            if (RtlDoesFileExists_U(name))
+            {
+                len = RtlGetFullPathName_U(name, buffer_size, buffer, file_part);
+                break;
+            }
+            paths = ptr;
+        }
+        RtlFreeHeap(RtlGetProcessHeap(), 0, name);
+    }
+    else if (RtlDoesFileExists_U(search))
+    {
+        len = RtlGetFullPathName_U(search, buffer_size, buffer, file_part);
+    }
+
+    return len;
 }
 
 
@@ -881,10 +879,9 @@
 {
 	UNICODE_STRING NtFileName;
 	OBJECT_ATTRIBUTES Attr;
-   FILE_BASIC_INFORMATION Info;
+    FILE_BASIC_INFORMATION Info;
 	NTSTATUS Status;
 	CURDIR CurDir;
-
 
 	if (!RtlDosPathNameToNtPathName_U (FileName,
 	                                   &NtFileName,
@@ -905,7 +902,7 @@
 
 	Status = ZwQueryAttributesFile (&Attr, &Info);
 
-   RtlFreeUnicodeString(&NtFileName);
+    RtlFreeUnicodeString(&NtFileName);
 
 
 	if (NT_SUCCESS(Status) ||




More information about the Ros-diffs mailing list