https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dd8f30f879c772c400047c...
commit dd8f30f879c772c400047c1186d656aeae078e5d Author: Mark Jansen mark.jansen@reactos.org AuthorDate: Thu Mar 7 00:13:19 2019 +0100 Commit: Mark Jansen mark.jansen@reactos.org 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;