https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127372

            Bug ID: 127372
           Summary: Incorrect ms_printf format warning: unknown conversion
                    type character 'Z' in format [-Wformat=]
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: pali at kernel dot org
  Target Milestone: ---

https://godbolt.org/z/vvEa5KKnM

Simple code which uses ms_printf format %Z with various sizes (none, h, w, l):

  #include <winternl.h>
  int printf(const char *format, ...) __attribute__((format(ms_printf, 1, 2)));
  int msvcrt_test(ANSI_STRING *astr, UNICODE_STRING *wstr) {
    return printf("%Z %hZ %wZ", astr, astr, wstr);
  }
  int ucrt_test(ANSI_STRING *astr, UNICODE_STRING *wstr) {
    return printf("%Z %hZ %lZ %wZ", wstr, astr, wstr, wstr);
  }

produces following warnings:

  warning: unknown conversion type character 'Z' in format [-Wformat=]

This is wrong as the msvcrt printf function supports Z format.

gcc documentation https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html for
ms_printf format attribute says:

  Values prefixed with ‘ms_’ refer to the formats accepted by the msvcrt.dll
  library.

For crtdll.dll, msvcrt10.dll, msvcrt.dll and msvcr{70-120}.dll, the %Z and %hZ
formats in printf expects the pointer to ANSI_STRING structure, and for %wZ
format expects the pointer to UNICODE_STRING structure. The %lZ format is not
supported (and is interpreted as %Z; the l size is ignored).

For UCRT (ucrtbase.dll, ucrtbased.dll, api-ms-win-crt-stdio-l1-1-0.dll), the
%Z, %lZ and %wZ refers to pointer to UNICODE_STRING structure and %hZ refers to
pointer to ANSI_STRING structure. (There is a change from the previous msvcrt
behavior).

For completeness, msvcrt20.dll and msvcrt40.dll do not support %Z format at
all.

Structures ANSI_STRING and UNICODE_STRING are counted strings (not nul-term),
used natively by the Windows NT APIs (hence in kernel drivers and syscalls),
their definitions for userspace applications is in the winternl.h header file
(provided by WinSDK or by mingw-w64).

mingw-w64 has this definitions:

  typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR Buffer;
  } UNICODE_STRING;

  typedef struct _STRING {
    USHORT Length;
    USHORT MaximumLength;
    PCHAR Buffer;
  } STRING;
  typedef STRING ANSI_STRING;

Documentation resources:
msvcr100.dll -
https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/hf4y5e3w(v=vs.100)
msvcr110.dll -
https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/hf4y5e3w(v=vs.110)
msvcr120.dll -
https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2013/hf4y5e3w(v=vs.120)
ucrt -
https://learn.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions#type-field-characters

Reply via email to