Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tagged pointer format changes in iOS 14 break JSONKit on ARM64 #203

Open
Dir9119 opened this issue Aug 10, 2020 · 8 comments
Open

Tagged pointer format changes in iOS 14 break JSONKit on ARM64 #203

Dir9119 opened this issue Aug 10, 2020 · 8 comments

Comments

@Dir9119
Copy link

Dir9119 commented Aug 10, 2020

Hello,

As described here, Apple decided to change tagged pointers format in iOS 14 on ARM64. This causes JSONKit's jk_object_class function to determine object classes incorrectly and makes JSONKit virtually unusable.

@asgeo1
Copy link

asgeo1 commented Aug 24, 2020

I'm having this issue too. Is there any workaround?

@adancondori
Copy link

I'm having this issue too. Exist any alternative for this error.?

@garyZJ
Copy link

garyZJ commented Sep 18, 2020

I'm having this issue too.

@Kirow
Copy link

Kirow commented Sep 28, 2020

If you using code from #158 you can replace (straight forward solution)

return(((uintptr_t)objectPtr) >> 60);

with

if (@available(iOS 14, *)) {
   return(((uintptr_t)objectPtr) & 0x7);
} else {
   return(((uintptr_t)objectPtr) >> 60);
}

if you using code from master branch you will need to update isa usage

patch.diff
diff --git a/JSONKit.m b/JSONKit.m
index 0e9331f..c47ab02 100644
--- a/JSONKit.m
+++ b/JSONKit.m
@@ -677,7 +677,7 @@ static JKArray *_JKArrayCreate(id *objects, NSUInteger count, BOOL mutableCollec
   NSCParameterAssert((objects != NULL) && (_JKArrayClass != NULL) && (_JKArrayInstanceSize > 0UL));
   JKArray *array = NULL;
   if(JK_EXPECT_T((array = (JKArray *)calloc(1UL, _JKArrayInstanceSize)) != NULL)) { // Directly allocate the JKArray instance via calloc.
-    array->isa      = _JKArrayClass;
+    object_setClass(array, _JKArrayClass);
     if((array = [array init]) == NULL) { return(NULL); }
     array->capacity = count;
     array->count    = count;
@@ -928,7 +928,7 @@ static JKDictionary *_JKDictionaryCreate(id *keys, NSUInteger *keyHashes, id *ob
   NSCParameterAssert((keys != NULL) && (keyHashes != NULL) && (objects != NULL) && (_JKDictionaryClass != NULL) && (_JKDictionaryInstanceSize > 0UL));
   JKDictionary *dictionary = NULL;
   if(JK_EXPECT_T((dictionary = (JKDictionary *)calloc(1UL, _JKDictionaryInstanceSize)) != NULL)) { // Directly allocate the JKDictionary instance via calloc.
-    dictionary->isa      = _JKDictionaryClass;
+    object_setClass(dictionary, _JKDictionaryClass);
     if((dictionary = [dictionary init]) == NULL) { return(NULL); }
     dictionary->capacity = _JKDictionaryCapacityForCount(count);
     dictionary->count    = 0UL;
@@ -2596,7 +2596,7 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object
 
 
   BOOL   workAroundMacOSXABIBreakingBug = (JK_EXPECT_F(((NSUInteger)object) & 0x1))     ? YES  : NO;
-  void  *objectISA                      = (JK_EXPECT_F(workAroundMacOSXABIBreakingBug)) ? NULL : *((void **)objectPtr);
+  void  *objectISA                      = (JK_EXPECT_F(workAroundMacOSXABIBreakingBug)) ? NULL : ((void *)object_getClass(objectPtr));
   if(JK_EXPECT_F(workAroundMacOSXABIBreakingBug)) { goto slowClassLookup; }
 
        if(JK_EXPECT_T(objectISA == encodeState->fastClassLookup.stringClass))     { isClass = JKClassString;     }
@@ -2792,7 +2792,7 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object
           for(id keyObject in enumerateObject) {
             if(JK_EXPECT_T(printComma)) { if(JK_EXPECT_F(jk_encode_write1(encodeState, 0L, ","))) { return(1); } }
             printComma = 1;
-            void *keyObjectISA = *((void **)keyObject);
+            void *keyObjectISA = (void *)object_getClass(keyObject);
             if(JK_EXPECT_F((keyObjectISA != encodeState->fastClassLookup.stringClass)) && JK_EXPECT_F(([keyObject isKindOfClass:[NSString class]] == NO))) { jk_encode_error(encodeState, @"Key must be a string object."); return(1); }
             if(JK_EXPECT_F(jk_encode_add_atom_to_buffer(encodeState, keyObject)))                                                        { return(1); }
             if(JK_EXPECT_F(jk_encode_write1(encodeState, 0L, ":")))                                                                      { return(1); }
@@ -2804,7 +2804,7 @@ static int jk_encode_add_atom_to_buffer(JKEncodeState *encodeState, void *object
           for(idx = 0L; idx < dictionaryCount; idx++) {
             if(JK_EXPECT_T(printComma)) { if(JK_EXPECT_F(jk_encode_write1(encodeState, 0L, ","))) { return(1); } }
             printComma = 1;
-            void *keyObjectISA = *((void **)keys[idx]);
+            void *keyObjectISA = (void *)object_getClass(keys[idx]);
             if(JK_EXPECT_F(keyObjectISA != encodeState->fastClassLookup.stringClass) && JK_EXPECT_F([(id)keys[idx] isKindOfClass:[NSString class]] == NO)) { jk_encode_error(encodeState, @"Key must be a string object."); return(1); }
             if(JK_EXPECT_F(jk_encode_add_atom_to_buffer(encodeState, keys[idx])))    { return(1); }
             if(JK_EXPECT_F(jk_encode_write1(encodeState, 0L, ":")))                  { return(1); }

however there was comment not to use object_getClass due to performance impact, but goal was to fix the crashes.

P.S. Did not test this deeply, but seems to be working...

@miyiyake
Copy link

NSNumber 类型数据都有问题,换成NSString类型就没有问题

@codedeman
Copy link

If you using code from #158 you can replace (straight forward solution)

return(((uintptr_t)objectPtr) >> 60);

with

if (@available(iOS 14, *)) {
   return(((uintptr_t)objectPtr) & 0x7);
} else {
   return(((uintptr_t)objectPtr) >> 60);
}

if you using code from master branch you will need to update isa usage

patch.diff
however there was comment not to use object_getClass due to performance impact, but goal was to fix the crashes.

P.S. Did not test this deeply, but seems to be working...

it's work for me

@jcbertin
Copy link

jcbertin commented Nov 17, 2020

I have fixed #158 for new format of tagged pointers in macOS on Apple Silicon and last versions of iOS, watchOS and tvOS. Also replaced isa dereference by fast class lookup.

Please comment if it is not working for you…

@jcbertin
Copy link

For people curious to compare #158 and NSJSON, see JSONKitTest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants