[PATCH] msvcrt: printf: Later width specifiers should override earlier ones

David Gow david at davidgow.net
Sun Nov 7 21:49:52 CST 2021


From: Andrew Eikum <aeikum at codeweavers.com>

This is a replacement for "msvcrt: The '*' character should be
interpreted as the beginning of the width specification"[1], which matches
the behaviour I see on my machine better.

If a printf format string contains both a '*' (to specify that the field
width should be read from a variable), followed by another explicit
field width, only the latter field width should be used.

For further details, see [2] and [3].

[1]: https://source.winehq.org/patches/data/218904
[2]: https://www.winehq.org/pipermail/wine-devel/2021-November/200039.html
[3]: https://github.com/ValveSoftware/Proton/issues/5258#issuecomment-962423092

Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
Co-Developed-by: David Gow <david at davidgow.net>
Signed-off-by: David Gow <david at davidgow.net>
---

Note also that this moves the new tests after the setlocale(LC_ALL,
"C"), as I don't think they need to run in a Japanese locale.

---
 dlls/msvcrt/printf.h       |  8 +++++++-
 dlls/msvcrt/tests/printf.c | 20 ++++++++++++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/dlls/msvcrt/printf.h b/dlls/msvcrt/printf.h
index aeb1290f48f..6d2f02ee85b 100644
--- a/dlls/msvcrt/printf.h
+++ b/dlls/msvcrt/printf.h
@@ -1050,7 +1050,13 @@ int FUNC_NAME(pf_printf)(FUNC_NAME(puts_clbk) pf_puts, void *puts_ctx, const API
                 flags.LeftAlign = TRUE;
                 flags.FieldLength = -flags.FieldLength;
             }
-        } else while (*p >= '0' && *p <= '9') {
+
+            /* Ignore this length if there's another specifier. */
+            if (*p >= '0' && *p <= '9')
+                flags.FieldLength = 0;
+        }
+
+        while (*p >= '0' && *p <= '9') {
             flags.FieldLength *= 10;
             flags.FieldLength += *p++ - '0';
         }
diff --git a/dlls/msvcrt/tests/printf.c b/dlls/msvcrt/tests/printf.c
index 06acf4c8450..cc824f571a6 100644
--- a/dlls/msvcrt/tests/printf.c
+++ b/dlls/msvcrt/tests/printf.c
@@ -396,6 +396,26 @@ static void test_sprintf( void )
     ok(!strcmp(buffer, "string to copy"), "failed: \"%s\"\n", buffer);
 
     setlocale(LC_ALL, "C");
+
+    r = p_sprintf(buffer, "%0*02d", 1, 0);
+    ok(r==2, "r = %d\n", r);
+    ok(!strcmp(buffer, "00"), "failed: \"%s\"\n", buffer);
+
+    r = p_sprintf(buffer, "%0*02d", 30, 17);
+    ok(r==2, "r = %d\n", r);
+    ok(!strcmp(buffer, "17"), "failed: \"%s\"\n", buffer);
+
+    r = p_sprintf(buffer, "%*1d", 1, 3);
+    ok(r==1, "r = %d\n", r);
+    ok(!strcmp(buffer, "3"), "failed: \"%s\"\n", buffer);
+
+    r = p_sprintf(buffer, "%0*0d", 1, 2);
+    ok(r==1, "r = %d\n", r);
+    ok(!strcmp(buffer, "2"), "failed: \"%s\"\n", buffer);
+
+    r = p_sprintf(buffer, "% *2d", 0, 7);
+    ok(r==2, "r = %d\n", r);
+    ok(!strcmp(buffer, " 7"), "failed: \"%s\"\n", buffer);
 }
 
 static void test_swprintf( void )
-- 
2.32.0




More information about the wine-devel mailing list