gdi32: Make sure that we don't read/write beyond the provided buffer in GetOutlineTextMetricsA, add a test case.
This commit is contained in:
parent
b18cc05965
commit
e915a3cfb1
|
@ -1484,17 +1484,33 @@ UINT WINAPI GetOutlineTextMetricsA(
|
|||
|
||||
/* check if the string offsets really fit into the provided size */
|
||||
/* FIXME: should we check string length as well? */
|
||||
if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
|
||||
lpOTM->otmpFamilyName = 0; /* doesn't fit */
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
|
||||
{
|
||||
if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
|
||||
lpOTM->otmpFamilyName = 0; /* doesn't fit */
|
||||
}
|
||||
|
||||
if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
|
||||
lpOTM->otmpFaceName = 0; /* doesn't fit */
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
|
||||
{
|
||||
if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
|
||||
lpOTM->otmpFaceName = 0; /* doesn't fit */
|
||||
}
|
||||
|
||||
if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
|
||||
lpOTM->otmpStyleName = 0; /* doesn't fit */
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
|
||||
{
|
||||
if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
|
||||
lpOTM->otmpStyleName = 0; /* doesn't fit */
|
||||
}
|
||||
|
||||
if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
|
||||
lpOTM->otmpFullName = 0; /* doesn't fit */
|
||||
/* make sure that we don't read/write beyond the provided buffer */
|
||||
if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
|
||||
{
|
||||
if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
|
||||
lpOTM->otmpFullName = 0; /* doesn't fit */
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
|
|
|
@ -732,6 +732,91 @@ todo_wine {
|
|||
ReleaseDC(0, hdc);
|
||||
}
|
||||
|
||||
static void test_GetOutlineTextMetrics(void)
|
||||
{
|
||||
OUTLINETEXTMETRIC *otm;
|
||||
LOGFONT lf;
|
||||
HFONT hfont, hfont_old;
|
||||
HDC hdc;
|
||||
DWORD ret, otm_size;
|
||||
|
||||
hdc = GetDC(0);
|
||||
|
||||
if (!is_font_installed("Arial"))
|
||||
{
|
||||
skip("Arial is not installed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&lf, 0, sizeof(lf));
|
||||
strcpy(lf.lfFaceName, "Arial");
|
||||
lf.lfHeight = -13;
|
||||
lf.lfWeight = FW_NORMAL;
|
||||
lf.lfPitchAndFamily = DEFAULT_PITCH;
|
||||
lf.lfQuality = PROOF_QUALITY;
|
||||
hfont = CreateFontIndirect(&lf);
|
||||
assert(hfont != 0);
|
||||
|
||||
hfont_old = SelectObject(hdc, hfont);
|
||||
otm_size = GetOutlineTextMetrics(hdc, 0, NULL);
|
||||
trace("otm buffer size %u (0x%x)\n", otm_size, otm_size);
|
||||
|
||||
otm = HeapAlloc(GetProcessHeap(), 0, otm_size);
|
||||
|
||||
memset(otm, 0xAA, otm_size);
|
||||
SetLastError(0xdeadbeef);
|
||||
otm->otmSize = sizeof(*otm); /* just in case for Win9x compatibility */
|
||||
ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
|
||||
ok(ret == 1 /* Win9x */ ||
|
||||
ret == otm->otmSize /* XP*/,
|
||||
"expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
|
||||
if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
|
||||
{
|
||||
ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
|
||||
ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
|
||||
ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
|
||||
ok(otm->otmpFullName == NULL, "expected NULL got %p\n", otm->otmpFullName);
|
||||
}
|
||||
|
||||
memset(otm, 0xAA, otm_size);
|
||||
SetLastError(0xdeadbeef);
|
||||
otm->otmSize = otm_size; /* just in case for Win9x compatibility */
|
||||
ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
|
||||
ok(ret == 1 /* Win9x */ ||
|
||||
ret == otm->otmSize /* XP*/,
|
||||
"expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
|
||||
if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
|
||||
{
|
||||
ok(otm->otmpFamilyName != NULL, "expected not NULL got %p\n", otm->otmpFamilyName);
|
||||
ok(otm->otmpFaceName != NULL, "expected not NULL got %p\n", otm->otmpFaceName);
|
||||
ok(otm->otmpStyleName != NULL, "expected not NULL got %p\n", otm->otmpStyleName);
|
||||
ok(otm->otmpFullName != NULL, "expected not NULL got %p\n", otm->otmpFullName);
|
||||
}
|
||||
|
||||
/* ask about truncated data */
|
||||
memset(otm, 0xAA, otm_size);
|
||||
SetLastError(0xdeadbeef);
|
||||
otm->otmSize = sizeof(*otm) - sizeof(LPSTR); /* just in case for Win9x compatibility */
|
||||
ret = GetOutlineTextMetrics(hdc, otm->otmSize, otm);
|
||||
ok(ret == 1 /* Win9x */ ||
|
||||
ret == otm->otmSize /* XP*/,
|
||||
"expected %u, got %u, error %d\n", otm->otmSize, ret, GetLastError());
|
||||
if (ret != 1) /* Win9x doesn't care about pointing beyond of the buffer */
|
||||
{
|
||||
ok(otm->otmpFamilyName == NULL, "expected NULL got %p\n", otm->otmpFamilyName);
|
||||
ok(otm->otmpFaceName == NULL, "expected NULL got %p\n", otm->otmpFaceName);
|
||||
ok(otm->otmpStyleName == NULL, "expected NULL got %p\n", otm->otmpStyleName);
|
||||
}
|
||||
ok(otm->otmpFullName == (LPSTR)0xAAAAAAAA, "expected 0xAAAAAAAA got %p\n", otm->otmpFullName);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, otm);
|
||||
|
||||
SelectObject(hdc, hfont_old);
|
||||
DeleteObject(hfont);
|
||||
|
||||
ReleaseDC(0, hdc);
|
||||
}
|
||||
|
||||
START_TEST(font)
|
||||
{
|
||||
test_logfont();
|
||||
|
@ -742,4 +827,5 @@ START_TEST(font)
|
|||
test_text_extents();
|
||||
test_GetGlyphIndices();
|
||||
test_GetKerningPairs();
|
||||
test_GetOutlineTextMetrics();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue