我创建了一个具有可变参数模板方法的类.这个方法调用printf函数.将零参数传递给方法时,我得到gcc的编译警告说:
警告:格式不是字符串文字而没有格式参数[-Wformat-security]
一个简化的类示例是:
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...);
}
};
Run Code Online (Sandbox Code Playgroud)
使用时
printer p;
p.print(23);
p.print(345,23);
Run Code Online (Sandbox Code Playgroud)
一切顺利,但使用时
printer p;
p.print();
Run Code Online (Sandbox Code Playgroud)
我收到编译警告
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...);
Run Code Online (Sandbox Code Playgroud)
当然,如果我只是打电话
printf("null\n");
Run Code Online (Sandbox Code Playgroud)
没有警告出现.
有人可以解释为什么会这样吗?
我可以在不禁用-Wformat-security标志的情况下删除警告吗?
Sha*_*our 12
这是一个预期的警告,如果我们查看-Wformat-security的文档,它说:
-Wformat-security如果指定了-Wformat,还会警告使用表示可能存在安全问题的格式函数.目前,这会警告调用printf和scanf函数,其中格式字符串不是字符串文字,并且没有格式参数,如printf(foo); .如果格式字符串来自不受信任的输入并包含"%n",则这可能是一个安全漏洞.(这是-Wformat-nonliteral警告的子集,但在将来的警告中可能会添加到-Wformat-nonliteral中未包含的-Wformat-security.) - Wformat = 2
因为结果c_str()不是字符串文字,所以不传递任何参数就是这种情况.
这个案例:
printf("null\n");
Run Code Online (Sandbox Code Playgroud)
没有警告,因为"null\n"字符串文字不可能从用户输入.
我们可以看到为什么这是一个潜在的安全问题,这个%n格式说明符程序在不同的编译器上给出不同的输出.为什么?.
如果你不想要所有的话,看起来你必须打开特定的开关-Wformat-secrity:
-Wformat包含在-Wall中.为了更好地控制格式检查的某些方面,选项-Wformat-y2k,-Wno-format-extra-args,-Wno-format-zero-length,-Wformat-nonliteral,-Wformat-security和-Wformat = 2是可用的,但不包括在-Wall中.
虽然如果-Wformat-secrity稍后添加更多选项,这是不好的选择,那么您需要不断更新.
AndyG提到的另一种选择是过载:
void print(){
std::printf("null\n");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
682 次 |
| 最近记录: |