How is my string potentially unsecure? [duplicate] - objective-c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Calling NSLog from C++: “Format string is not a string literal (potentially insecure)”
Why is my string potentially unsecure in my iOS application?
I have this code to log the number of elements in my NSMutableDictionary called "myDictionary" in objective-c.
NSLog([NSString stringWithFormat:#"%d", [myDictionary count]]);
XCode warns me that "Format string is not a string literal. Potentially insecure."
Why? Aren't I using a secure formatted string as opposed to directly casting the count?

NSLog() already assumes that you'll be passing in a formatted string. Try this instead:
NSLog(#"%d", [myDictionary count]);

The string you pass to NSLog is interpreted like a format string, so the appropriate way to do this is NSLog(#"%d", myDictionary.count);.
The reason it's "unsafe" is that it's possible to crash the program in cases like this:
NSString *someString = #"The integer format specifier is %d";
NSLog([NSString stringWithFormat:#"%#", someString]);
The input to NSLog is treated like a format string, but there's no corresponding value for the %d at the end. In your case it's not a problem, but the compiler isn't smart enough to figure that out.

Related

Objective-C equivalent of Swift "\(variable)"

The question title says it all, really. In swift you use "\()" for string interpolation of a variable. How does one do it with Objective-C?
There is no direct equivalent. The closest you will get is using a string format.
NSString *text = #"Tomiris";
NSString *someString = [NSString stringWithFormat:#"My name is %#", text];
Swift supports this as well:
let text = "Tomiris"
let someString = String(format: "My name is %#", text)
Of course when you use a format string like this (in either language), the biggest issue is that you need to use the correct format specifier for each type of variable. Use %# for object pointers. Use %d for integer types, etc. It's all documented.
#rmaddy's Answer is the gist of it. I just wanted to follow up on his comment that "It's all documented". Well, these symbols like %# and %d are called String Format Specifiers the documentation can be found at the following links.
Formatting String Objects
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Strings/Articles/FormatStrings.html
String Format Specifiers
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265-SW1
Just telling us noobs "It's all documented" isn't very helpful because often (if you're like me) you googled to find this stackoverflow post at the top of the SEO. And taking the link in hopes of finding the original documentation!

How to do NSLog with variable

What should be the correct format of the below to print *newString ?
NSString *newString = #"Hello this is a string!";
NSLog(#newString);
NSLog works pretty much as a C printf, with the addition of the %# string format specifier, which is meant for objects. Being NSString an object, %# is the right format to use:
NSString *newString = #"Hello this is a string!";
NSLog(#"%#", newString);
For as tempting as it can look, NEVER do
NSLog(newString); //NONONONONO!
since it's a terrible practice that may lead to unexpected crashes (not to mention security issues).
More info on the subject: Warning: "format not a string literal and no format arguments"
The # symbol is just a shorthand for specifying some common Objective-C objects. #"..." represents a string (NSString to be specific, which is different from regular C strings), #[...] represents an array (NSArray), #{...} represents a dictionary (NSDictionary).
On the first line, you've already specified a NSString object using the # sign. newString is now an NSString instance. On the second line, you can just give it's variable name:
NSLog(newString);
You could theoretically just give the variable name, but it is a dangerous approach. If newString has any format specifiers, your app may crash/mess up (or access something that it shouldn't be accesing) because NSLog would try to read the arguments corresponding to the format specifiers, but the arguments don't exist. The safe solution would be NSLog(#"%#", newString);. The first argument to NSLog is now hard-coded and can't be changed. We now know that it will expect a single argument, that we are providing that argument, newString, so we are safe.
Because you've already specified a string and just passing that instance to NSLog, you don't need the # sign again.

Working with big numbers in Objective-C?

I need to convert values like 1393443048683555715 to HEX. But, first of all, i cann't display it as decimal using NSLog(), for example.
Ok, it works:
NSLog(#"%qu", 1393443048683555706);
But what about converting to HEX. What type i have to use to store this big value?
NSLog([NSString stringWithFormat: #"%x", 1393443048683555706]);
// result eb854b7a. It's incorrect result!
but i forgot to say that this big number represented as string #"1393443048683555706" (not int)
You can use %qi and %qu format specifiers with NSLog to display 64-bit integers. Your constant appears to fit in 64-bit signed number, with the limits of:
[−9223372036854775808 to 9223372036854775807]
The "x" format specifier is for 32-bit numbers; you need to use either "qx" or "qX" (depending on whether you want the letter values to be uppercase or not). These are the formatters for unsigned long long values, see:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265-SW1
Next, you should not pass a string as you have done above directly to NSLog - this can cause a crash.
NSLog(string); // bad!!
NSLog(#"%#", string); // good
So if your value comes as a string, you'll want to do this:
NSString *longNumber = #"1393443048683555706";
NSLog(#"%qx", [longNumber longLongValue]);
If the string value can't be coerced to a number, longLongValue will return 0. I'll leave it to you do handle the error (and bounds) checking - see NSString for details.
If you want to save the hex value as a string, do this:
NSString *hexRepresentation = [NSString stringWithFormat:#"%qx", [longNumber longLongValue]];
Again, best to take care for error handling.

Reading String from File with Objective C

This one is weird. Hopefully I will ask the right question:
I'm using an md5 method to create a checksum value which I then write to a file. Then afterwards I read the file using this:
NSString * id_From_File = [[NSString alloc]
initWithContentsOfFile:path_to_ID
encoding:NSUTF8StringEncoding
error:&error];
The result gets placed in a NSString which when I print gives me very strange behaviour. For example when I use this to print,
id_with_date = [NSString stringWithFormat:#" %# %#", dateString, id_From_File];
it will print both strings if dateString is placed in the first parameter and id_From_File in the second. If I switch them around (which I need to do) only id_From_File shows.
Edit 1: Example of the switch:
id_with_date = [NSString stringWithFormat:#" %# %#", id_From_File, dateString];
I strongly believe this has something to do with the encoding of the id_From_File string.
Any knowledge!?
Thanks,
NSString should actually be capable of recognizing null characters as the file ending. Did you try to use a different method to load the string. I'd go for this one instead:
- (id)initWithContentsOfFile:(NSString *)path usedEncoding:(NSStringEncoding *)enc error:(NSError **)error
This method automatically detects the file's encoding instead of decoding it with a fixed one.
I've solved the problem!
It has to do with the fact that some strings use a null character to identify the end. Allow me to explain:
Lets say you have two strings, one with a null character at the end and one that doesn't. Depending on which way you order them, they will be read differently when concatenated.
"somestring(null char)" + "another string"
The above, in some code, will read
somestring
if places are switched
"another string" + "somestring(null char)"
then you get
"another string somestring"
My simple hack to fix this was to make a new string with a substring of "some string" which easily got rid of that last char that was causing the bug.
I hope this is clear and helpful!

#"%# in Objective C?

I was following a tut and found a line of code like #"%# button pressed.". I'm pretty sure the relevant part is the %#, but is the first # an escape sequence or what?
Anyways, searching symbols doesn't go well in any search engine so I thought I'd ask. I think the %# is like {0} in C#?
%# is a format specifier. Functions such as NSLog and methods such as +stringWithFormat: will replace %# with the description of the provided Objective-C or Core Foundation object argument.
For example:
NSString *myName = #"dreamlax";
NSLog (#"My name is: %#", myName);
This will log the output "My name is: dreamlax". See here for more information format specifiers.
The initial # symbol at the beginning of the string tells the compiler to create a static instance of an NSString object. Without that initial # symbol, the compiler will create a simpler C-style string. Since C-style strings are not Objective-C objects you cannot add them to NSArray or NSDictionary objects, etc.
#"some string" means this is an NSString literal.
The string as show in #"CupOverflowException", is a constant
NSString object. The # sign is used
often in Objective-C to denote
extentions to the language. A C string
is just like C and C++, "String
constant", and is of type char *
I found this page which might help - http://www.yetanotherchris.me/home/2009/6/22/objective-c-by-example-for-a-c-developer.html
It seems that you are on the right track.
I'm still fairly new to the language, but it looks like the # specifies that the variable being passed/created is an NSObject, or a compiler directive.
As mentioned above, if you use it like this:
#"someText"
you're instantiating an NSString object, and setting the text of that object to someText. If you look at a good ol' C-style format specifier such as:
..."This is some text, and this is a float: %f", myFloat);
You're creating some text and telling the compiler to put the floating point string representation of myFloat into the string. %# is a format specifier, just like %f, %d, %c, %s and any other format specifier you're used to. However, if you use %# as follows:
... "This is some text, and this is an object:%#", myObject];
What you're doing is (I believe) telling the compiler that myObject is an object, and that you want it to include the output of the description method (ie. [myObject description]) in the string that you're creating.