[PATCH] msvcrt: The '*' character should be interpreted as the beginning of the width specification

David Gow david at davidgow.net
Sun Nov 7 03:47:31 CST 2021


In reply to Andrew Eikum:
 >
 > Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
 > ---
 >
 > For example,
 >
 >     "%*0d", 1, ...
 >
 > becomes
 >
 >     "%10d", ...
 >
 > i.e. prints ten digits.
This doesn't seem to be correct to me.

I've written a test program and built it with MSVC 2019:
int main(int argc, char **argv)
{
         printf("%0*02d\n",1,0);
         printf("%0*02d\n",30,17);
         printf("%*1d\n", 1, 3);
         printf("%0*0d\n", 1, 2);
         printf("% *2d\n", 0, 7);
         return 0;
}

The output on windows (and wine with native ucrtbase.dll) is:
00
17
3
2
  7

The output with this patch is notably different:
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
<absurd number of zeros elided>0000017
           3
0000000002
  7

I've uploaded a binary for said test program here:
https://davidgow.net/stuff/TestPrintf.exe

Similarly, Age of Empires IV shows an incorrect timer with this patch 
(the text under "Gold Medal (Goal…)" should read 00:17):
https://davidgow.net/stuff/aoe4-printf-bigtime.jpg


This diff to the patch fixes these issues (though it doesn't update the 
tests):
diff --git a/dlls/msvcrt/printf.h b/dlls/msvcrt/printf.h
index 40a8a13d861..6df7fd66156 100644
--- a/dlls/msvcrt/printf.h
+++ b/dlls/msvcrt/printf.h
@@ -1050,6 +1050,10 @@ int FUNC_NAME(pf_printf)(FUNC_NAME(puts_clbk) 
pf_puts, void *puts_ctx, const API
                  flags.LeftAlign = TRUE;
                  flags.FieldLength = -flags.FieldLength;
              }
+
+           /* Ignore this length if there's another specifier. */
+           if (*p >= '0' && *p <= '9')
+                   flags.FieldLength = 0;
          }

          while (*p >= '0' && *p <= '9') {


Cheers,
-- David



More information about the wine-devel mailing list