Linux fprintf,错误:格式不是字符串文字且没有格式参数 [-Werror=format-security

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17260409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 23:17:26  来源:igfitidea点击:

fprintf, error: format not a string literal and no format arguments [-Werror=format-security

clinuxgcccompiler-errors

提问by

when I try to compile fprintf(stderr,Usage)on Ubuntu I got this error:

当我尝试fprintf(stderr,Usage)在 Ubuntu上编译时出现此错误:

 error: format not a string literal and no format arguments [-Werror=format-security

but when I compiled that on other linux distributions (RedHat, Fedora, SUSE) that is compiled successfully.

但是当我在其他编译成功的 Linux 发行版(RedHat、Fedora、SUSE)上编译它时。

Anyone has an idea?

有人有想法吗?

采纳答案by nos

You should use fputs(Usage, stderr);

你应该使用 fputs(Usage, stderr);

There is no need to use fprintf if you arn't doing formatting. If you want to use fprintf, use fprintf(stderr, "%s", Usage);

如果您不进行格式化,则无需使用 fprintf。如果要使用 fprintf,请使用fprintf(stderr, "%s", Usage);

The default compiler flagson Ubuntu includes -Wformat -Wformat-securitywhich is what gives this error.

Ubuntu 上的默认编译器标志包括-Wformat -Wformat-security导致此错误的原因。

That flag is used as a precaution against introducing security related bugs, imagine what would happen if you somehow did this:

该标志用作防止引入与安全相关的错误的预防措施,想象一下如果您以某种方式这样做会发生什么:

char *Usage = "Usage %s, [options] ... ";
...
fprintf(stderr, Usage);

This would be the same as fprintf(stderr, "Usage %s, [options] ... ]");which is wrong.

这与fprintf(stderr, "Usage %s, [options] ... ]");哪个错误相同 。

Now the Usagestring includes a format specifier, %s, but you do not provide that argument to fprintf, resulting in undefined behavior, possibly crashing your program or allowing it to be exploited. This is more relevant if the string you pass to fprintf comes from user input.

现在该Usage字符串包含一个格式说明符 ,%s但您没有向 提供该参数fprintf,从而导致未定义的行为,可能会导致您的程序崩溃或允许其被利用。如果您传递给 fprintf 的字符串来自用户输入,则这更相关。

But if you do fprintf(stderr,"%s", "Usage %s, [options] ... ]");There is no such problem. The 2. %swill not be interpreted as a format specifer. gcc can warn about this, and the default Ubuntu compiler flags makes it a compiler error.

但是如果你这样做fprintf(stderr,"%s", "Usage %s, [options] ... ]");就不会有这样的问题。2.%s不会被解释为格式说明符。gcc 可以对此发出警告,默认的 Ubuntu 编译器标志使其成为编译器错误。

回答by R.. GitHub STOP HELPING ICE

Use fputs(Usage)or fprintf(stderr, "%s", Usage). The idiom of passing a message string to a printf-family function is dangerous because, unless it's known not to contain format specifiers, any possible format specifiers in the string will be interpreted and result in undefined behavior (since they have no arguments corresponding to them), and this will almost always translate into security bugs.

使用fputs(Usage)fprintf(stderr, "%s", Usage)。将消息字符串传递给printf-family 函数的习惯用法是危险的,因为除非已知不包含格式说明符,否则字符串中任何可能的格式说明符都将被解释并导致未定义的行为(因为它们没有对应的参数) ,这几乎总是会转化为安全漏洞。

回答by BobC

It is perfectly correct to use fprintf()with only two arguments. As the function definition clearly indicates, all arguments after the second are optional.

fprintf()仅使用两个参数是完全正确的。正如函数定义清楚地表明的那样,第二个之后的所有参数都是可选的。

When the second argument does not contain a format clause, this warning actually becomes a bug, one that was introduced into GCC because of a BAD assumption that the second argument to fprintf()would alwayscontain a format clause. There is nothing that is true about that assumption. This was a flawed decision, a bug, that was repaired in newer versions of GCC, which actually inspect the second argument to ensure the proper number and types of additional arguments are present when required.

当第二个参数不包含格式条款,此警告实际上变成了一个bug,即引入GCC因为一个坏的假设是,第二个参数之一fprintf()始终包含格式条款。这个假设没有任何事实是正确的。这是一个有缺陷的决定,一个错误,在较新版本的 GCC 中修复,它实际上检查第二个参数以确保在需要时存在正确数量和类型的附加参数。

Mixing fputs()and fprintf()calls is asking for bugs. Plus it just makes the code uglier. It is much cleaner to use fprintf()everywhere, so long as you are also using a recent and sane GCC.

混合fputs()fprintf()调用是在寻找错误。此外,它只会使代码更丑。fprintf()只要您还使用最新且正常的 GCC,在任何地方使用它都会更干净。

The moral of this story is simple: Never modify good code to make a bad compiler happy.

这个故事的寓意很简单:永远不要为了让糟糕的编译器高兴而修改好的代码。