उद्देश्य सी
(शायद केवल अगर मैक ओएस एक्स पर क्लैंग के साथ संकलित किया गया है)
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
void unusedFunction(void) {
printf("huh?\n");
exit(0);
}
int main() {
NSString *string;
string = (__bridge id)(void*)0x2A27; // Is this really valid?
NSLog(@"%@", [string stringByAppendingString:@"foo"]);
return 0;
}
@interface MyClass : NSObject
@end
@implementation MyClass
+ (void)load {
Class newClass = objc_allocateClassPair([NSValue class], "MyClass2", 0);
IMP imp = class_getMethodImplementation(self, @selector(unusedMethod));
class_addMethod(object_getClass(newClass), _cmd, imp, "");
objc_registerClassPair(newClass);
[newClass load];
}
- (void)unusedMethod {
Class class = [self superclass];
IMP imp = (IMP)unusedFunction;
class_addMethod(class, @selector(doesNotRecognizeSelector:), imp, "");
}
@end
यह कोड अप्रयुक्त फ़ंक्शन को प्राप्त करने के लिए कई तरकीबों का उपयोग करता है। पहले मान 0x2A27 है। यह पूर्णांक 42 के लिए एक टैग किया गया सूचक है , जो किसी ऑब्जेक्ट को आवंटित करने से बचने के लिए पॉइंटर में मान को एन्कोड करता है।
अगला है MyClass
। इसका उपयोग कभी नहीं किया जाता है, लेकिन रनटाइम उस +load
विधि को कहता है जब इसे लोड किया जाता है, पहले main
। यह गतिशील NSValue
रूप से अपने सुपरक्लास के रूप में उपयोग करते हुए, एक नया वर्ग बनाता है और पंजीकृत करता है । यह भी एक कहते हैं +load
कि वर्ग के लिए पद्धति का उपयोग MyClass
के -unusedMethod
कार्यान्वयन के रूप में। पंजीकरण के बाद, यह नई कक्षा पर लोड विधि कहता है (किसी कारण से इसे स्वचालित रूप से नहीं कहा जाता है)।
चूंकि नए वर्ग की लोड विधि उसी कार्यान्वयन का उपयोग करती है unusedMethod
, जो प्रभावी रूप से कहा जाता है। यह स्वयं का सुपरक्लास लेता है, और unusedFunction
उस वर्ग के doesNotRecognizeSelector:
तरीके के कार्यान्वयन के रूप में जोड़ता है । यह विधि मूल रूप से एक उदाहरण विधि थी MyClass
, लेकिन इसे नए वर्ग पर एक वर्ग विधि के रूप में कहा जा रहा है, इसलिए self
नई कक्षा वस्तु है। इसलिए, सुपरक्लास वह है NSValue
, जिसके लिए सुपरक्लास भी है NSNumber
।
अंत में, main
चलाता है। यह पॉइंटर मान लेता है और इसे एक NSString *
चर में चिपका देता है ( __bridge
और void *
एआरसी के साथ या इसके बिना उपयोग करने की अनुमति देने के लिए पहली डाली )। फिर, यह stringByAppendingString:
उस चर पर कॉल करने की कोशिश करता है । चूंकि यह वास्तव में एक संख्या है, जो उस पद्धति को लागू नहीं करता है, इसलिए doesNotRecognizeSelector:
विधि को इसके बजाय कहा जाता है, जो कक्षा पदानुक्रम के माध्यम से यात्रा करता है NSValue
जहां यह प्रयोग करके लागू किया जाता है unusedFunction
।
नोट: अन्य प्रणालियों के साथ असंगति सूचक सूचक उपयोग के कारण है, जो मुझे नहीं लगता कि अन्य कार्यान्वयनों द्वारा कार्यान्वित किया गया है। यदि इसे सामान्य रूप से बनाई गई संख्या से बदल दिया गया तो बाकी कोड ठीक काम करना चाहिए।