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