gdi32: Make sure that we don't read/write beyond the provided
buffer in GetOutlineTextMetricsA, add a test case
Dmitry Timoshkov
dmitry at codeweavers.com
Fri Feb 2 04:18:15 CST 2007
Hello,
this patch should fix the bugs #6376 and #7080, the test case passes
under XP and Win9x.
Changelog:
gdi32: Make sure that we don't read/write beyond the provided buffer
in GetOutlineTextMetricsA, add a test case.
---
dlls/gdi32/font.c | 32 +++++++++++++----
dlls/gdi32/tests/font.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 8 deletions(-)
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 527a0d9..ee57ba8 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -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:
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index e18bffe..670ec36 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -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();
}
--
1.4.4.4
More information about the wine-patches
mailing list