usp10/tests: Reserve for InClass a byte for every character in teststr. (v2)
Bernhard Übelacker
bernhardu at mailbox.org
Wed Aug 3 17:44:58 CDT 2016
https://bugs.winehq.org/show_bug.cgi?id=40385
ScriptStringAnalyse crashes if InClass is just one byte in size
followed by memory marked as PAGE_NOACCESS.
By testing the size it seems it should have the same size as characters
in teststr are given to the function.
v1:
https://www.winehq.org/pipermail/wine-patches/2016-August/153001.html
https://www.winehq.org/pipermail/wine-devel/2016-August/114173.html
Changes since v1:
- Avoid compiler warning by using static with explicit array length.
- Show trace just when we expect a crash.
- Check hr if we did not crash.
Signed-off-by: Bernhard Übelacker <bernhardu at mailbox.org>
---
dlls/usp10/tests/usp10.c | 103 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 95 insertions(+), 8 deletions(-)
diff --git a/dlls/usp10/tests/usp10.c b/dlls/usp10/tests/usp10.c
index 6b2152f..0fa34aa 100644
--- a/dlls/usp10/tests/usp10.c
+++ b/dlls/usp10/tests/usp10.c
@@ -2900,7 +2900,7 @@ static void test_ScriptString(HDC hdc)
DWORD Flags = SSA_GLYPHS;
int ReqWidth = 100;
const int Dx[5] = {10, 10, 10, 10, 10};
- const BYTE InClass = 0;
+ static const BYTE InClass[8]; /* Array size equal to String_len */
SCRIPT_STRING_ANALYSIS ssa = NULL;
int X = 10;
@@ -2919,26 +2919,26 @@ static void test_ScriptString(HDC hdc)
/* Test without hdc to get E_PENDING */
hr = ScriptStringAnalyse( NULL, teststr, len, Glyphs, Charset, Flags,
ReqWidth, NULL, NULL, Dx, NULL,
- &InClass, &ssa);
+ InClass, &ssa);
ok(hr == E_PENDING, "ScriptStringAnalyse Stub should return E_PENDING not %08x\n", hr);
/* Test that 0 length string returns E_INVALIDARG */
hr = ScriptStringAnalyse( hdc, teststr, 0, Glyphs, Charset, Flags,
ReqWidth, NULL, NULL, Dx, NULL,
- &InClass, &ssa);
+ InClass, &ssa);
ok(hr == E_INVALIDARG, "ScriptStringAnalyse should return E_INVALIDARG not %08x\n", hr);
/* test with hdc, this should be a valid test */
hr = ScriptStringAnalyse( hdc, teststr, len, Glyphs, Charset, Flags,
ReqWidth, NULL, NULL, Dx, NULL,
- &InClass, &ssa);
+ InClass, &ssa);
ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr);
ScriptStringFree(&ssa);
/* test makes sure that a call with a valid pssa still works */
hr = ScriptStringAnalyse( hdc, teststr, len, Glyphs, Charset, Flags,
ReqWidth, NULL, NULL, Dx, NULL,
- &InClass, &ssa);
+ InClass, &ssa);
ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr);
ok(ssa != NULL, "ScriptStringAnalyse pssa should not be NULL\n");
@@ -2982,7 +2982,7 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
int Charset = -1; /* unicode */
DWORD Flags = SSA_GLYPHS;
int ReqWidth = 100;
- const BYTE InClass = 0;
+ static const BYTE InClass[8]; /* Array size equal to String_len */
SCRIPT_STRING_ANALYSIS ssa = NULL;
int Ch; /* Character position in string */
@@ -2999,7 +2999,7 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
hr = ScriptStringAnalyse( hdc, String, String_len, Glyphs, Charset, Flags,
ReqWidth, NULL, NULL, NULL, NULL,
- &InClass, &ssa);
+ InClass, &ssa);
ok(hr == S_OK ||
hr == E_INVALIDARG, /* NT */
"ScriptStringAnalyse should return S_OK or E_INVALIDARG not %08x\n", hr);
@@ -3139,7 +3139,7 @@ static void test_ScriptStringXtoCP_CPtoX(HDC hdc)
*/
hr = ScriptStringAnalyse( hdc, String, String_len, Glyphs, Charset, Flags,
ReqWidth, NULL, NULL, NULL, NULL,
- &InClass, &ssa);
+ InClass, &ssa);
ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr);
/*
@@ -3610,6 +3610,89 @@ static void test_ScriptGetFontFunctions(HDC hdc)
}
}
+static DWORD get_pagesize(void)
+{
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+
+ return si.dwPageSize;
+}
+
+static void* get_guarded_memory(int size, int at_end_of_page, void**base_address)
+{
+ DWORD pagesize = get_pagesize();
+ char *buf;
+ char *ret;
+ DWORD old_protect = 0;
+
+ buf = VirtualAlloc(NULL, ((size / pagesize) + 3) * pagesize, MEM_COMMIT, PAGE_READWRITE);
+ if (!buf)
+ {
+ trace("VirtualAlloc failed\n");
+ return NULL;
+ }
+ *base_address = buf;
+
+ if (!VirtualProtect(buf, pagesize, PAGE_NOACCESS, &old_protect)) {
+ trace("VirtualProtect failed\n");
+ }
+
+ ret = buf + pagesize;
+ if (at_end_of_page) {
+ ret += pagesize - size;
+ }
+
+ if (!VirtualProtect(buf + (pagesize * 2), pagesize, PAGE_NOACCESS, &old_protect)) {
+ trace("VirtualProtect failed\n");
+ }
+
+ return ret;
+}
+
+static void free_guarded_memory(void* base_address)
+{
+ if (base_address)
+ {
+ if (!VirtualFree(base_address, 0, MEM_RELEASE))
+ trace("VirtualFree failed\n");
+ }
+}
+
+static void test_ScriptStringAnalyse_InClass_length(HDC hdc, int crash)
+{
+ HRESULT hr;
+ static const WCHAR teststr1[] = {0x05e9, 'i', 0x05dc, 'n', 0x05d5, 'e', 0x05dd, '.',0};
+ void *String = (WCHAR *) &teststr1; /* ScriptStringAnalysis needs void */
+ int String_len = (sizeof(teststr1)/sizeof(WCHAR))-1;
+ int Glyphs = String_len * 2 + 16; /* size of buffer as recommended */
+ int Charset = -1; /* unicode */
+ DWORD Flags = SSA_GLYPHS;
+ int ReqWidth = 100;
+ const BYTE *InClass;
+ SCRIPT_STRING_ANALYSIS ssa = NULL;
+
+ void* base_address = NULL;
+
+ /* Get a chunk of memory followed by memory with PAGE_NOACCESS to
+ * trigger an exception on access.
+ *
+ * Seems InClass should point to memory with at least the length String_len.
+ */
+ InClass = (BYTE*)get_guarded_memory(String_len - (crash?1:0), 1, &base_address);
+ *(BYTE*)InClass = 0;
+
+ if (crash)
+ trace("before ScriptStringAnalyse crash=%d\n", crash);
+ hr = ScriptStringAnalyse( hdc, String, String_len, Glyphs, Charset, Flags,
+ ReqWidth, NULL, NULL, NULL, NULL,
+ InClass, &ssa);
+ if (crash)
+ ok(0, "expected access violation but succeeded.\n");
+ ok(hr == S_OK, "ScriptStringAnalyse should return S_OK not %08x\n", hr);
+ ScriptStringFree(&ssa);
+ free_guarded_memory(base_address);
+}
+
START_TEST(usp10)
{
HWND hwnd;
@@ -3664,6 +3747,10 @@ START_TEST(usp10)
test_ScriptGetFontFunctions(hdc);
+ test_ScriptStringAnalyse_InClass_length(hdc, 0);
+ if (0)
+ test_ScriptStringAnalyse_InClass_length(hdc, 1); /* is supposed to crash */
+
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
}
--
2.1.4
More information about the wine-patches
mailing list