9

我正在创建一个链表并使用容器对对象、下一个和上一个属性进行分组。像 Foundation 集合一样,我希望它实现NSSecureCoding. 这是声明:

@interface ListContainer : NSObject <NSCopying, NSSecureCoding>

@property (readonly, nonatomic) id object;
@property (nonatomic) ListContainer * next;
@property (nonatomic) ListContainer * previous;

@end

在实现该- initWithCoder:方法时,我不知道该对象使用哪个类:

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];

    if (self) {

        _object = [aDecoder decodeObjectOfClass:<#(__unsafe_unretained Class)#> forKey:@"object"];

        BOOL nextIsNil = [aDecoder decodeBoolForKey:@"nextIsNil"];

        if (!nextIsNil) {

            // Decode next
            _next = [aDecoder decodeObjectOfClass:[ListContainer class] forKey:@"next"];

            if (_next == nil) {
                return nil;
            }

            // Link the nodes manually to prevent infinite recursion
            self.next.previous = self;
        }
    }

    return self;
}

我应该-decodeObjectForKey:改用吗?它仍然是安全编码吗?

4

1 回答 1

3

我最终将同样的问题发布到 Cocoa 的邮件列表中,最有趣的讨论发生了。一些亮点:

[...] 制作一个包含普通内容的 NSArray,例如 NSString、NSNumber,对其进行编码,使用 decodeObjectForClasses 对其进行解码,无需任何类。你会在阵列上失败。将 NSArray 添加到允许的类列表中,并且 .. 它可以工作。所以,你认为,NSArray 会盲目地解码任何东西,所以它不再安全。

将实现安全编码的自定义类的对象添加到数组中,它将再次开始失败。NSArray 和其他集合类型允许已知安全系统类型的元素,如 NSString,但在除此之外的任何事情上都失败。[...]

在这一点上,我明白 NSArray 的行为不像我预期的那样。安全编码似乎不再那么安全了:

这似乎远非理想 [...] 事实上,它解码一组已知实现 NSSecureCoding 的类是错误的,IMO,有两个原因 [...]

1) 包含的类实现 NSSecureCoding 的事实并不意味着我期待它。[...]

2)它限制了可以存储的类。[...]

在替代攻击中获得一个我没想到的课程尤其可怕。不过,显然 Cocoa 的承诺是不同的:

[...] 如果你在编码中直接使用 NSArray() 或其他集合类,你需要检查你得到了什么。它们被“安全”解码到 Apple 认为解码它们不会导致缓冲区溢出等的程度,这就是你默认得到的全部。[...]

所以,不,NSSecureCoding不保证容器的安全编码,或者至少不保证类型检查,你必须自己做。甚至在我最初假设的 Cocoa 的本机数据结构中也没有(有理由,我仍然这么认为)。

道具归罗兰国王所有。你可以在这里看到完整的对话。

于 2015-07-16T21:11:00.247 回答