https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dd8f30f879c772c400047c1186d656aeae078e5d

commit dd8f30f879c772c400047c1186d656aeae078e5d
Author:     Mark Jansen <[email protected]>
AuthorDate: Thu Mar 7 00:13:19 2019 +0100
Commit:     Mark Jansen <[email protected]>
CommitDate: Mon Apr 27 12:54:10 2020 +0200

    [WIN32K] Allocate a buffer for a classname that is too long
---
 win32ss/user/ntuser/class.c | 90 ++++++++++++++++++++++++++++++---------------
 1 file changed, 60 insertions(+), 30 deletions(-)

diff --git a/win32ss/user/ntuser/class.c b/win32ss/user/ntuser/class.c
index d669340baf7..9210852dca7 100644
--- a/win32ss/user/ntuser/class.c
+++ b/win32ss/user/ntuser/class.c
@@ -335,31 +335,54 @@ IntRegisterClassAtom(IN PUNICODE_STRING ClassName,
                      OUT RTL_ATOM *pAtom)
 {
     WCHAR szBuf[65];
-    PWSTR AtomName;
+    PWSTR AtomName = szBuf;
     NTSTATUS Status;
 
     if (ClassName->Length != 0)
     {
-        /* FIXME: Don't limit to 64 characters! Use SEH when allocating 
memory! */
-        if (ClassName->Length / sizeof(WCHAR) >= sizeof(szBuf) / 
sizeof(szBuf[0]))
+        if (ClassName->Length + sizeof(UNICODE_NULL) > sizeof(szBuf))
         {
-            EngSetLastError(ERROR_INVALID_PARAMETER);
-            return (RTL_ATOM)0;
+            AtomName = ExAllocatePoolWithTag(PagedPool,
+                                             ClassName->Length + 
sizeof(UNICODE_NULL),
+                                             TAG_USTR);
+
+            if (AtomName == NULL)
+            {
+                EngSetLastError(ERROR_OUTOFMEMORY);
+                return FALSE;
+            }
         }
 
-        RtlCopyMemory(szBuf,
-                      ClassName->Buffer,
-                      ClassName->Length);
-        szBuf[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
-        AtomName = szBuf;
+        _SEH2_TRY
+        {
+            RtlCopyMemory(AtomName,
+                          ClassName->Buffer,
+                          ClassName->Length);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            if (AtomName != szBuf)
+                ExFreePoolWithTag(AtomName, TAG_USTR);
+            SetLastNtError(_SEH2_GetExceptionCode());
+            _SEH2_YIELD(return FALSE);
+        }
+        _SEH2_END;
+        AtomName[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
     }
     else
+    {
+        ASSERT(IS_ATOM(ClassName->Buffer));
         AtomName = ClassName->Buffer;
+    }
 
     Status = RtlAddAtomToAtomTable(gAtomTable,
                                    AtomName,
                                    pAtom);
 
+    if (AtomName != ClassName->Buffer && AtomName != szBuf)
+        ExFreePoolWithTag(AtomName, TAG_USTR);
+
+
     if (!NT_SUCCESS(Status))
     {
         SetLastNtError(Status);
@@ -1275,39 +1298,46 @@ IntGetAtomFromStringOrAtom(
     if (ClassName->Length != 0)
     {
         WCHAR szBuf[65];
-        PWSTR AtomName;
-        NTSTATUS Status;
+        PWSTR AtomName = szBuf;
+        NTSTATUS Status = STATUS_INVALID_PARAMETER;
 
         *Atom = 0;
 
         /* NOTE: Caller has to protect the call with SEH! */
-
-        if (ClassName->Length != 0)
+        if (ClassName->Length + sizeof(UNICODE_NULL) > sizeof(szBuf))
         {
-            /* FIXME: Don't limit to 64 characters! use SEH when allocating 
memory! */
-            if (ClassName->Length / sizeof(WCHAR) >= sizeof(szBuf) / 
sizeof(szBuf[0]))
+            AtomName = ExAllocatePoolWithTag(PagedPool,
+                                             ClassName->Length + 
sizeof(UNICODE_NULL),
+                                             TAG_USTR);
+            if (AtomName == NULL)
             {
-                EngSetLastError(ERROR_INVALID_PARAMETER);
-                return (RTL_ATOM)0;
+                EngSetLastError(ERROR_OUTOFMEMORY);
+                return FALSE;
             }
+        }
 
-            /* We need to make a local copy of the class name! The caller could
-               modify the buffer and we could overflow in 
RtlLookupAtomInAtomTable.
-               We're protected by SEH, but the ranges that might be accessed 
were
-               not probed... */
-            RtlCopyMemory(szBuf,
+        _SEH2_TRY
+        {
+            RtlCopyMemory(AtomName,
                           ClassName->Buffer,
                           ClassName->Length);
-            szBuf[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
-            AtomName = szBuf;
         }
-        else
-            AtomName = ClassName->Buffer;
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            if (AtomName != szBuf)
+                ExFreePoolWithTag(AtomName, TAG_USTR);
+            SetLastNtError(_SEH2_GetExceptionCode());
+            _SEH2_YIELD(return FALSE);
+        }
+        _SEH2_END;
+        AtomName[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
 
         /* Lookup the atom */
-        Status = RtlLookupAtomInAtomTable(gAtomTable,
-                                          AtomName,
-                                          Atom);
+        Status = RtlLookupAtomInAtomTable(gAtomTable, AtomName, Atom);
+
+        if (AtomName != szBuf)
+            ExFreePoolWithTag(AtomName, TAG_USTR);
+
         if (NT_SUCCESS(Status))
         {
             Ret = TRUE;

Reply via email to