Re: Secure coding NSArray
Re: Secure coding NSArray
- Subject: Re: Secure coding NSArray
- From: Dave <email@hidden>
- Date: Mon, 15 Feb 2016 11:43:24 +0000
Hi Quincey,
Thank you so much for the "heads-up" on this, I will be changing my App to use Secure Coding in the new future and it’s littered with NSArrays and NSDictionary properties.
Do you know if same thing applies to dictionaries as well as arrays?
All the Best
Dave
> On 14 Feb 2016, at 08:45, Quincey Morris <email@hidden> wrote:
>
> I might be late to this party, but since I just spent hours on it, I’ll document this for anyone who hasn’t run into it yet.
>
> If you’re using NSSecureCoding, there’s a problem decoding NSArray objects. You can’t use this:
>
> myArray = [coder decodeObjectForKey: @“myArray”];
>
> and you can’t use this:
>
> myArray = [coder decodeObjectOfClass: [NSArray class] forKey: @“myArray”];
>
> The error message in the resulting exception won’t be very helpful, but it means that the class of the array elements is invalid. What you actually need to do is this:
>
> myArray = [coder decodeObjectOfClasses: [NSSet setWithObjects: [NSArray class], [MyElementClass class], nil] forKey: @“myArray”];
>
> Besides being obscure, this is also semantically incorrect, in that it appears to allow decoding of objects that are not strictly arrays of MyElementClass objects. (I guess this is not a security violation, since it doesn’t permit an attack to substitute objects of arbitrary classes, but it sure is annoying.]
>
> Now, if you want to do this in Swift, you might be tempted to try the obvious translation:
>
> let classes = Set<AnyClass> (arrayLiteral: [… anything here… ])
> let myArray = coder.decodeObjectOfClasses (classes, forKey: “myArray”)
>
> but that won’t work because AnyClass isn’t Hashable. So you might try (well, I tried) something like this:
>
> let classes = Set<NSObject> (arrayLiteral: [NSArray.self, MyElementClass.self])
> let myArray = coder.decodeObjectOfClasses (classes, forKey: “myArray”)
>
> This compiles, but it fails at run-time, with a message saying it found an object of class ‘NSArray’, but only objects of classes ‘NSArray’ and ‘MyElementClass’ are allowed. (!)
>
> The solution is to fall back to an explicit NSSet object:
>
> let classes = NSSet (objects: NSArray.self, MyElementClass.self)
> let myArray = coder.decodeObjectOfClasses (classes, forKey: “myArray”)
>
> There really needs to be (radar #24646135) API to decode a NSArray and specify the class (or classes) of the elements. In Obj-C, something like:
>
> myArray = [coder decodeArrayWithObjectsOfClass: [MyElementClass class] forKey: @“myArray”];
>
> or in Swift:
>
> let myArray = coder.decodeArrayWithObjectsOfClass (MyElementClass.self, forKey: “myArray”)
>
> This would be particular useful in Swift, because it would give you compile-time checking of the types in the assignment. (There is already a Swift-only version of ‘decodeObjectOfClass’ that’s generic, so you get the “correct” return type.)
>
>
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden