Warning: "format not a string literal and no format arguments"

86,761

Solution 1

Are you nesting your brackets correctly? I don't think NSLog() likes taking only one argument, which is what you're passing it. Also, it already does the formatting for you. Why not just do this?

NSLog(@"%@ %@, %@", 
   errorMsgFormat, 
   error, 
   [error userInfo]);              

Or, since you say errorMsgFormat is a format string with a single placeholder, are you trying to do this?

NSLog(@"%@, %@", [NSString stringWithFormat:errorMsgFormat, error], 
   [error userInfo]);              

Solution 2

Xcode is complaining because this is a security problem.

Here's code similar to yours:

NSString *nameFormat = @"%@ %@";
NSString *firstName = @"Jon";
NSString *lastName = @"Hess %@";
NSString *name = [NSString stringWithFormat:nameFormat, firstName, lastName];
NSLog(name);

That last NSLog statement is going to be executing the equivalent of this:

NSLog(@"Jon Hess %@");

That's going to cause NSLog to look for one more string argument, but there isn't one. Because of the way the C language works, it's going to pick up some random garbage pointer from the stack and try to treat it like an NSString. This will most likely crash your program. Now your strings probably don't have %@'s in them, but some day they might. You should always use a format string with data you explicitly control as the first argument to functions that take format strings (printf, scanf, NSLog, -[NSString stringWithFormat:], ...).

As Otto points out, you should probably just do something like:

NSLog(errorMsgFormat, error, [error userInfo]);

Solution 3

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

NSLog(@"%@", myNSString);

That way, even if there are format specifiers in myNSString, they don't get evaluated by NSLog.

Solution 4

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

Solution 5

Quickest way to fix it would be to add @"%@", as the first argument to your NSLog call, i.e.,

NSLog(@"%@", [NSString stringWithFormat: ....]);

Though, you should probably consider Sixteen Otto's answer.

Share:
86,761

Related videos on Youtube

Alexi Groove
Author by

Alexi Groove

Updated on January 30, 2020

Comments

  • Alexi Groove
    Alexi Groove almost 3 years

    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?

  • Christopher Fairbairn
    Christopher Fairbairn about 13 years
    That will silence the warning, but it won't do anything to fix the underlying flaw within your application. By silencing the warning you're ignoring a potential bug that could crash your application based simply on the data entered by the user (or in this case the error message generated by CoreData). It would be better to follow some of the other answers within this question to remove the bug within the source code that is causing the warning to appear.
  • aldi
    aldi about 13 years
    True... That's why I posted "get rid of the warning" instead of "solve".
  • Dan Rosenstark
    Dan Rosenstark almost 13 years
    And once again on SO, the detailed and good answers fall to the wayside. THANK YOU for explaining this fully. I would've never figured this out.
  • user102008
    user102008 almost 12 years
    "I don't think NSLog() likes taking only one argument" NSLog() can take one argument, when the format string contains no format specifiers.
  • cprcrack
    cprcrack about 10 years
    Can somebody explain WHY passing nil as second paramente solves the warning?
  • Admin
    Admin almost 10 years
    Passing nil is explicit while the lack of a second parameter is not. You can assume your fireplace wasn't lit when you left the house or you can make sure it wasn't. While nothing usually happens because you rarely use your fireplace, it'll be that one time when it is that your house burns down.
  • Mark Amery
    Mark Amery over 9 years
    @SoldOutActivist Unhelpful. The non-obvious point here (to someone who doesn't come from a C background) is what the difference in behaviour is between passing an explicit nil and not passing anything, and your comment doesn't explain that.
  • Admin
    Admin over 9 years
    Fine: Anything Obj-C method that can accept a variable number of arguments must be explicitly nil-terminated. Passing nothing is not the same as passing nil. Spend any time with Obj-C and you will see this over and over. Building arrays being the most common.
  • jscs
    jscs over 9 years
    This may stop the compiler warning, but the underlying problem, which was explained by Jon Hess, still exists -- if there's more than one format specifier in myString, the first will be fine, but the second one will pick up garbage off the stack. The substitution list in NSLog() is never nil-terminated, @Sold. There are two options for figuring out how long the list of arguments is: a sentinel value, or what's used in printf() and family -- another argument that allows calculation of the number (e.g., by counting the format specifiers).
  • alfwatt
    alfwatt about 9 years
    I ran into a case where the uthash library was triggering this warning on calls to it's utstring_printf function, so this is useful in situations where the warning is wrong.
  • Mark Amery
    Mark Amery about 9 years
    -1; as Josh Caswell's comment explains, this is the wrong way to make the warning go away and leaves the underlying problem.
  • Mark Amery
    Mark Amery about 9 years
    Using stringWithFormat is redundant here when you could just do NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
  • hasan
    hasan almost 9 years
    Gives another warning Data argument not used by format string.