I have created a class which has a variadic template method. This method calls printf
function. When passing zero arguments to the method, I get a compile warning by gcc saying:
warning: format not a string literal and no format arguments [-Wformat-security]
A simplified class example is:
class printer{
std::map<int,std::string> str;
public:
printer(){
str[0] = "null\n";
str[1] = "%4d\n";
str[2] = "%4d %4d\n";
str[3] = "%4d %4d\n%4d\n";
}
template<typename ...Args>
void print(Args... args){
printf(str[sizeof...(args)].c_str(),args...);
}
};
When using
printer p;
p.print(23);
p.print(345,23);
everything compiles smoothly, but when using
printer p;
p.print();
I get the compile warning
main.cpp: In instantiation of ‘void printer::print(Args ...) [with Args = {}]’:
main.cpp:23:11: required from here
main.cpp:17:50: warning: format not a string literal and no format arguments [-Wformat-security]
printf(str[sizeof...(args)].c_str(),args...);
Of course if I just call
printf("null\n");
no warning appears.
Could someone explain why this is happening?
Can I remove warning without disabling the -Wformat-security
flag?
This is an expected warning, if we look at the document for -Wformat-security it says:
-Wformat-security If -Wformat is specified, also warn about uses of format functions that represent possible security problems. At present, this warns about calls to printf and scanf functions where the format string is not a string literal and there are no format arguments, as in printf (foo);. This may be a security hole if the format string came from untrusted input and contains `%n'. (This is currently a subset of what -Wformat-nonliteral warns about, but in future warnings may be added to -Wformat-security that are not included in -Wformat-nonliteral.) -Wformat=2
which is the case when you pass no arguments since the result of c_str()
is not a string literal.
This case:
printf("null\n");
does not warn because "null\n"
is a string literal not possibly input from a user.
We can see why this is a potential security issue from this %n format specifier program giving different outputs on different compilers. Why?.
It looks like you have to turn on specific switches if you don't want all of -Wformat-secrity
:
-Wformat is included in -Wall. For more control over some aspects of format checking, the options -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security, and -Wformat=2 are available, but are not included in -Wall.
Although this is poor option if -Wformat-secrity
adds more options later on, then you need to continually keep updating.
Another alternative as AndyG mentioned would be an overload:
void print(){
std::printf("null\n");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With