Erzwingen von Typen mit NSSecureCoding

8

Ich habe mich dazu entschieden, NSSecureCoding über NSCoding zu verwenden, aber ich habe Probleme damit, es zum Laufen zu bringen.

Ich würde erwarten, dass der folgende Code fehlschlägt, da ich ein NSString codiere, aber versuche, ein NSNumber zu dekodieren. Das Objekt wird jedoch initialisiert, ohne dass eine Ausnahme ausgelöst wird.

%Vor%

Hier ist der Code, den ich verwende, um das Snippet von oben zu testen:

%Vor%

Fehle ich etwas völlig Offensichtliches oder warum wird beim Decodieren keine Ausnahme ausgelöst?

    
Christian Schnorr 24.03.2015, 21:09
quelle

1 Antwort

9

Wenn Sie sich die Definition von -[NSCoder decodeObjectOfClass:forKey:] anschauen, sollte Ihr Code-Beispiel eine Ausnahme ausgelöst haben. Die Beschreibung der Methode sagt es:

  

Dekodiert ein Objekt für den Schlüssel, das auf die angegebene Klasse beschränkt ist.

Und die Diskussion sagt:

  

Wenn der Coder YES auf requiresSecureCoding antwortet, wird eine Exception ausgelöst, wenn die zu dekodierende Klasse nicht NSSecureCoding implementiert oder nicht isKindOfClass: von aClass.

Es gibt zwei Inkonsistenzen mit der Implementierung von NSKeyedUnarchiver dieser Methode in Bezug auf Optimierungen. Die erste besteht darin, dass decodeObjectOfClass:forKey: und decodeObjectForKey: ein Objekt erst beim ersten Mal dekodieren.

Zum Beispiel wird das assert im folgenden Code übergeben, weil foo und foo2 als dasselbe Objekt gestartet wurden und nur einmal dekodiert wurden, während foo3 als separates Objekt gestartet und als Ergebnis separat decodiert wurde.

%Vor%

Es scheint, dass Klassen nur überprüft werden, wenn das Objekt tatsächlich dekodiert wird. Die Liste der genehmigten Klassen wird mit der Klasse verglichen, die das Objekt anfordert. In meinem vorherigen Beispiel könnte ich also die Klasse für foo2 so ändern, wie ich möchte und der Code wird weiterhin ausgeführt und gibt NSSet zurück:

%Vor%

Die zweite Inkonsistenz, die direkt mit Ihrem Beispiel zusammenhängt, ist, dass bestimmte Objekttypen niemals wirklich decodiert werden. NSKeyedArchiver speichert alle seine Daten als eine Liste mit binären Eigenschaften, die nach Der Quelltext von Apple unterstützt native Zeichen-, Daten-, Zahlen-, Datums-, Wörterbuch- und Array-Typen. Wenn NSKeyedArchiver auf ein NSString , NSNumber oder NSData -Objekt (aber keine Unterklasse) trifft, speichert es den Wert nicht direkt in encodeWithObject: und speichert Informationen über die Dekodierung der PList. Wenn Sie dann decodeObjectOfClass:withKey: aufrufen, sieht es die bereits vorhandene Zeichenfolge und gibt sie ohne Dekodierung zurück. Keine Dekodierung bedeutet keine Klassenprüfung.

Ob dieses Verhalten gut oder schlecht ist, könnte diskutiert werden. Weniger Überprüfung bedeutet schneller Code, aber das Verhalten stimmt wirklich nicht mit der API-Dokumentation überein. Das heißt, Sie fragen sich vielleicht, welche sichere Codierung Sie bekommt, wenn es keine Rückgabetypen garantiert. Die sichere Kodierung mit NSKeyedUnarchiver schützt Sie davor, dass ein in böser Absicht erstelltes Archiv Sie nicht dazu bringen kann, alloc / initWithCoder: in einer beliebigen Klasse aufzurufen. Wenn Sie mehr als das möchten, können Sie eine Unterklasse erstellen, die den Ausgabetyp aller decodeObjectOfClass:withKey: und decodeObjectOfClasses:withKey: call validiert.

    
Brian Nickel 27.03.2015, 19:52
quelle