gdi32: Make sure that we don't read/write beyond the provided buffer in GetOutlineTextMetricsA, add a test case.

This commit is contained in:
Dmitry Timoshkov 2007-02-02 18:18:15 +08:00 committed by Alexandre Julliard
parent b18cc05965
commit e915a3cfb1
2 changed files with 110 additions and 8 deletions

View File

@ -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:

View File

@ -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();
}