[PATCH] kernelbase: Fix stack overflow by DefineDosDeviceW().

Xu Wei xuwei at uniontech.com
Wed Mar 9 00:34:37 CST 2022


Signed-off-by: Xu Wei <xuwei at uniontech.com>
---
 dlls/kernel32/tests/volume.c | 10 ++++++++++
 dlls/kernelbase/volume.c     | 17 +++++++++++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/dlls/kernel32/tests/volume.c b/dlls/kernel32/tests/volume.c
index 3bc3c7e4872..10746dd6507 100644
--- a/dlls/kernel32/tests/volume.c
+++ b/dlls/kernel32/tests/volume.c
@@ -112,6 +112,7 @@ static void test_dos_devices(void)
 {
     char buf[MAX_PATH], buf2[400];
     char drivestr[3];
+    WCHAR drivestrW[3];
     HANDLE file;
     BOOL ret;
 
@@ -186,6 +187,15 @@ static void test_dos_devices(void)
     ret = QueryDosDeviceA( drivestr, buf, sizeof(buf) );
     ok(!ret, "expected failure\n");
     ok(GetLastError() == ERROR_FILE_NOT_FOUND, "got error %lu\n", GetLastError());
+
+    SetLastError(0);
+    ret = DefineDosDeviceW( DDD_RAW_TARGET_PATH, drivestrW, NULL );
+    ok(!ret, "expected failure\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
+
+    SetLastError(0);
+    ret = DefineDosDeviceW ( DDD_RAW_TARGET_PATH,L"C:/windows/",L"\\Device\\C:/windows/" );
+    ok(ret, "got error %u\n", GetLastError());
 }
 
 static void test_FindFirstVolume(void)
diff --git a/dlls/kernelbase/volume.c b/dlls/kernelbase/volume.c
index 39386867aa3..d604ee02500 100644
--- a/dlls/kernelbase/volume.c
+++ b/dlls/kernelbase/volume.c
@@ -384,7 +384,7 @@ err_ret:
  */
 BOOL WINAPI DECLSPEC_HOTPATCH DefineDosDeviceW( DWORD flags, const WCHAR *device, const WCHAR *target )
 {
-    WCHAR link_name[15] = L"\\DosDevices\\";
+    WCHAR *link_name = NULL;
     UNICODE_STRING nt_name, nt_target;
     OBJECT_ATTRIBUTES attr;
     NTSTATUS status;
@@ -395,17 +395,28 @@ BOOL WINAPI DECLSPEC_HOTPATCH DefineDosDeviceW( DWORD flags, const WCHAR *device
     if (flags & ~(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION))
         FIXME("Ignoring flags %#lx.\n", flags & ~(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION));
 
-    lstrcatW( link_name, device );
+    if (!(link_name = HeapAlloc( GetProcessHeap(), 0, sizeof(L"\\DosDevices\\") + (device ? lstrlenW(device)*sizeof(WCHAR) : 0))))
+    {
+        SetLastError(ERROR_OUTOFMEMORY);
+        return FALSE;
+    }
+
+    lstrcpyW( link_name, L"\\DosDevices\\" );
+    if (device) lstrcatW( link_name, device );
     RtlInitUnicodeString( &nt_name, link_name );
     InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 0, NULL );
     if (flags & DDD_REMOVE_DEFINITION)
     {
         if (!set_ntstatus( NtOpenSymbolicLinkObject( &handle, 0, &attr ) ))
+        {
+            HeapFree( GetProcessHeap(), 0, link_name );
             return FALSE;
+        }
 
         status = NtMakeTemporaryObject( handle );
         NtClose( handle );
 
+        HeapFree( GetProcessHeap(), 0, link_name );
         return set_ntstatus( status );
     }
 
@@ -414,6 +425,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH DefineDosDeviceW( DWORD flags, const WCHAR *device
         if (!RtlDosPathNameToNtPathName_U( target, &nt_target, NULL, NULL))
         {
             SetLastError( ERROR_PATH_NOT_FOUND );
+            HeapFree( GetProcessHeap(), 0, link_name );
             return FALSE;
         }
     }
@@ -422,6 +434,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH DefineDosDeviceW( DWORD flags, const WCHAR *device
 
     if (!(status = NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, &nt_target )))
         NtClose( handle );
+    HeapFree( GetProcessHeap(), 0, link_name );
     return set_ntstatus( status );
 }
 
-- 
2.20.1






More information about the wine-devel mailing list