I have a need to ensure the user-inputed string in a UITextField is cleared from memory immediately after it has been used. If I set field.text = #"" or nil and let it go out of scope it should ge gone but I am not sure if it is guaranteed to be released immediately and even if it is, I dont think the OS actually clears the data, it seems likely it is just marked as unused and the data in it is still there until overwritten by something else.
The .text property of the field is a normal NSString and I have looked around for ways to get a useable pointer to its contents using the various CFString / CString methods but none of them work. For example CFStringGetCharactersPtr and CFStringGetCStringPtr both either return const-pointers which cant be written to, or often NULL (the docs say it may return null "if the internal storage of the String does not allow this to be returned efficiently") and from my testing it always returns NULL.
Is there anyway to do this?
answering my own question to be clear:
I got a reply from an apple employee at the devforums and he confirms it is pretty much impossible. His suggestion was to do everything yourself based on UITextInput and not use NSString or UITextField at all.
Related
I'm going through an old code base and fixing issues that pop up with xCode's static analyzer. The issue that shows is that the value is never read and basically what is happening in this method is that it's taking a string that should be a number and casting it to an int. Here is the line in question though:
if (len50 == CANNOT_CALCULATE)
{
len50 = 0;
strLen50 = #"";
}
Cannot_Calculate is a macro for a certain int that means it wasn't casted correctly and there's an else statement that does stuff with the int it it was casted correctly. The objects len50 and strLen50 aren't used at all after this if check, hence the reason of the warning from the analyzer.
My question is if this line is necessary? Does setting a int to 0 or string to an empty string save on memory? If it does then the owner of the codebase will want it in, but it doesn't then I might as well get rid or it.
That be some weird code all the way around.
1) No, setting a variable to a value does not impact memory one way or another. If the value is never read, it is a wasted line of code (that the compiler will likely optimize away anyway).
2) !"" would be weird for setting a boolean value.
I'd be highly suspect of the rest of the codebase, having just read that. (Having been a consultant on many projects, suspect code is oft a way of life.)
After merging master to my working branch I got compiler error on the line, which wasn't be changed. The error looks like
id test;
[test count];
Multiple methods named 'count' found with mismatched result.
At first it looks clear, because compiler doesn't know which concrete type the "test" variable is. But I don't understand why it worked before.
If I create a new file this line works, assuming that is a NSArray's method. Why compiler doesn't show error in this case?
While showing error message, there is several possible receivers of count method are shown. (NSArray, NSDictionary, NSSet) Does it search all classes that can receive that message and show error if there are multiple?
I noticed that error occurs when I import "-Swift.h" file. How it depends?
Compiler doesn't cast or check your id type. It just provides you all possible selectors. You said that this issue connected with importing "-Swift.h" file. In this case check you Swift code, probably you have count function visible for Objective C which returns something else than Int.
Also, you can check the issue in Issue navigator, select it and it will show all count calls visible in Objective C. Check them all, most of them will return NSUInteger, but there should be one that returns something else, for example:
SWIFT_CLASS("_TtC3dev19YourClass")
#interface YourClass : NSObject
- (int32_t)count SWIFT_WARN_UNUSED_RESULT;
#end
Objective-C doesn't need to know the type of the receiver. At run-time, all objects are just id, and everything is dynamically dispatched. So any message can be sent to any object, no matter its type. (At run-time, objects are free to decide what to do with messages they don't understand. The most common thing to do is raise an exception and crash, but there are many kinds of objects that can handle arbitrary messages that don't map directly to method calls.)
There is a couple of technical details, however, that complicate this.
The ABI (application binary interface) defines different mechanisms for returning certain primitive types. As long as the value is "a word-sized integer," then it doesn't matter (this includes things like NSInteger and all pointers, which means by extension all objects). But on some processors, floats are returned in different registers than integers, and structs (like CGRect) might be returned in a variety of ways depending on their size. In order to write the necessary assembly language, the compiler has to know what kind of return value it will be.
ARC has added additional wrinkles that require that the compiler know a more about the type of the parameters (specifically whether they're objects or primitives), and whether there are any memory-management attributes that have to be considered.
The compiler doesn't really care what "real" type test is, as long as it can figure out the types and attributes of -count. So when dealing with an id value, it looks through every known selector it can see (i.e. every one defined in an included header or the current .m). It's fine if there are many of them on different classes, as long as they all agree. But if it can't find the selector at all, or if some of the interfaces disagree, then it can't compile the line of code.
As lobstah notes, you likely have a type somewhere in your Swift code that has an #objc method called count() or an #objc property named count that returns something other than Int (which maps to NSInteger, and so match the usual signature of -count). You'll need to fix that method, or you'll need to hide it from ObjC (for example, by adding #nonobjc).
Or much better: get rid of the id, and use its actual type. id is generally a bad idea in Cocoa, and is especially a bad idea if you're calling methods on it, since the compiler can't check that the object will respond and you may crash.
I am trying to improve our code security. We use a static code analysis tool named CheckMarx. The tool is new at the company, in particular we are the only team to work on iOS with objective C.
I have a parameter class to connect to a server, it contains server address, port, few parameters, login and password
The password should not be taped by user but. It is retrieved as a token from another strong authentication service each time needed. It should not be saved as persistant value (because it change every time), so keychain do not looks to answer my need.
For the demo project, the user will tap it in a textField. That demo projet is under security validation.
When running the analysis, I get a 'heap inspection' vulnerability :
https://cwe.mitre.org/data/definitions/244.html about the password. In theory i understand the problem I should clear the memory space where the password was stored, but I have no idea to achieve this, in objective C.
The password is an NSString, which is immutable, so if i try to overwrite the NSString, I will only create a new string and let the old one somewhere in the heap. (And if I overwrite it anyway in dealloc method, i get another warning saying that hardcoded string is a bad practice for password).
renaming the variable into another dummy variable name like MyDummyPropThatContainsData
1) ARC will clear the pointer but i do not think it will clean up the heap. So i believe this is not a false positive. Am i wrong ?
2) I have try using a NSMutableString allocated with MAX_SIZE_PASSWORD. I use the setString method to set the variable (at the same place). I erase it in the dealloc method by calling setString method with a dummy value of exactly MAX_SIZE_PASSWORD. It removed the warning, is it a good practice ?
I am quite sure that this should be another warning saying that hardcoded string is a bad practice for password, but it is not detected. I suppose the bad practice remains ...
3) I have thought to use a char* so i would be able to memset it later, but it sounds bad to me. I am afraid that it could be a reliability and maintenance issue. Is this could solve my problem ? is it recommanded with ARC to manage myself allocation of char * everywhere I need to manage passwords ?
I have found nothing in objective C to prevent Heap Inspection vulnerabilities. Is there some common way to prevent that in objective C ?
Do you know some good points where to start ?
Any help appreciated !
One comment and also a recipe. In a system that supports either no swap or an encrypted swap, nil-ling out the data is mostly moot. The main remaining attack to discovering the password is directly attaching to the running app. I use the keychain modes to defend against this attack.
The goal is to erase the secret on the heap.
As I keep passwords in my keychain, they are returned as an NSData BLOB. This is key. You can then initialize an NSString with the BLOB's bytes and disallow the string from owning them (freeWhenDone: NO). While I cannot guarantee that NSString does not copy the data, it appears to be the case. (Make sure you do not specify an encoding that causes the NSString to have to recast the data. UTF-8 generally works fine.)
When you are done with the password NSString, release it. (Using ARC, set it to nil.)
Now the key to cleaning up the heap is to use the NSData routine to enumerate through each of its byte arrays, typically there is only one, and then set the bytes to NULL. If you prefer, you can bang in random bytes. You can now release the NSData BLOB.
Yes, this breaks all of the rules of mutability preservation. That is what unsafe pointer operations are for. They are unsafe. But you are also doing something in a specific place for a very good reason.
As this is a rather delicate operation, I hesitate to share code that implements the above algorithm. IMO, you need to be responsible for your own security hygiene.
If the above isn't clear, I'm happy to refine the answer further.
After updating to XCode 6.3, compiler started giving this warning.
Comparison of address of 'myObject' not equal to null pointer is always true.
Here is my piece of code,
Scratching my head with it, but didn't find any solution or workaround to get rid of this warning.
My question is linked with question over here. But, it can't be solved using answer discussed.
Any help will be welcomed :)
Correct way of checking the pointer is
if (anotherInView != nil) {
}
You are comparing address of a variable with the NULL. Every variable has an address you can't have a variable whose address is NULL, you can have a variable whose value is NULL
Also anotherRect != NULL is again not valid. anotherRect will always have a value as it's a struct
There are four mistakes here. The first two are that you aren't setting any initial values for the CGRect and UIView variables, so there's no way to detect a failure. Try setting the CGRect to a zero-width, zero-height rect initially if you think that is useful, and set the UIView to nil.
The third and fourth mistakes are that the address of a local variable is never NULL. (Note that this is not true for global variables in libraries, as I mentioned in another comment—the address of an NSString pointer constant might be NULL if the symbol didn't exist on the version of the OS you're running—but for local variables, you're guaranteed an address up to the point where your stack overflows and your app crashes.)
I'm also puzzled by why you're calling a delegate method yourself. Normally, the OS itself calls those methods, so calling them yourself is somewhat atypical usage. To be fair, I've done it on occasion when a delegate method performs a computation that I need somewhere else in the code, and I've also done it when implementing delegates that call other delegates, but in the context of this question, it seemed like a potential mistake.
For the first instruction, a changed to :
if (!CGRectIsNull(anotherRect)) {
}
When I call a certain function from my iOS app, it returns an id data type. I can't see into this function so I don't know what it's doing or what the return type really is.
If I print it to console using NSLog("#"...) I get a string similar to this:
2012-01-18 19:03:08.915 HelloWorld[165:707] Key Press State.
Is there any way for me to determine the structure of this basic Id object? How would I go about getting a specific part of that response out, such as "Key press state". String parsing seems like a horrible idea, but maybe that's the only way. Perhaps the data really is just an NSString?
Thanks!
Try this:
NSLog(#"Mystery object is a %#", NSStringFromClass([mysteryObject class]));
If you look in <objc/runtime.h> you'll see methods for querying an object about its class, method selectors, ivars, etc. However, you don't usually want to do that, as it breaks encapsulation and can lead to you relying on implementation details that might change in the future, so be careful with it. You can read more here.