Patch for leaks in NSHTTPURLHandle
Patch for leaks in NSHTTPURLHandle
- Subject: Patch for leaks in NSHTTPURLHandle
- From: "Steven W. Riggins" <email@hidden>
- Date: Mon, 29 Oct 2001 19:51:10 -0800
Thanks to Andrew Platzer for verifying where the bugs existed and what they were, so this patch could be written. Thanks to John Hvrnkvist for writing the patch shell and showing me how to patch Objective-C!
This code will patch if you are running on build 5L14 (10.1+security patch) or earlier. If 10.1.1 does not fix this patch, you will have to update your code.
Synopsis: NSURL uses NSURLHandles to retrieve data for particular URL types. Apple's NSHTTPURLHandle has two bugs. The first bug causes the NSHTTPURLHandle to never be freed, because its dealloc never calls super.
The second bug causes the data allocated by loadInForeground to never be released, because it does not call autorelease on its NSData.
These patches correct these bugs.
If you have a standard main.m, you can replace the contents of main.m with the following code. The patch is applied before you application runs.
This email was sent because I believe the more we share our fixes (and not just get answers in private emails and go on with life) the better Mac software we get quicker.
Enjoy!
Steve
// main.m
#import <Cocoa/Cocoa.h>
#import <objc/objc-class.h>
#import <Foundation/Foundation.h>
#import <AppKit/NSApplication.h>
extern void _objc_flush_caches(Class);
#define my_NSAppKitVersionNumber10_1 620 // From build 5L14
@interface NSHTTPURLHandle:NSURLHandle
{
}
+ (void)install_patch;
@end
@implementation NSHTTPURLHandle(DeallocPatch)
static IMP NSHTTPURLHandle_dealloc=nil;
static IMP NSHTTPURLHandle_loadInForeground=nil;
+ (void)install_patch
{
struct objc_method *method;
// patch dealloc
NSHTTPURLHandle_dealloc=[self instanceMethodForSelector:@selector(dealloc)];
if (method = class_getInstanceMethod([self class], @selector(dealloc)))
{
method->method_imp = [self instanceMethodForSelector:@selector(my_dealloc)];
_objc_flush_caches([self class]);
}
// patch loadInForeground
NSHTTPURLHandle_loadInForeground=[self instanceMethodForSelector:@selector(loadInForeground)];
if (method = class_getInstanceMethod([self class], @selector(loadInForeground)))
{
method->method_imp = [self instanceMethodForSelector:@selector(my_loadInForeground)];
_objc_flush_caches([self class]);
}
}
// NSHTTPURLHandle's dealloc does not call [super dealloc] so we'll do that here
- (void)my_dealloc
{
NSHTTPURLHandle_dealloc(self,@selector(dealloc));
[super dealloc];
}
// NSHTTPURLHandle's loadInForeground does not autorelease its data, so we will
- (NSData*)my_loadInForeground
{
// Call autorelease on the result
return ([NSHTTPURLHandle_loadInForeground(self,@selector(loadInForeground)) autorelease]);
}
@end
int main(int argc, const char *argv[])
{
if (NSAppKitVersionNumber <= my_NSAppKitVersionNumber10_1)
[NSHTTPURLHandle install_patch];
return NSApplicationMain(argc, argv);
}