Re: Launching apps on 10.13.2


Graham Cox
 

So, this is looking damn strange. So far, it appears is if 10.13.2 has actually broken dearchiving when using this. It may be an intentional breakage, or not.

I’ve been through the documentation and it seems is though [-NSKeyedArchiver encodeArrayOfObjCType:@encode(float) …] is perfectly legal. @encode(float) basically returns the C string “f”. It looks as if 10.13 added a more secure mechanism for encoding and decoding arbitrary types - I’m wondering if somehow accommodating this new API has broken the old one.

(DISCLAIMER: I’m reluctant to point the finger at OS code when things don’t work for obvious reasons, but hear me out!)

This is a fragment of the archive that is written (complete archive attached):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>$0</key>
<real>4</real>
<key>$1</key>
<real>1</real>
<key>$2</key>
<real>1</real>
<key>$3</key>
<real>1</real>
<key>$class</key>
<dict>
<key>CF$UID</key>
<integer>11</integer>
</dict>
<key>NS.count</key>
<integer>4</integer>
<key>NS.size</key>
<integer>4</integer>
<key>NS.type</key>
<integer>102</integer>
</dict>
</plist>


This is a dictionary embedded in the archive corresponding to the use of -encodeArrayOfObjCType:

In this case I’ve written 4 float values, as can be seen in the corresponding NS.count entry. The values of the elements of the array are keyed using $0..$3. (the corresponding values are 4.0, 1.0, 1.0, 1.0)

I’m not sure how NS.type works, but its value is always 102 for these float arrays.

When NSKeyedDearchiver is asked to dearchive this array, internally it makes an object with the class _NSKeyedCoderOldStyleArray, and calls -initWithCoder: on it. That method throws the exception "*** -[_NSKeyedCoderOldStyleArray initWithCoder:]: unable to decode element in array of size (4) and count (2)” noted earlier. To try and figure out what’s going on, I’ve created a class of my own which I can substitute for this class. My class gets created and called instead as expected, and I can ask the decoder for NS.count, NS.type, NS.size, and I get back the values from the archive as expected.

But when I ask for the value of the key “$0”, it doesn’t exist. Nor do any of the others. Presumably this is what _NSKeyedCoderOldStyleArray is discovering as well, and throws the exception.

At this point it’s unclear what the further problem is - is NSKeyedArchiver disallowing the key, or is it really the case that the key doesn’t exist - I don’t know. Peeking at what data members of NSKeyedUnarchiver I can, I can’t see anything useful.

I’m going to create a simple test case that shows the problem in isolation (if it does), and submit it as a bug. I’m thinking that this particular feature of archiving is not used much, Apple have broken it, and it wasn’t picked up in testing. Again, I’m reluctant to draw this conclusion, but that’s how it looks right now.

It would be useful if someone else could check this out to confirm or disprove it though.

—Graham

On 8 Dec 2017, at 1:11 pm, Quincey Morris <quinceymorris@...> wrote:

On Dec 7, 2017, at 16:34 , Graham Cox <graham@...> wrote:

It makes me wonder if @encode(float) is actually legal, or perhaps I’ve just been getting away with it for years?
Can you find out what @encode(float) is in 10.12 and 10.13.2?

Does decoding fail if you use @encode(uint32_t) instead?

Join cocoa@apple-dev.groups.io to automatically receive all group messages.