14

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

 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.

Anyone has an idea?

devnull
  • 118,548
  • 33
  • 236
  • 227

3 Answers3

26

You should use 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);

The default compiler flags on Ubuntu includes -Wformat -Wformat-security which is what gives this error.

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.

Now the Usage string 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.

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

nos
  • 223,662
  • 58
  • 417
  • 506
9

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.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
-1

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

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 always contain 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.

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.

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

pushkin
  • 9,575
  • 15
  • 51
  • 95
BobC
  • 345
  • 2
  • 10
  • Can you explain what GCC bug you are referring to? The changes proposed above (eg, using fputs) are not making the compiler happy. They are preventing bugs by avoiding the complex formatting logic when it is not wanted. For literals the compiler checks that the conversion directives match the arguments eliminating many bugs. But for variable format strings the programmer is on their own, which can lead to bad outcomes. – Ted Apr 13 '21 at 21:17