Mon application iPad qui est écrite en Objective C plante sur une méthode qui se trouve sur NSDictionary Category qui est écrite dans un framework (je n'ai que des fichiers d'en-tête dans le framework). Je n'appelle cette méthode de catégorie nulle part, mais elle est appelée d'une manière ou d'une autre et elle plante avec un sélecteur non reconnu envoyé à l'instance. Je voudrais trouver l’origine de l’appel qui y est lancé. Y a-t-il moyen de le faire?

Il plante uniquement sur iOS14 et fonctionne correctement sur les versions ci-dessous d'iOS. Toute aide est très appréciée.

MISE À JOUR AVEC CRASH LOG - NSDictionary (NSDictionary_SA_Additions) est une catégorie dans un cadre que j'ai mentionné plus tôt.

2020-08-27 11:00:03.017073+0100 MyApp[5881:81328] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConstantIntegerNumber characterAtIndex:]: unrecognized selector sent to instance 0x7fff86cc4850'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff20439dee __exceptionPreprocess + 242
    1   libobjc.A.dylib                     0x00007fff20177f78 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff2044893f +[NSObject(NSObject) instanceMethodSignatureForSelector:] + 0
    3   CoreFoundation                      0x00007fff2043e32e ___forwarding___ + 1489
    4   CoreFoundation                      0x00007fff20440368 _CF_forwarding_prep_0 + 120
    5   Foundation                          0x00007fff207c2b1f -[NSDictionary(NSKeyValueCoding) valueForKey:] + 79
    6   MyApp                               0x0000000101b645fd -[NSDictionary(NSDictionary_SA_Additions) SA_md5Hash] + 397
    7   MyApp                               0x0000000101b64646 -[NSDictionary(NSDictionary_SA_Additions) SA_md5Hash] + 470
    8   MyApp                               0x0000000101b6445b -[NSDictionary(NSDictionary_SA_Additions) hash] + 43
    9   libcache.dylib                      0x00007fff53be7bc7 _entry_get_optionally_checking_collisions + 42
    10  libcache.dylib                      0x00007fff53be6097 cache_get + 128
    11  CoreFoundation                      0x00007fff20465132 -[NSCache objectForKey:] + 152
    12  CoreText                            0x00007fff21000ed2 _ZN15TPurgeableCache19RetainedValueForKeyEPKv + 54
    13  CoreText                            0x00007fff210b192e _ZN12TCGFontCache21CopyFontWithVariationEP6CGFontPK14__CFDictionary + 1694
    14  CoreText                            0x00007fff210813e4 _ZNK29TTenuousComponentInstanceFont16CopyGraphicsFontEv + 150
    15  CoreText                            0x00007fff20fdf98b _ZNK9TBaseFont26GetInitializedGraphicsFontEv + 63
    16  CoreText                            0x00007fff2106ca11 _ZNK9TBaseFont13GetParserFontEv + 9
    17  CoreText                            0x00007fff21054284 _ZNK10TcmapTable8MapRangeE7CFRangePt + 42
    18  CoreText                            0x00007fff21072c20 _ZNK9TBaseFont26GetGlyphsForCharacterRangeE7CFRangePt + 94
    19  CoreText                            0x00007fff2107eab8 _ZNK14TComponentFont26GetGlyphsForCharacterRangeE7CFRangePt + 278
    20  CoreText                            0x00007fff20fc884a _ZN15TASCIIDataCacheC2EPK5TFont + 78
    21  CoreText                            0x00007fff20fdd430 _ZNK5TFont18InitASCIIDataCacheEv + 34
    22  CoreText                            0x00007fff20fcf9d0 CTFontGetLatin1GlyphsAndAdvanceWidths + 51
    23  UIFoundation                        0x00007fff239e0268 -[NSCoreTypesetter _NSFastDrawString:length:attributes:paragraphStyle:typesetterBehavior:lineBreakMode:rect:padding:graphicsContext:baselineRendering:usesFontLeading:usesScreenFont:scrollable:syncAlignment:mirrored:boundingRectPointer:baselineOffsetPointer:drawingContext:] + 1821
    24  UIFoundation                        0x00007fff239e1b0b -[NSCoreTypesetter _stringDrawingCoreTextEngineWithOriginalString:rect:padding:graphicsContext:forceClipping:attributes:stringDrawingOptions:drawingContext:stringDrawingInterface:] + 1278
    25  UIFoundation                        0x00007fff239db738 __NSStringDrawingEngine + 2887
    26  UIFoundation                        0x00007fff239dabc7 -[NSString(NSExtendedStringDrawing) boundingRectWithSize:options:attributes:context:] + 187
    27  UIKitCore                           0x00007fff24ae3d10 -[UILabel _drawTextInRect:baselineCalculationOnly:] + 4020
    28  UIKitCore                           0x00007fff24ae0ff7 -[UILabel drawTextInRect:] + 1061
    29  UIKitCore                           0x00007fff24ae3e42 -[UILabel drawRect:] + 71
    30  UIKitCore                           0x00007fff24ba1c85 -[UIView(CALayerDelegate) drawLayer:inContext:] + 625
    31  QuartzCore                          0x00007fff27a7830d -[CALayer drawInContext:] + 288
    32  QuartzCore                          0x00007fff27935321 CABackingStoreUpdate_ + 190
    33  QuartzCore                          0x00007fff27a819b9 ___ZN2CA5Layer8display_Ev_block_invoke + 53
    34  QuartzCore                          0x00007fff27a77b4a -[CALayer _display] + 2111
    35  QuartzCore                          0x00007fff27a8b327 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 463
    36  QuartzCore                          0x00007fff279cb3d4 _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 496
    37  QuartzCore                          0x00007fff27a02163 _ZN2CA11Transaction6commitEv + 783
    38  UIKitCore                           0x00007fff246656a0 __34-[UIApplication _firstCommitBlock]_block_invoke_2 + 81
    39  CoreFoundation                      0x00007fff203a834b __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
    40  CoreFoundation                      0x00007fff203a775f __CFRunLoopDoBlocks + 434
    41  CoreFoundation                      0x00007fff203a217c __CFRunLoopRun + 899
    42  CoreFoundation                      0x00007fff203a190e CFRunLoopRunSpecific + 567
    43  GraphicsServices                    0x00007fff2ba85db3 GSEventRunModal + 139
    44  UIKitCore                           0x00007fff24647ffd -[UIApplication _run] + 912
    45  UIKitCore                           0x00007fff2464cf0e UIApplicationMain + 101
    46  MyApp                               0x000000010177f16e main + 78
    47  libdyld.dylib                       0x00007fff20257415 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConstantIntegerNumber characterAtIndex:]: unrecognized selector sent to instance 0x7fff86cc4850'
CoreSimulator 732.13 - Device: iPad Air (3rd generation) (C762993D-AFF7-412A-89AF-92DB600B2153) - Runtime: iOS 14.0 (18A5351d) - DeviceType: iPad Air (3rd generation)
terminating with uncaught exception of type NSException
1
nOOb iOS 27 août 2020 à 12:39

2 réponses

Meilleure réponse

Intéressant. Il semble basé sur cette réponse que la véritable fonction de hachage de CFDictionary / NSDictionary est aussi basique que il obtient (la valeur de hachage calculée est le nombre d'éléments dans un dictionnaire). Cela conduirait à BEAUCOUP de collisions si quelqu'un voulait avoir un dictionnaire utilisant NSDictionary comme clé. Semble une raison plausible de remplacer la fonction de hachage de stock via la catégorie NSDictionary_SA_Additions avec l'implémentation SA_md5Hash.

Je pense que la prochaine étape serait d'étudier la fonction de hachage iOS14 de NSDictionary (avec des valeurs différentes à l'intérieur) par rapport aux versions iOS précédentes.

J'imagine qu'un correctif potentiel pourrait être de restaurer la fonction de hachage de NSDictionary si détecté sous iOS14 à condition que le framework gênant continue de fonctionner correctement.

MISE À JOUR: vous ne pouvez pas revenir à une catégorie. Mais vous pouvez le remplacer par un swizzling.

#include <objc/message.h>
__attribute__((constructor))
static void premain() {
    SEL hashSelector = @selector(hash);
    Method method = class_getClassMethod([NSDictionary class], hashSelector);
    const char * encoding = method_getTypeEncoding(method);
    IMP newHashImplementation = imp_implementationWithBlock(^NSUInteger (NSDictionary* self, SEL __cmd){
        return CFDictionaryGetCount((CFDictionaryRef)self);
    });
    class_replaceMethod([NSDictionary class], hashSelector, newHashImplementation, encoding);
}

C'est une nouvelle implémentation dans l'esprit de l'original. Malheureusement, nous ne pouvons pas obtenir le véritable original après le remplacement de la catégorie en raison du conflit du nom du sélecteur ("hash"). __attribute__((constructor)) garantit qu'il est exécuté comme la toute première chose une fois que votre application a terminé le lancement des catégories.

Alternativement pour inverser la catégorie au sens littéral, une modification binaire du framework est requise. Plus précisément le __TEXT,__objc_methname entrez la description de l'image ici entrez la description de l'image ici Vous changeriez le hash en quelque chose d'autre, par exemple hasg. Mais c'est presque certain d'être contre la licence du framework.

1
Kamil.S 31 août 2020 à 13:52

Quelqu'un appelle la fonction NSString characterAtIndex sur un objet de type NSConstantIntegerNumber, qui ne peut évidemment pas fonctionner.

À moins que vous ne vous sentiez responsable de la définition d'un entier en tant que clé dans un dictionnaire qui attend des clés de chaîne, je déposerais un rapport de bogue contre iOS 14.

1
gnasher729 31 août 2020 à 14:35