Andrew Nguyen : kernel32: Reject a format string with insertions if no variadic arguments are passed to FormatMessageA /W.
Alexandre Julliard
julliard at winehq.org
Mon May 3 11:54:06 CDT 2010
Module: wine
Branch: master
Commit: f2c91f0d3c7203a4394eded89a54759e765aa8a0
URL: http://source.winehq.org/git/wine.git/?a=commit;h=f2c91f0d3c7203a4394eded89a54759e765aa8a0
Author: Andrew Nguyen <anguyen at codeweavers.com>
Date: Sat May 1 03:40:46 2010 -0500
kernel32: Reject a format string with insertions if no variadic arguments are passed to FormatMessageA/W.
---
dlls/kernel32/format_msg.c | 7 ++++
dlls/kernel32/tests/format_msg.c | 64 ++++++++++++++++++++++++++++++++++++++
2 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/dlls/kernel32/format_msg.c b/dlls/kernel32/format_msg.c
index 302a78d..b1befb3 100644
--- a/dlls/kernel32/format_msg.c
+++ b/dlls/kernel32/format_msg.c
@@ -296,6 +296,13 @@ static LPWSTR format_message( BOOL unicode_caller, DWORD dwFlags, LPCWSTR fmtstr
case '6':case '7':case '8':case '9':
if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS)
goto ignore_inserts;
+ else if (((dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) && !format_args->args) ||
+ (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) && !format_args->list))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ HeapFree(GetProcessHeap(), 0, target);
+ return NULL;
+ }
insertnr = *f-'0';
switch (f[1]) {
case '0':case '1':case '2':case '3':
diff --git a/dlls/kernel32/tests/format_msg.c b/dlls/kernel32/tests/format_msg.c
index 25be3ac..1c4dd76 100644
--- a/dlls/kernel32/tests/format_msg.c
+++ b/dlls/kernel32/tests/format_msg.c
@@ -180,6 +180,27 @@ static void test_message_from_string_wide(void)
ok(r==0, "succeeded: r=%d\n", r);
ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error);
+ /* insertion with no variadic arguments */
+ SetLastError(0xdeadbeef);
+ memcpy(out, init_buf, sizeof(init_buf));
+ r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_1, 0,
+ 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ error = GetLastError();
+ ok(!memcmp(out, init_buf, sizeof(init_buf)),
+ "Expected the buffer to be unchanged\n");
+ ok(r==0, "succeeded: r=%d\n", r);
+ ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error);
+
+ SetLastError(0xdeadbeef);
+ memcpy(out, init_buf, sizeof(init_buf));
+ r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, fmt_1, 0,
+ 0, out, sizeof(out)/sizeof(WCHAR), NULL);
+ error = GetLastError();
+ ok(!memcmp(out, init_buf, sizeof(init_buf)),
+ "Expected the buffer to be unchanged\n");
+ ok(r==0, "succeeded: r=%d\n", r);
+ ok(error==ERROR_INVALID_PARAMETER, "last error %u\n", error);
+
/* using the format feature */
r = doitW(FORMAT_MESSAGE_FROM_STRING, fmt_1s, 0,
0, out, sizeof(out)/sizeof(WCHAR), test);
@@ -483,6 +504,35 @@ static void test_message_from_string(void)
ok(GetLastError()==ERROR_INVALID_PARAMETER,
"last error %u\n", GetLastError());
+ /* insertion with no variadic arguments */
+ SetLastError(0xdeadbeef);
+ memcpy(out, init_buf, sizeof(init_buf));
+ r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "%1", 0,
+ 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
+ broken(!strcmp("%1", out)), /* Win9x */
+ "Expected the buffer to be untouched\n");
+ ok(r==0 ||
+ broken(r==2), /* Win9x */
+ "succeeded: r=%d\n", r);
+ ok(GetLastError()==ERROR_INVALID_PARAMETER ||
+ broken(GetLastError()==0xdeadbeef), /* Win9x */
+ "last error %u\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ memcpy(out, init_buf, sizeof(init_buf));
+ r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, "%1", 0,
+ 0, out, sizeof(out)/sizeof(CHAR), NULL);
+ ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
+ broken(!strcmp("%1", out)), /* Win9x */
+ "Expected the buffer to be untouched\n");
+ ok(r==0 ||
+ broken(r==2), /* Win9x */
+ "succeeded: r=%d\n", r);
+ ok(GetLastError()==ERROR_INVALID_PARAMETER ||
+ broken(GetLastError()==0xdeadbeef), /* Win9x */
+ "last error %u\n", GetLastError());
+
/* using the format feature */
r = doit(FORMAT_MESSAGE_FROM_STRING, "%1!s!", 0,
0, out, sizeof(out)/sizeof(CHAR), "test");
@@ -1340,6 +1390,20 @@ static void test_message_from_hmodule(void)
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
ok(ret != 0, "FormatMessageA returned 0\n");
+ /* Test a message string with an insertion without passing any variadic arguments. */
+ ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 193 /* ERROR_BAD_EXE_FORMAT */,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
+ ok(ret == 0 ||
+ broken(ret != 0), /* Win9x */
+ "FormatMessageA returned non-zero\n");
+
+ ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY, h, 193 /* ERROR_BAD_EXE_FORMAT */,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), out, sizeof(out)/sizeof(CHAR), NULL);
+ ok(ret == 0 ||
+ broken(ret != 0), /* Win9x */
+ "FormatMessageA returned non-zero\n");
+
/*Test nonexistent messageID with varying language ID's Note: FormatMessageW behaves the same*/
SetLastError(0xdeadbeef);
ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, h, 3044,
More information about the wine-cvs
mailing list