microsoft / wil

Windows Implementation Library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

__WI_CHECK_MSG_FMT using wprintf instead of printf?

brycehutchings opened this issue · comments

I tried to update to the latest version of wil and got a compiler error for the following line of code which succeeded previously:

Code:
RETURN_HR_MSG(MF_E_INVALIDREQUEST, "Stream is not in running state, state:%d, selected: %s", (int)m_streamState, (m_bSelected ? "true" : "false"));

The compiler error:

1>SimpleMediaStream.cpp(197): error C2220: the following warning is treated as an error
1>SimpleMediaStream.cpp(176): warning C6302: Format string mismatch.

In digging into it, I found a recent change #383 added this formatting check but seemed to intentionally use the wide variant, wprintf, despite the wil functions (like Return_HrMsg) taking an ansi string for formatting. This mismatch would not get caught except for use of %s in our format string.

Your code as written currently has a bug. Before formatting the message, WIL will "widen" the format string (to ensure that there's no "loss" of data when formatting Unicode strings). You should explicitly specify %hs for narrow char* strings

More info from the documentation:

Be explicit when logging strings with XXXX_MSG macros. Use either: %ls or %hs to control whether an argument is a wide or ascii string, rather than using %s or %S. The format string is expected to be ASCII to minimize binary size, but internally is printed Unicode to avoid loss of data from params. Use the explicit format specifier to avoid the ambiguity this can bring.

Thanks, I will fix it. If wil is interpreting a format string that is provided as char* as if it is wide, is there a way to provide a more helpful error message? Even if the comment on __WI_CHECK_MSG_FMT explained this, then I would have been able to fix the problem without opening this issue. As it is, this wil design is surprising and not everyone updating to a new version of wil will be familiar with this requirement.

is there a way to provide a more helpful error message?

Depends on which part of the error message you find unhelpful. IIRC the vast majority of error messages I saw said something like:

warning C4477: 'wprintf' : format string '%s' requires an argument of type 'wchar_t *', but variadic argument 1 has type 'const char *'
note: consider using '%hs' in the format string
note: consider using '%Ts' in the format string
note: this warning is based on non-standard semantics used by Visual C++

That's fairly specific. The most confusing part is the reference to wprintf. AFAIK there's no way to make that part better for two reasons:

  1. The check done by the compiler seems to be hard coded based off function name. Therefore, we have a limited set of options in terms of triggering the warning as something like _Printf_format_string_ is unfortunately not checked by the compiler and you instead have to run additional tools to get warnings (e.g. compiling with /analyze)
  2. Even if the above were resolved, and _Printf_format_string_ (or some other attribute) did work, we'd need a way to communicate to the compiler that we're going to be widening the string

Even if the comment on __WI_CHECK_MSG_FMT explained this, then I would have been able to fix the problem without opening this issue

If there's verbiage that would have been more helpful, feel free to submit a PR to clarify things.