[WIN32K] Allocate a buffer for a classname that is too long

This commit is contained in:
Mark Jansen 2019-03-07 00:13:19 +01:00
parent e6e45b34cc
commit dd8f30f879
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B

View file

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