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