Description of problem: Recently, I got bug #1037377, where there are these errors: njamfont.cpp:119:44: error: format not a string literal and no format arguments [-Werror=format-security] njamfont.cpp:128:44: error: format not a string literal and no format arguments [-Werror=format-security] The offending lines read: printf((const char *)TTF_GetError()); printf((const char *)SDL_GetError()); as the value is typed as "const char *", I do not understand the requirement for a "format argument" and I think it is a false positive. Version-Release number of selected component (if applicable): (ask dkholia about the environment) How reproducible: (haven't tried myself) Steps to Reproduce: 1. rebuild vodovod package with -Werror=format-security Actual results: allmenus.cpp:367:69: error: format not a string literal and no format arguments [-Werror=format-security] allmenus.cpp:370:69: error: format not a string literal and no format arguments [-Werror=format-security] njamfont.cpp:119:44: error: format not a string literal and no format arguments [-Werror=format-security] njamfont.cpp:128:44: error: format not a string literal and no format arguments [-Werror=format-security] Expected results: no errors Additional info:
No, this is not a bug. The -Wformat-security warning is documented: -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.) (const char *)TTF_GetError() is not a string literal, therefore can't be verified by the compiler, and the -Wformat-security warning warns (-Werror=format-security errors out) if you don't have any ... arguments in that case. This might or might not be a bug in the application, it depends on if the string returned in there might be coming from untrusted source. The fact that -Werror=format-security is now on by default in Fedora rpm flags is on by default wasn't my decision, I disagree with it (especially because with -D_FORTIFY_SOURCE=2 %n in there doesn't cause a security problem unless you have the string literal with %n in it somewhere in .rodata section), but it isn't a gcc bug that it warns with non-default warning option about what that warning is documented to warn about.
(In reply to Jakub Jelinek from comment #1) > No, this is not a bug. The -Wformat-security warning is documented: the fact that something works as documented doesn't guarantee that the way it works is okay :-) > -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.) > > (const char *)TTF_GetError() is not a string literal, therefore can't be > verified by the compiler, and the -Wformat-security warning warns > (-Werror=format-security errors out) if you don't have any ... arguments in > that case. I must be missing something here ... I thought the whole point of this check is to ensure that printf gets a hunk of bytes which is of the same type as printf expects it to be in this regard, I do not see any difference whether you express that we are dealing with string by using "%s" or by specifying the string type by "char *" construct of course, this needs that compiler AI gets a bit further, but still it is not an issue that'd need a crystall ball so the check in the way it is done (and documented) seems insufficient to me but I'm no C expert, much less compilers expert, so probably I'm looking at it wrongly please feel free to point me to some docs which would cover this specific issue, if they exist, or catch me on irc to explain it in person (and in Czech ...), or whatever, but currently I do not feel convinced that nothing could be done - so please let me keep this opened until it gets sorted out, even if there is high chance it is solely my fault and mistake to consider this bug/rfe material > This might or might not be a bug in the application, it depends on if the > string returned in there might be coming from untrusted source. please, could you be more specific what does that mean "untrusted"? - it comes from: char *SDL_GetError(void); - this is string, it is not a float or whatever > The fact that -Werror=format-security is now on by default in Fedora rpm flags > is on by default wasn't my decision, I disagree with it (especially because > with -D_FORTIFY_SOURCE=2 %n in there doesn't cause a security problem unless > you have the string literal with %n in it somewhere in .rodata section), please could you express your concerns at the corresponding ticket then? https://fedorahosted.org/fesco/ticket/1185 > but it isn't a gcc bug that it warns with non-default warning option about > what that warning is documented to warn about. see above, to the best of my current knowledge, it is not quite optimal how the "what to warn about" is defined ... however, I'm eager to know where am I wrong, looking forward to broadening my knowledge :-)
(In reply to Karel Volný from comment #2) > > (const char *)TTF_GetError() is not a string literal, therefore can't be > > verified by the compiler, and the -Wformat-security warning warns > > (-Werror=format-security errors out) if you don't have any ... arguments in > > that case. > > I must be missing something here ... > > I thought the whole point of this check is to ensure that printf gets a hunk > of bytes which is of the same type as printf expects it to be > > in this regard, I do not see any difference whether you express that we are > dealing with string by using "%s" or by specifying the string type by "char > *" construct Then you are clearly misunderstanding what it is about. The problem is say: #include <stdio.h> int main (int argc, const char **argv) { printf (argv[1]); return 0; } if you run this program with ./a.out %n then (if not -D_FORTIFY_SOURCE=2), it will overwrite some bytes somewhere in memory, or even if you just call it with ./a.out %s%s%s it could crash etc. If for printf without ... the argument is a string literal, the compiler can see it and complain if you do something invalid, like printf ("%s"); and let you do printf ("foobar no percent sign anywhere in it or just %% or %m"); Note the untrusted source of the string doesn't have to be from command line, it could be from some file, from network, etc., and that is something that is reasonable to be warned about. The compiler can't figure out (at least without big inter-procedural analysis) if in your case you always pass properly constructed strings that won't contain any % characters in it. If you do printf ("%s", SDL_GetError ()); instead, then no % signs are interpreted in the string, it is printed as is.
(In reply to Jakub Jelinek from comment #3) ... ah, thanks seems I completely misunderstood how printf itself works, that it tries to interpret _anything_ it gets in the format string, not just format specifiers set at compile time