Correcting “format string is not a string literal”

2019-04-28 05:56发布

问题:

I have a warning in my code that is driving me crazy:

int vasprintf_wrapper(char** bufptr, const char* fmt, va_list ap)
{
    // Do stuff...
    // ...
    return vasprintf(bufptr, fmt, ap);
}

Clang (3.6.0), complains with "format string is not a string literal", referring to the fmt argument that is being forwarded.

Naively, I tried to:

return vasprintf(bufptr, reinterpret_cast<const char[]>(fmt), ap);

Which of course doesn't compile.

What do I do? Disabling the warning altogether is not an option. I want to have the warning. But in this case, I would like to tell the compiler that I know what I'm doing ("famous last words" jokes aside...)

回答1:

Indicate a parameter is a printf-style format using the __attribute__ flag. For example:

__attribute__((__format__ (__printf__, 2, 0)))
int vasprintf_wrapper(char** bufptr, const char* fmt, va_list ap)
{
  ...
}

The last parameter (0) disables checking for va_list.

From the documentation:

format (archetype, string-index, first-to-check)

The format attribute specifies that a function takes printf-, scanf-, strftime-, or strfmon-style arguments that should be type-checked against a format string.

The parameter archetype determines how the format string is interpreted.

The parameter string-index specifies which argument is the format string argument (starting from 1).

The parameter first-to-check is the number of the first argument to check against the format string. For functions where the arguments are not available to be checked (such as vprintf), specify the third parameter as zero.

See also:

  • http://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
  • http://clang.llvm.org/docs/AttributeReference.html#format


回答2:

The warning flag that enables this type of warning is -Wformat-nonliteral. Since you don't want to turn that warning off completely, you can locally disable this warning using the following code:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-nonliteral"

...

#pragma clang diagnostic pop

So your function would look like this:

int vasprintf_wrapper(char** bufptr, const char* fmt, va_list ap)
{
    // Do stuff...
    // ...

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-nonliteral"
    return vasprintf(bufptr, fmt, ap);
#pragma clang diagnostic pop
}


标签: c++ clang