Andrew Nguyen : kernel32: Fail if a format placeholder is present without a format specifier in FormatMessageA /W.

Alexandre Julliard julliard at winehq.org
Wed Apr 28 16:35:46 CDT 2010


Module: wine
Branch: master
Commit: 3cb43a081b4b062330c82900fbd1dee03b00cba7
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3cb43a081b4b062330c82900fbd1dee03b00cba7

Author: Andrew Nguyen <anguyen at codeweavers.com>
Date:   Wed Apr 28 04:20:19 2010 -0500

kernel32: Fail if a format placeholder is present without a format specifier in FormatMessageA/W.

---

 dlls/kernel32/format_msg.c       |    9 +++++-
 dlls/kernel32/tests/format_msg.c |   51 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/dlls/kernel32/format_msg.c b/dlls/kernel32/format_msg.c
index 4dbaf36..b6ffb7f 100644
--- a/dlls/kernel32/format_msg.c
+++ b/dlls/kernel32/format_msg.c
@@ -297,8 +297,9 @@ static LPWSTR format_message( BOOL unicode_caller, DWORD dwFlags, LPCWSTR fmtstr
 
                 f++;
                 if (!*f) {
-                    ADD_TO_T('%');
-                    continue;
+                    SetLastError(ERROR_INVALID_PARAMETER);
+                    HeapFree(GetProcessHeap(), 0, target);
+                    return NULL;
                 }
 
                 switch (*f) {
@@ -433,6 +434,8 @@ DWORD WINAPI FormatMessageA(
     }
 
     target = format_message( FALSE, dwFlags, from, &format_args );
+    if (!target)
+        goto failure;
 
     TRACE("-- %s\n", debugstr_w(target));
     destlength = WideCharToMultiByte(CP_ACP, 0, target, -1, NULL, 0, NULL, NULL);
@@ -522,6 +525,8 @@ DWORD WINAPI FormatMessageW(
     }
 
     target = format_message( TRUE, dwFlags, from, &format_args );
+    if (!target)
+        goto failure;
 
     talloced = strlenW(target)+1;
     TRACE("-- %s\n",debugstr_w(target));
diff --git a/dlls/kernel32/tests/format_msg.c b/dlls/kernel32/tests/format_msg.c
index f118831..c842409 100644
--- a/dlls/kernel32/tests/format_msg.c
+++ b/dlls/kernel32/tests/format_msg.c
@@ -58,6 +58,8 @@ static void test_message_from_string_wide(void)
     static const WCHAR t[]           = {'t',0};
     static const WCHAR e[]           = {'e',0};
     static const WCHAR s[]           = {'s',0};
+    static const WCHAR fmt_null[]    = {'%',0};
+    static const WCHAR fmt_tnull[]   = {'t','e','s','t','%',0};
     static const WCHAR fmt_1[]       = {'%','1',0};
     static const WCHAR fmt_12[]      = {'%','1','%','2',0};
     static const WCHAR fmt_123[]     = {'%','1','%','3','%','2','%','1',0};
@@ -121,6 +123,9 @@ static void test_message_from_string_wide(void)
     static const WCHAR s_sp002sp003[] = {' ',' ','0','0','0','2',',',' ','0','0','0','0','3',0};
     static const WCHAR s_sp001004[]   = {' ',' ','0','0','1',',','0','0','0','0','0','4',0};
 
+    static const WCHAR init_buf[] = {'x', 'x', 'x', 'x', 'x', 'x'};
+    static const WCHAR broken_buf[] = {'t','e','s','t','x','x'};
+
     WCHAR out[0x100] = {0};
     DWORD r, error;
 
@@ -139,6 +144,29 @@ static void test_message_from_string_wide(void)
     ok(!lstrcmpW(test, out), "failed out=%s\n", wine_dbgstr_w(out));
     ok(r==4, "failed: r=%d\n", r);
 
+    /* format placeholder with no specifier */
+    SetLastError(0xdeadbeef);
+    memcpy(out, init_buf, sizeof(init_buf));
+    r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_null, 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);
+
+    /* test string with format placeholder with no specifier */
+    SetLastError(0xdeadbeef);
+    memcpy(out, init_buf, sizeof(init_buf));
+    r = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt_tnull, 0,
+        0, out, sizeof(out)/sizeof(WCHAR), NULL);
+    error = GetLastError();
+    ok(!memcmp(out, init_buf, sizeof(init_buf)) ||
+       broken(!memcmp(out, broken_buf, sizeof(broken_buf))), /* W2K3+ */
+       "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);
@@ -383,6 +411,7 @@ static void test_message_from_string(void)
 {
     CHAR out[0x100] = {0};
     DWORD r;
+    static const char init_buf[] = {'x', 'x', 'x', 'x', 'x', 'x'};
     static const WCHAR szwTest[] = { 't','e','s','t',0};
 
     /* the basics */
@@ -391,6 +420,28 @@ static void test_message_from_string(void)
     ok(!strcmp("test", out),"failed out=[%s]\n",out);
     ok(r==4,"failed: r=%d\n",r);
 
+    /* format placeholder with no specifier */
+    SetLastError(0xdeadbeef);
+    memcpy(out, init_buf, sizeof(init_buf));
+    r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "%", 0,
+        0, out, sizeof(out)/sizeof(CHAR), NULL);
+    ok(!memcmp(out, init_buf, sizeof(init_buf)),
+       "Expected the buffer to be untouched\n");
+    ok(r==0, "succeeded: r=%d\n", r);
+    ok(GetLastError()==ERROR_INVALID_PARAMETER,
+       "last error %u\n", GetLastError());
+
+    /* test string with format placeholder with no specifier */
+    SetLastError(0xdeadbeef);
+    memcpy(out, init_buf, sizeof(init_buf));
+    r = FormatMessageA(FORMAT_MESSAGE_FROM_STRING, "test%", 0,
+        0, out, sizeof(out)/sizeof(CHAR), NULL);
+    ok(!memcmp(out, init_buf, sizeof(init_buf)),
+       "Expected the buffer to be untouched\n");
+    ok(r==0, "succeeded: r=%d\n", r);
+    ok(GetLastError()==ERROR_INVALID_PARAMETER,
+       "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");




More information about the wine-cvs mailing list