[ADVAPI32]

- ConvertStringSidToSidW: Stop writing 1 subauthority too much. Fixes a DWORD sized buffer overflow. Should fix bug #5764.
- ConvertStringSidToSidW: Don't leak an allocated SID in case of failure.
[SETUPAPI]
- SetupDiClassNameFromGuidExW: Rewrite to prevent a buffer overflow and pass additional winetests. Should fix bug #5474.
- SetupDiClassNameFromGuidExA: Return the required buffer size in failure cases.

svn path=/trunk/; revision=50066
This commit is contained in:
Roel Messiant 2010-12-19 23:19:04 +00:00
parent 4989fe718a
commit 8e7e8f566f
2 changed files with 87 additions and 63 deletions

View file

@ -1982,16 +1982,14 @@ ConvertStringSidToSidW(IN LPCWSTR StringSid,
if (*StringSid == '-') if (*StringSid == '-')
StringSid++; StringSid++;
pisid->SubAuthority[i] = atoiW(StringSid);
while (*StringSid) while (*StringSid)
{ {
pisid->SubAuthority[i++] = atoiW(StringSid);
while (*StringSid && *StringSid != '-') while (*StringSid && *StringSid != '-')
StringSid++; StringSid++;
if (*StringSid == '-') if (*StringSid == '-')
StringSid++; StringSid++;
pisid->SubAuthority[++i] = atoiW(StringSid);
} }
if (i != pisid->SubAuthorityCount) if (i != pisid->SubAuthorityCount)
@ -2002,7 +2000,10 @@ ConvertStringSidToSidW(IN LPCWSTR StringSid,
lend: lend:
if (!ret) if (!ret)
{
LocalFree(pisid);
SetLastError(ERROR_INVALID_SID); SetLastError(ERROR_INVALID_SID);
}
TRACE("returning %s\n", ret ? "TRUE" : "FALSE"); TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
return ret; return ret;

View file

@ -1103,7 +1103,7 @@ BOOL WINAPI SetupDiClassNameFromGuidExA(
if (MachineName) if (MachineName)
MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN, ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
NULL, MachineNameW, Reserved); RequiredSize, MachineNameW, Reserved);
if (ret) if (ret)
{ {
int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName, int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
@ -1113,8 +1113,6 @@ BOOL WINAPI SetupDiClassNameFromGuidExA(
SetLastError(ERROR_INSUFFICIENT_BUFFER); SetLastError(ERROR_INSUFFICIENT_BUFFER);
ret = FALSE; ret = FALSE;
} }
else if (RequiredSize)
*RequiredSize = len;
} }
MyFree(MachineNameW); MyFree(MachineNameW);
return ret; return ret;
@ -1135,73 +1133,98 @@ BOOL WINAPI SetupDiClassNameFromGuidExW(
DWORD dwLength; DWORD dwLength;
DWORD dwRegType; DWORD dwRegType;
LONG rc; LONG rc;
PWSTR Buffer;
TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName, TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved); ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
hKey = SetupDiOpenClassRegKeyExW(ClassGuid, /* Make sure there's a GUID */
KEY_QUERY_VALUE, if (ClassGuid == NULL)
DIOCR_INSTALLER, {
MachineName, SetLastError(ERROR_INVALID_CLASS); /* On Vista: ERROR_INVALID_USER_BUFFER */
Reserved); return FALSE;
}
/* Make sure there's a real buffer when there's a size */
if ((ClassNameSize > 0) && (ClassName == NULL))
{
SetLastError(ERROR_INVALID_PARAMETER); /* On Vista: ERROR_INVALID_USER_BUFFER */
return FALSE;
}
/* Open the key for the GUID */
hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INSTALLER, MachineName, Reserved);
if (hKey == INVALID_HANDLE_VALUE) if (hKey == INVALID_HANDLE_VALUE)
{
return FALSE;
}
if (RequiredSize != NULL)
{
dwLength = 0;
if (RegQueryValueExW(hKey,
Class,
NULL,
NULL,
NULL,
&dwLength))
{
RegCloseKey(hKey);
return FALSE;
}
*RequiredSize = dwLength / sizeof(WCHAR) + 1;
}
if (!ClassGuid)
{
SetLastError(ERROR_INVALID_CLASS);
RegCloseKey(hKey);
return FALSE; return FALSE;
}
if (!ClassName && ClassNameSize > 0)
{
SetLastError(ERROR_INVALID_PARAMETER);
RegCloseKey(hKey);
return FALSE;
}
dwLength = ClassNameSize * sizeof(WCHAR) - sizeof(UNICODE_NULL); /* Retrieve the class name data */
rc = RegQueryValueExW(hKey, dwLength = ClassNameSize * sizeof(WCHAR);
Class,
NULL, do
&dwRegType, {
(LPBYTE)ClassName, /* Allocate a buffer to retrieve the class name data */
&dwLength); Buffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
if (Buffer == NULL)
{
rc = GetLastError();
break;
}
/* Query for the class name data */
rc = RegQueryValueExW(hKey, Class, NULL, &dwRegType, (LPBYTE) Buffer, &dwLength);
/* Clean up the buffer if needed */
if (rc != ERROR_SUCCESS)
HeapFree(GetProcessHeap(), 0, Buffer);
} while (rc == ERROR_MORE_DATA);
/* Close the key */
RegCloseKey(hKey);
/* Make sure we got the data */
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
{ {
SetLastError(rc); SetLastError(rc);
RegCloseKey(hKey);
return FALSE;
}
if (dwRegType != REG_SZ)
{
SetLastError(ERROR_GEN_FAILURE);
RegCloseKey(hKey);
return FALSE; return FALSE;
} }
if (ClassNameSize > 1) /* Make sure the data is a string */
ClassName[ClassNameSize] = UNICODE_NULL; if (dwRegType != REG_SZ)
RegCloseKey(hKey); {
HeapFree(GetProcessHeap(), 0, Buffer);
SetLastError(ERROR_GEN_FAILURE);
return FALSE;
}
/* Determine the length of the class name */
dwLength /= sizeof(WCHAR);
if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
/* Count the null-terminator */
dwLength++;
/* Inform the caller about the class name */
if ((ClassName != NULL) && (dwLength <= ClassNameSize))
{
memcpy(ClassName, Buffer, (dwLength - 1) * sizeof(WCHAR));
ClassName[dwLength - 1] = UNICODE_NULL;
}
/* Inform the caller about the required size */
if (RequiredSize != NULL)
*RequiredSize = dwLength;
/* Clean up the buffer */
HeapFree(GetProcessHeap(), 0, Buffer);
/* Make sure the buffer was large enough */
if ((ClassName == NULL) || (dwLength > ClassNameSize))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return TRUE; return TRUE;
} }