Since upgrading to the latest Xcode 3.2.1 and Snow Leopard, I've been getting the warning
"format not a string literal and no format arguments"
from the following code:
NSError *error = nil;
if (![self.managedObjectContext save:&error])
{
NSLog([NSString stringWithFormat:@"%@ %@, %@",
errorMsgFormat,
error,
[error userInfo]]);
}
If errorMsgFormat
is an NSString
with format specifiers (eg: "print me like this: %@"
), what is wrong with the above NSLog
call? And what is the recommended way to fix it so that the warning isn't generated?
I don't especially recommend using this, since the warning IS a real warning.. in a dynamic use of the language it's possible to do things runtime to the string (i.e. insert new information or even crash the program).. However it's possible to force suppress if you KNOW that it should be like this and you really don't want to be warned about it..
#pragma GCC diagnostic ignored "-Wformat-security"
Would tell GCC to temporarily ignore the compilation warning.. Again it's not solving anything but there may be times when you can't find a good way to actually fix the problem.
EDIT: As of clang, the pragma has changed. See this: https://stackoverflow.com/a/17322337/3937
FWIW, this applies to iPhone dev as well. I'm coding against the 3.1.3 SDK, and got the same error with the same problem (nesting stringWithFormat inside NSLog()). Sixten and Jon are on the money.
Final answer: As Jon Hess said, it's a security issue because you're passing a WHATEVER string to a function expecting a format string. That is, it'll evaluate all format specifiers WITHIN the whatever string. If there aren't any, awesome, but if there are, bad things could happen.
The proper thing to do, then, is USE a format string directly, for example
That way, even if there are format specifiers in myNSString, they don't get evaluated by NSLog.
NSLog() expects a format string, what is getting passed in is just a string. You do not need to use stringWithFormat:, you can just do:
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
And that would make the warning go away.