views:

122

answers:

2

I need simple client-server communication with iPhone app, and XML property lists seem like quite easy and simple solution that saves me trouble of dealing with XML parser delegates and building these structures myself.

I just wonder is it wise to use NSPropertyListSerialization class with external data? Are there any obscure plist features that could be exploited?

+1  A: 

Yes, it's safe to use NSPropertyListSerialization with untrusted data, but after you turn the bag of bytes into a hiearchy of plist types, you have to validate those types to makes sure they match your expected data format.

For example, if you expect a dictionary with string keys, and NSNumbers as values, you have to validate that with something like:

NSString *errorDescription = nil;
NSPropertyListFormat format = 0;
id topObject = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&errorDescription];
NSDictionary *validDictionary = nil;
if ([topObject isKindOfClass:[NSDictionary class]]) {
    BOOL allNumbers = YES;
    for(id value in [topObject allValues]) {
        allNumbers = allNumbers && [value isKindOfClass:[NSNumber class]];
    }
    if (allNumbers) {
        validDictionary = topObject;
    }
}
return validDictionary;

If you don't do that, the source of the data could have placed plist values into the archive with mis matched types, or illegal values that could cause your client to misbehave and wind up being a security vulnerability.

Jon Hess
A: 

@Jon Hess: thanks. I've created NSDictionary category to cut down on required number of isKindOfClasses.

@interface NSDictionary (TypedDictionary)

-(NSArray *)arrayForKey:(NSString*)key;
-(NSString *)stringForKey:(NSString*)key;
-(NSDictionary *)dictionaryForKey:(NSString*)key;

@end


@implementation NSDictionary (TypedDictionary)

-(NSArray *)arrayForKey:(NSString*)key {
    NSArray *obj = [self objectForKey:key];
    return [obj isKindOfClass:[NSArray class]] ? obj : nil;
}
-(NSString *)stringForKey:(NSString*)key {
    NSString *obj = [self objectForKey:key];
    return [obj isKindOfClass:[NSString class]] ? obj : nil;
}
-(NSDictionary *)dictionaryForKey:(NSString*)key {
    NSDictionary *obj = [self objectForKey:key];
    return [obj isKindOfClass:[NSDictionary class]] ? obj : nil;
}
@end
porneL