From 25505b2e67d5bf2f689623ef7e8dbe1180d81066 Mon Sep 17 00:00:00 2001 From: rfm Date: Thu, 14 Nov 2024 14:45:05 +0000 Subject: [PATCH 01/64] Some more leak improvements --- Headers/GNUstepBase/NSObject+GNUstepBase.h | 17 ++++---- Source/Additions/NSObject+GNUstepBase.m | 7 ++-- Source/GSTLS.m | 48 ++++++++++++++-------- Source/NSCharacterSet.m | 30 ++++++++++++-- Source/NSTimeZone.m | 31 +++++++++----- 5 files changed, 90 insertions(+), 43 deletions(-) diff --git a/Headers/GNUstepBase/NSObject+GNUstepBase.h b/Headers/GNUstepBase/NSObject+GNUstepBase.h index cc4ccda058..bef4a5c74a 100644 --- a/Headers/GNUstepBase/NSObject+GNUstepBase.h +++ b/Headers/GNUstepBase/NSObject+GNUstepBase.h @@ -219,10 +219,10 @@ extern "C" { * set to YES).
* Your class then has two options for performing clean-up when the process * ends: - *

1. Use the +leaked: method to register objects which are simply to be - * retained until the process ends, and then either ignored or released - * depending on the clean-up setting in force. This mechanism is simple - * and should be sufficient for many classes. + *

1. Use the +leaked: method to register addresses whose contents are to + * be either ignored or released depending on the clean-up setting in force + * when the program exits. + * This mechanism is simple and should be sufficient for many classes. *

*

2. Implement a +atExit method to be run when the process ends and, * within your +initialize implementation, call +shouldCleanUp to determine @@ -241,10 +241,11 @@ extern "C" { */ + (BOOL) isExiting; -/** This method informs the system that the object at anAddress has been - * intentionally leaked (will not be deallocated by higher level code) - * and should be cleaned up at process exit (and the address content - * zeroed out) if clean-up is enabled. +/** This method informs the system that anAddress is a pointer whose content + * has been leaked and should be released and zeroed out (if clean-up is + * enabled) at process exit. If the content of the location is changed + * between the point where this method is called and the process exits, + * then the new content of the address is what will be released on clean-up. */ + (void) leaked: (id*)anAddress; diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m index 6b14eed965..d2c1c757bb 100644 --- a/Source/Additions/NSObject+GNUstepBase.m +++ b/Source/Additions/NSObject+GNUstepBase.m @@ -181,7 +181,7 @@ static inline void setup() isExiting = YES; unknownThread = GSRegisterCurrentThread(); - CREATE_AUTORELEASE_POOL(arp); + ENTER_POOL while (exited != 0) { @@ -202,7 +202,7 @@ static inline void setup() } else if (YES == shouldCleanUp) { - if (0 != tmp->at) + if (tmp->at) { tmp->obj = *(tmp->at); *(tmp->at) = nil; @@ -211,7 +211,8 @@ static inline void setup() } free(tmp); } - DESTROY(arp); + LEAVE_POOL + if (unknownThread == YES) { GSUnregisterCurrentThread(); diff --git a/Source/GSTLS.m b/Source/GSTLS.m index 24ec20eee7..b1a1f58674 100644 --- a/Source/GSTLS.m +++ b/Source/GSTLS.m @@ -188,9 +188,22 @@ static int gcry_mutex_unlock(void **lock) */ @implementation GSTLSObject +static NSLock *certificateListLock = nil; +static NSMutableDictionary *certificateListCache = nil; + +static NSLock *credentialsLock = nil; +static NSMutableDictionary *credentialsCache = nil; + static NSLock *fileLock = nil; static NSMutableDictionary *fileMap = nil; +static NSLock *paramsLock = nil; +static NSMutableDictionary *paramsCache = nil; + +static NSLock *privateKeyLock = nil; +static NSMutableDictionary *privateKeyCache0 = nil; +static NSMutableDictionary *privateKeyCache1 = nil; + + (void) _defaultsChanged: (NSNotification*)n { NSBundle *bundle; @@ -289,6 +302,21 @@ + (void) _defaultsChanged: (NSNotification*)n gnutls_global_set_log_level(globalDebug); } ++ (void) atExit +{ + DESTROY(certificateListLock); + DESTROY(certificateListCache); + DESTROY(credentialsLock); + DESTROY(credentialsCache); + DESTROY(fileLock); + DESTROY(fileMap); + DESTROY(paramsLock); + DESTROY(paramsCache); + DESTROY(privateKeyLock); + DESTROY(privateKeyCache0); + DESTROY(privateKeyCache1); +} + + (NSData*) dataForTLSFile: (NSString*)fileName { NSData *result; @@ -328,6 +356,8 @@ + (void) initialize { beenHere = YES; + [self registerAtExit]; + fileLock = [NSLock new]; fileMap = [NSMutableDictionary new]; @@ -397,8 +427,6 @@ + (void) setData: (NSData*)data forTLSFile: (NSString*)fileName @end @implementation GSTLSDHParams -static NSLock *paramsLock = nil; -static NSMutableDictionary *paramsCache = nil; static NSTimeInterval paramsWhen = 0.0; static BOOL paramsGenerating = NO; static GSTLSDHParams *paramsCurrent = nil; @@ -496,10 +524,8 @@ + (void) initialize if (nil == paramsLock) { paramsLock = [NSLock new]; - [[NSObject leakAt: ¶msLock] release]; paramsWhen = [NSDate timeIntervalSinceReferenceDate]; paramsCache = [NSMutableDictionary new]; - [[NSObject leakAt: ¶msCache] release]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(housekeeping:) name: @"GSHousekeeping" object: nil]; @@ -570,8 +596,6 @@ - (gnutls_dh_params_t) params @implementation GSTLSCertificateList -static NSLock *certificateListLock = nil; -static NSMutableDictionary *certificateListCache = nil; + (void) certInfo: (gnutls_x509_crt_t)cert to: (NSMutableString*)str { @@ -700,9 +724,7 @@ + (void) initialize if (nil == certificateListLock) { certificateListLock = [NSLock new]; - [[NSObject leakAt: &certificateListLock] release]; certificateListCache = [NSMutableDictionary new]; - [[NSObject leakAt: &certificateListCache] release]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(housekeeping:) name: @"GSHousekeeping" object: nil]; @@ -884,9 +906,6 @@ - (void) dealloc @implementation GSTLSPrivateKey -static NSLock *privateKeyLock = nil; -static NSMutableDictionary *privateKeyCache0 = nil; -static NSMutableDictionary *privateKeyCache1 = nil; /* Method to purge older keys from cache. */ @@ -940,11 +959,8 @@ + (void) initialize if (nil == privateKeyLock) { privateKeyLock = [NSLock new]; - [[NSObject leakAt: &privateKeyLock] release]; privateKeyCache0 = [NSMutableDictionary new]; - [[NSObject leakAt: &privateKeyCache0] release]; privateKeyCache1 = [NSMutableDictionary new]; - [[NSObject leakAt: &privateKeyCache1] release]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(housekeeping:) @@ -1074,8 +1090,6 @@ - (gnutls_x509_privkey_t) key @implementation GSTLSCredentials -static NSLock *credentialsLock = nil; -static NSMutableDictionary *credentialsCache = nil; /* Method to purge older credentials from cache. */ @@ -1106,9 +1120,7 @@ + (void) initialize if (nil == credentialsLock) { credentialsLock = [NSLock new]; - [[NSObject leakAt: &credentialsLock] release]; credentialsCache = [NSMutableDictionary new]; - [[NSObject leakAt: &credentialsCache] release]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(housekeeping:) diff --git a/Source/NSCharacterSet.m b/Source/NSCharacterSet.m index 5363887a44..cacd8c810f 100644 --- a/Source/NSCharacterSet.m +++ b/Source/NSCharacterSet.m @@ -632,6 +632,15 @@ - (Class) classForCoder return abstractClass; } +- (void) dealloc +{ + if (cache_map[_index] == self) + { + cache_map[_index] = nil; + } + [super dealloc]; +} + - (void) encodeWithCoder: (NSCoder*)aCoder { [aCoder encodeValueOfObjCType: @encode(int) at: &_index]; @@ -707,6 +716,20 @@ - (id) initWithBitmap: (NSData*)bitmap number: (int)number @implementation NSCharacterSet +static gs_mutex_t cache_lock = GS_MUTEX_INIT_STATIC; + ++ (void) atExit +{ + unsigned i; + + for (i = 0; i < MAX_STANDARD_SETS; i++) + { + GS_MUTEX_LOCK(cache_lock); + DESTROY(cache_set[i]); + GS_MUTEX_UNLOCK(cache_lock); + } +} + + (void) initialize { static BOOL beenHere = NO; @@ -723,6 +746,7 @@ + (void) initialize concreteMutableClass = [NSMutableBitmapCharSet class]; #endif beenHere = YES; + [self registerAtExit]; } } @@ -735,7 +759,7 @@ + (NSCharacterSet*) _staticSet: (const void*)bytes length: (unsigned)length number: (int)number { - static gs_mutex_t cache_lock = GS_MUTEX_INIT_STATIC; + NSCharacterSet *set; GS_MUTEX_LOCK(cache_lock); if (cache_set[number] == nil && bytes != 0) @@ -747,11 +771,11 @@ + (NSCharacterSet*) _staticSet: (const void*)bytes freeWhenDone: NO]; cache_set[number] = [[_GSStaticCharSet alloc] initWithBitmap: bitmap number: number]; - [[NSObject leakAt: &cache_set[number]] release]; RELEASE(bitmap); } + set = RETAIN(cache_set[number]); GS_MUTEX_UNLOCK(cache_lock); - return cache_set[number]; + return AUTORELEASE(set); } + (id) alphanumericCharacterSet diff --git a/Source/NSTimeZone.m b/Source/NSTimeZone.m index 3f478c7757..1768fbb606 100644 --- a/Source/NSTimeZone.m +++ b/Source/NSTimeZone.m @@ -643,7 +643,6 @@ + (void) initialize { absolutes = NSCreateMapTable(NSIntegerMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0); - [[NSObject leakAt: (id*)&absolutes] release]; } } @@ -1281,6 +1280,24 @@ + (id) allocWithZone: (NSZone*)z } } ++ (void) atExit +{ + id o; + + DESTROY(zoneDictionary); + DESTROY(placeholderMap); + DESTROY(localTimeZone); + DESTROY(defaultTimeZone); + DESTROY(systemTimeZone); + DESTROY(abbreviationDictionary); + DESTROY(abbreviationMap); + DESTROY(absolutes); + + o = defaultPlaceholderTimeZone; + defaultPlaceholderTimeZone = nil; + NSDeallocateObject(o); +} + /** * Return the default time zone for this process. */ @@ -1309,31 +1326,23 @@ + (void) initialize GS_MUTEX_INIT_RECURSIVE(zone_mutex); GSPlaceholderTimeZoneClass = [GSPlaceholderTimeZone class]; zoneDictionary = [[NSMutableDictionary alloc] init]; - [[NSObject leakAt: &zoneDictionary] release]; /* * Set up infrastructure for placeholder timezones. */ defaultPlaceholderTimeZone = (GSPlaceholderTimeZone*) NSAllocateObject(GSPlaceholderTimeZoneClass, 0, NSDefaultMallocZone()); - [[NSObject leakAt: &defaultPlaceholderTimeZone] release]; placeholderMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 0); - [[NSObject leakAt: (id*)&placeholderMap] release]; localTimeZone = [[NSLocalTimeZone alloc] init]; - [[NSObject leakAt: (id*)&localTimeZone] release]; - - [[NSObject leakAt: (id*)&defaultTimeZone] release]; - [[NSObject leakAt: (id*)&systemTimeZone] release]; - [[NSObject leakAt: (id*)&abbreviationDictionary] release]; - [[NSObject leakAt: (id*)&abbreviationMap] release]; - [[NSObject leakAt: (id*)&absolutes] release]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_notified:) name: NSUserDefaultsDidChangeNotification object: nil]; + + [self registerAtExit]; } } From 8b0543571b1108a23e4c98737ae2bb574f85239b Mon Sep 17 00:00:00 2001 From: rfm Date: Thu, 14 Nov 2024 14:56:28 +0000 Subject: [PATCH 02/64] Don't use deprecated +leak: method. --- Headers/GNUstepBase/NSObject+GNUstepBase.h | 2 +- Source/GSLocale.m | 3 ++- Source/NSDistributedNotificationCenter.m | 27 ++++++++++++++-------- Source/NSRunLoop.m | 15 +++++++----- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/Headers/GNUstepBase/NSObject+GNUstepBase.h b/Headers/GNUstepBase/NSObject+GNUstepBase.h index bef4a5c74a..150b5838f2 100644 --- a/Headers/GNUstepBase/NSObject+GNUstepBase.h +++ b/Headers/GNUstepBase/NSObject+GNUstepBase.h @@ -251,7 +251,7 @@ extern "C" { /** Deprecated: use +leaked: instead. */ -+ (id) NS_RETURNS_RETAINED leak: (id)anObject ;//GS_DEPRECATED_FUNC; ++ (id) NS_RETURNS_RETAINED leak: (id)anObject GS_DEPRECATED_FUNC; /** Deprecated: use +leaked: instead. */ diff --git a/Source/GSLocale.m b/Source/GSLocale.m index aacf68ff8b..d52ab8c964 100644 --- a/Source/GSLocale.m +++ b/Source/GSLocale.m @@ -222,7 +222,8 @@ */ if (saved == nil) { - saved = [NSObject leak: dict]; + saved = [dict copy]; + [NSObject leaked: &saved]; } /** diff --git a/Source/NSDistributedNotificationCenter.m b/Source/NSDistributedNotificationCenter.m index e68d40493f..c0d63f85c8 100644 --- a/Source/NSDistributedNotificationCenter.m +++ b/Source/NSDistributedNotificationCenter.m @@ -114,6 +114,13 @@ + (id) allocWithZone: (NSZone*)z return nil; } ++ (void) atExit +{ + DESTROY(locCenter); + DESTROY(pubCenter); + DESTROY(netCenter); +} + /** * Returns the default notification center ... a shared notification * center for the local host. This is simply a convenience method @@ -125,6 +132,11 @@ + (id) defaultCenter return [self notificationCenterForType: NSLocalNotificationCenterType]; } ++ (void) initialize +{ + [self registerAtExit]; +} + /** * Returns a notification center of the specified type.
* The NSLocalNotificationCenterType provides a shared access to @@ -144,7 +156,7 @@ + (NSDistributedNotificationCenter*) notificationCenterForType: (NSString*)type if (locCenter == nil) { GS_MUTEX_LOCK(classLock); - if (locCenter == nil) + if (locCenter == nil && NO == [NSObject isExiting]) { NS_DURING { @@ -154,8 +166,7 @@ + (NSDistributedNotificationCenter*) notificationCenterForType: (NSString*)type NSAllocateObject(self, 0, NSDefaultMallocZone()); tmp->_centerLock = [NSRecursiveLock new]; tmp->_type = RETAIN(NSLocalNotificationCenterType); - locCenter = [NSObject leak: tmp]; - [tmp release]; + locCenter = tmp; } NS_HANDLER { @@ -173,7 +184,7 @@ + (NSDistributedNotificationCenter*) notificationCenterForType: (NSString*)type if (pubCenter == nil) { GS_MUTEX_LOCK(classLock); - if (pubCenter == nil) + if (pubCenter == nil && NO == [NSObject isExiting]) { NS_DURING { @@ -183,8 +194,7 @@ + (NSDistributedNotificationCenter*) notificationCenterForType: (NSString*)type NSAllocateObject(self, 0, NSDefaultMallocZone()); tmp->_centerLock = [NSRecursiveLock new]; tmp->_type = RETAIN(GSPublicNotificationCenterType); - pubCenter = [NSObject leak: tmp]; - [tmp release]; + pubCenter = tmp; } NS_HANDLER { @@ -202,7 +212,7 @@ + (NSDistributedNotificationCenter*) notificationCenterForType: (NSString*)type if (netCenter == nil) { GS_MUTEX_LOCK(classLock); - if (netCenter == nil) + if (netCenter == nil && NO == [NSObject isExiting]) { NS_DURING { @@ -212,8 +222,7 @@ + (NSDistributedNotificationCenter*) notificationCenterForType: (NSString*)type NSAllocateObject(self, 0, NSDefaultMallocZone()); tmp->_centerLock = [NSRecursiveLock new]; tmp->_type = RETAIN(GSNetworkNotificationCenterType); - netCenter = [NSObject leak: tmp]; - [tmp release]; + netCenter = tmp; } NS_HANDLER { diff --git a/Source/NSRunLoop.m b/Source/NSRunLoop.m index 297226e6be..9b13b56062 100644 --- a/Source/NSRunLoop.m +++ b/Source/NSRunLoop.m @@ -786,7 +786,7 @@ + (NSRunLoop*) _runLoopForThread: (NSThread*) aThread NSTimer *timer; SEL sel; #ifdef RL_INTEGRATE_DISPATCH - GSMainQueueDrainer *drain; + static GSMainQueueDrainer *drainer = nil; #endif ctr = [NSNotificationCenter defaultCenter]; @@ -810,17 +810,20 @@ + (NSRunLoop*) _runLoopForThread: (NSThread*) aThread [current addTimer: timer forMode: NSDefaultRunLoopMode]; #ifdef RL_INTEGRATE_DISPATCH - /* We leak the queue drainer, because it's integral part of RL - * operations - */ - drain = [NSObject leak: [[GSMainQueueDrainer new] autorelease]]; + if (nil == drainer) + { + /* We leak the queue drainer, because it's integral part of RL + * operations + */ + drainer = [GSMainQueueDrainer new]; + } [current addEvent: [GSMainQueueDrainer mainQueueFileDescriptor] #ifdef _WIN32 type: ET_HANDLE #else type: ET_RDESC #endif - watcher: drain + watcher: drainer forMode: NSDefaultRunLoopMode]; #endif From 4185b687f2edab5e7f971ca3fc1f416d30129d60 Mon Sep 17 00:00:00 2001 From: rfm Date: Thu, 14 Nov 2024 15:30:01 +0000 Subject: [PATCH 03/64] fix little leak --- Source/NSUserDefaults.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/NSUserDefaults.m b/Source/NSUserDefaults.m index 0f4a57b256..0913bc8e35 100644 --- a/Source/NSUserDefaults.m +++ b/Source/NSUserDefaults.m @@ -1347,6 +1347,7 @@ - (void) dealloc RELEASE(_tempDomains); RELEASE(_changedDomains); RELEASE(_dictionaryRep); + RELEASE(_defaultsDatabase); RELEASE(_fileLock); RELEASE(_lock); [super dealloc]; From 43484b2c34d7a078b6fdc7221394078fa4bf4184 Mon Sep 17 00:00:00 2001 From: rfm Date: Thu, 14 Nov 2024 16:18:26 +0000 Subject: [PATCH 04/64] Fix deallocation of placeholder strings at exit. --- Source/NSString.m | 20 ++++++++++++++++++-- Tests/base/NSString/basic.m | 25 ++++++++++++++++--------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Source/NSString.m b/Source/NSString.m index 91077a9dda..561be82e3a 100644 --- a/Source/NSString.m +++ b/Source/NSString.m @@ -878,7 +878,23 @@ - (NSString *) _normalizedICUStringOfType: (const char*)normalization + (void) atExit { - DESTROY(placeholderMap); + /* Deallocate all the placeholders in the map before destroying it. + */ + GS_MUTEX_LOCK(placeholderLock); + if (placeholderMap) + { + NSMapEnumerator mEnum = NSEnumerateMapTable(placeholderMap); + Class c; + id o; + + while (NSNextMapEnumeratorPair(&mEnum, (void *)&c, (void *)&o)) + { + NSDeallocateObject(o); + } + NSEndMapTableEnumeration(&mEnum); + DESTROY(placeholderMap); + } + GS_MUTEX_UNLOCK(placeholderLock); DESTROY(nonBase); DESTROY(rPathSeps); DESTROY(uPathSeps); @@ -956,7 +972,7 @@ + (id) allocWithZone: (NSZone*)z */ GS_MUTEX_LOCK(placeholderLock); obj = (id)NSMapGet(placeholderMap, (void*)z); - if (obj == nil) + if (obj == nil && NO == [NSObject isExiting]) { /* * There is no placeholder object for this zone, so we diff --git a/Tests/base/NSString/basic.m b/Tests/base/NSString/basic.m index 2b87f05d2f..6698d5531b 100644 --- a/Tests/base/NSString/basic.m +++ b/Tests/base/NSString/basic.m @@ -24,7 +24,8 @@ int main() int i = 256; char buf[32]; NSString *s; - NSString *testObj = [NSString stringWithCString: "Hello\n"]; + NSData *d; + NSString *testObj = [NSString stringWithCString: "Hello\n"]; while (i-- > 0) { @@ -49,21 +50,25 @@ int main() isKindOfClass: [NSString class]] && ![s isKindOfClass: [NSMutableString class]], "[NSString initWithCharacters:length:] creates immutable string for ascii"); + DESTROY(s); PASS([(s = [[NSMutableString alloc] initWithCharacters: &u0 length: 1]) isKindOfClass: [NSString class]] && [s isKindOfClass: [NSMutableString class]], "[NSMutableString initWithCharacters:length:] creates mutable string for ascii"); + DESTROY(s); PASS([(s = [[NSString alloc] initWithCharacters: &u1 length: 1]) isKindOfClass: [NSString class]] && ![s isKindOfClass: [NSMutableString class]], "[NSString initWithCharacters:length:] creates immutable string for unicode"); + DESTROY(s); PASS([(s = [[NSMutableString alloc] initWithCharacters: &u1 length: 1]) isKindOfClass: [NSString class]] && [s isKindOfClass: [NSMutableString class]], "[NSMutableString initWithCharacters:length:] creates mutable string for unicode"); + DESTROY(s); PASS_EXCEPTION([[NSString alloc] initWithString: nil];, NSInvalidArgumentException, @@ -81,6 +86,7 @@ int main() isKindOfClass: [NSString class]] && [s length] == 256, "can create latin1 string with 256 values"); + DESTROY(s); PASS([(s = [[NSString alloc] initWithBytes: bytes length: 128 @@ -88,6 +94,7 @@ int main() isKindOfClass: [NSString class]] && [s length] == 128, "can create ascii string with 128 values"); + DESTROY(s); PASS(nil == [[NSString alloc] initWithBytes: bytes length: 256 @@ -97,18 +104,18 @@ int main() s = [[NSString alloc] initWithBytes: bytes length: 256 encoding: NSISOLatin1StringEncoding]; - s = [[NSString alloc] - initWithData: [s dataUsingEncoding: NSNonLossyASCIIStringEncoding] - encoding: NSASCIIStringEncoding]; + d = [s dataUsingEncoding: NSNonLossyASCIIStringEncoding]; + DESTROY(s); + s = [[NSString alloc] initWithData: d encoding: NSASCIIStringEncoding]; PASS_EQUAL(s, @"\\000\\001\\002\\003\\004\\005\\006\\007\\010\t\n\\013\\014\r\\016\\017\\020\\021\\022\\023\\024\\025\\026\\027\\030\\031\\032\\033\\034\\035\\036\\037 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\\177\\200\\201\\202\\203\\204\\205\\206\\207\\210\\211\\212\\213\\214\\215\\216\\217\\220\\221\\222\\223\\224\\225\\226\\227\\230\\231\\232\\233\\234\\235\\236\\237\\240\\241\\242\\243\\244\\245\\246\\247\\250\\251\\252\\253\\254\\255\\256\\257\\260\\261\\262\\263\\264\\265\\266\\267\\270\\271\\272\\273\\274\\275\\276\\277\\300\\301\\302\\303\\304\\305\\306\\307\\310\\311\\312\\313\\314\\315\\316\\317\\320\\321\\322\\323\\324\\325\\326\\327\\330\\331\\332\\333\\334\\335\\336\\337\\340\\341\\342\\343\\344\\345\\346\\347\\350\\351\\352\\353\\354\\355\\356\\357\\360\\361\\362\\363\\364\\365\\366\\367\\370\\371\\372\\373\\374\\375\\376\\377", "latin1 in lossy encoding"); NSLog(@"%lu '%s'", [s length], [s UTF8String]); - RELEASE(s); + DESTROY(s); s = [[NSString alloc] initWithData: [@"€" dataUsingEncoding: NSNonLossyASCIIStringEncoding] encoding: NSASCIIStringEncoding]; PASS_EQUAL(s, @"\\u20ac", "euro in lossy encoding"); - RELEASE(s); + DESTROY(s); s = [[NSString alloc] initWithBytes: "\\" length: 1 @@ -124,19 +131,19 @@ int main() length: 2 encoding: NSNonLossyASCIIStringEncoding]; PASS_EQUAL(s, @"\\", "lossy backslash-backslash is backslash"); - RELEASE(s); + DESTROY(s); s = [[NSString alloc] initWithBytes: "\\101" length: 4 encoding: NSNonLossyASCIIStringEncoding]; PASS_EQUAL(s, @"A", "lossy backslassh-101 is A"); - RELEASE(s); + DESTROY(s); s = [[NSString alloc] initWithBytes: "\\u20ac" length: 6 encoding: NSNonLossyASCIIStringEncoding]; PASS_EQUAL(s, @"€", "lossy backslassh-u20ac is a euro"); - RELEASE(s); + DESTROY(s); s = makeFormattedString(@"%d.%d%s", 10, 20, "hello"); PASS_EQUAL(s, @"10.20hello", "simple intWithFormat: works"); From bb57918f701a875bedf2a26dbfb327e095bfe733 Mon Sep 17 00:00:00 2001 From: rfm Date: Thu, 14 Nov 2024 17:57:55 +0000 Subject: [PATCH 05/64] Protect against dealloc before init --- Source/NSOperation.m | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/NSOperation.m b/Source/NSOperation.m index f60aea49f8..6a871dedaa 100644 --- a/Source/NSOperation.m +++ b/Source/NSOperation.m @@ -199,7 +199,9 @@ - (GSOperationCompletionBlock) completionBlock - (void) dealloc { - if (internal != nil) + /* Only clean up if ivars have been initialised + */ + if (internal && internal->lock) { NSOperation *op; @@ -832,7 +834,8 @@ - (id) init internal->cond = [[NSConditionLock alloc] initWithCondition: 0]; [internal->cond setName: [NSString stringWithFormat: @"cond-for-op-%p", self]]; - internal->name = [[NSString alloc] initWithFormat: @"NSOperationQueue %p", self]; + internal->name + = [[NSString alloc] initWithFormat: @"NSOperationQueue %p", self]; /* Ensure that default thread name can be displayed on systems with a * limited thread name length. From 1c7e81dee1bff2a2feb1a5fe46951d42d0440bdb Mon Sep 17 00:00:00 2001 From: rfm Date: Thu, 14 Nov 2024 18:57:05 +0000 Subject: [PATCH 06/64] Free 'leaked' memory at exit. --- Source/NSArray.m | 20 ++++++++++-- Source/NSTimeZone.m | 77 ++++++++++++++++++++++++++++----------------- Source/NSValue.m | 47 ++++++++++++++++++++++----- 3 files changed, 105 insertions(+), 39 deletions(-) diff --git a/Source/NSArray.m b/Source/NSArray.m index 828c739b52..2cff0f2114 100644 --- a/Source/NSArray.m +++ b/Source/NSArray.m @@ -114,7 +114,23 @@ + (void) atExit defaultPlaceholderArray = nil; NSDeallocateObject(o); - DESTROY(placeholderMap); + /* Deallocate all the placeholders in the map before destroying it. + */ + GS_MUTEX_LOCK(placeholderLock); + if (placeholderMap) + { + NSMapEnumerator mEnum = NSEnumerateMapTable(placeholderMap); + Class c; + id o; + + while (NSNextMapEnumeratorPair(&mEnum, (void *)&c, (void *)&o)) + { + NSDeallocateObject(o); + } + NSEndMapTableEnumeration(&mEnum); + DESTROY(placeholderMap); + } + GS_MUTEX_UNLOCK(placeholderLock); } + (void) initialize @@ -176,7 +192,7 @@ + (id) allocWithZone: (NSZone*)z */ GS_MUTEX_LOCK(placeholderLock); obj = (id)NSMapGet(placeholderMap, (void*)z); - if (obj == nil) + if (obj == nil && NO == [NSObject isExiting]) { /* * There is no placeholder object for this zone, so we diff --git a/Source/NSTimeZone.m b/Source/NSTimeZone.m index 1768fbb606..e7066e4e7c 100644 --- a/Source/NSTimeZone.m +++ b/Source/NSTimeZone.m @@ -189,12 +189,12 @@ Default place for the NSTimeZone directory is _time_zone_path(): static inline UCalendar * ICUCalendarSetup (NSTimeZone *tz, NSLocale *locale) { - NSString *tzStr; - int32_t tzLen; - const char *cLocale; - UChar tzName[BUFFER_SIZE]; - UCalendar *cal; - UErrorCode err = U_ZERO_ERROR; + NSString *tzStr; + int32_t tzLen; + const char *cLocale; + UChar tzName[BUFFER_SIZE]; + UCalendar *cal; + UErrorCode err = U_ZERO_ERROR; tzStr = [tz name]; if ((tzLen = [tzStr length]) > BUFFER_SIZE) @@ -287,6 +287,9 @@ @interface GSWindowsTimeZone : NSTimeZone /* one-to-many abbreviation to time zone name dictionary. */ static NSMutableDictionary *abbreviationMap = nil; +static NSArray *namesArray = nil; +static NSArray *regionsArray = nil; + /* Lock for creating time zones. */ static gs_mutex_t zone_mutex; @@ -991,7 +994,7 @@ + (NSDictionary*) abbreviationDictionary NSAutoreleasePool *pool = [NSAutoreleasePool new]; NSString *path; - path = _time_zone_path (ABBREV_DICT, @"plist"); + path = _time_zone_path(ABBREV_DICT, @"plist"); if (path != nil) { /* @@ -1195,8 +1198,6 @@ + (NSDictionary*) abbreviationMap */ + (NSArray*) knownTimeZoneNames { - static NSArray *namesArray = nil; - /* We create the array only when we need it to reduce overhead. */ if (namesArray != nil) { @@ -1204,7 +1205,7 @@ + (NSArray*) knownTimeZoneNames } GS_MUTEX_LOCK(zone_mutex); - if (namesArray == nil) + if (namesArray == nil && NO == [NSObject isExiting]) { unsigned i; NSMutableArray *ma; @@ -1284,14 +1285,33 @@ + (void) atExit { id o; + /* Deallocate all the placeholders in the map before destroying it. + */ + GS_MUTEX_LOCK(zone_mutex); + if (placeholderMap) + { + NSMapEnumerator mEnum = NSEnumerateMapTable(placeholderMap); + Class c; + id o; + + while (NSNextMapEnumeratorPair(&mEnum, (void *)&c, (void *)&o)) + { + NSDeallocateObject(o); + } + NSEndMapTableEnumeration(&mEnum); + DESTROY(placeholderMap); + } + GS_MUTEX_UNLOCK(zone_mutex); + DESTROY(zoneDictionary); - DESTROY(placeholderMap); DESTROY(localTimeZone); DESTROY(defaultTimeZone); DESTROY(systemTimeZone); DESTROY(abbreviationDictionary); DESTROY(abbreviationMap); DESTROY(absolutes); + DESTROY(namesArray); + DESTROY(regionsArray); o = defaultPlaceholderTimeZone; defaultPlaceholderTimeZone = nil; @@ -1653,7 +1673,8 @@ + (NSTimeZone*) systemTimeZone if (localZoneString != nil) { NSDebugLLog (@"NSTimeZone", @"Using zone %@", localZoneString); - zone = [defaultPlaceholderTimeZone initWithName: localZoneString]; + zone = AUTORELEASE([defaultPlaceholderTimeZone + initWithName: localZoneString]); if (zone == nil) { NSArray *possibleZoneNames; @@ -1689,7 +1710,7 @@ of possible time zone names (e.g. SAMT is valid for && [dflt contentsEqualAtPath: fileName andPath: SYSTEM_TIME_FILE]) { - zone = [[self timeZoneWithName: zoneName] retain]; + zone = [self timeZoneWithName: zoneName]; if (zone != nil) { @@ -1737,7 +1758,7 @@ of possible time zone names (e.g. SAMT is valid for @"See '%@'\n" @"for the standard timezones such as 'GB-Eire' or 'America/Chicago'.\n", LOCALDBKEY, LOCALDBKEY, _time_zone_path (ZONES_DIR, nil)); - zone = [[self timeZoneWithAbbreviation: localZoneString] retain]; + zone = [self timeZoneWithAbbreviation: localZoneString]; if (zone != nil) { NSInteger s; @@ -1771,7 +1792,7 @@ of possible time zone names (e.g. SAMT is valid for if (zone == nil) { NSLog(@"Using time zone with absolute offset 0."); - zone = systemTimeZone; + zone = [self timeZoneForSecondsFromGMT: 0]; } ASSIGN(systemTimeZone, zone); } @@ -1786,17 +1807,15 @@ of possible time zone names (e.g. SAMT is valid for * Each element contains an array of NSStrings which are * the region names. */ -+ (NSArray *)timeZoneArray ++ (NSArray*) timeZoneArray { - static NSArray *regionsArray = nil; - /* We create the array only when we need it to reduce overhead. */ if (regionsArray != nil) { return regionsArray; } GS_MUTEX_LOCK(zone_mutex); - if (regionsArray == nil) + if (regionsArray == nil && NO == [NSObject isExiting]) { NSAutoreleasePool *pool = [NSAutoreleasePool new]; NSMutableArray *temp_array[24]; @@ -1838,9 +1857,9 @@ + (NSArray *)timeZoneArray newLineSet = [NSCharacterSet newlineCharacterSet]; scanner = [NSScanner scannerWithString: contents]; - while ([scanner scanInteger: &index] && - [scanner scanUpToCharactersFromSet: newLineSet - intoString: &name]) + while ([scanner scanInteger: &index] + && [scanner scanUpToCharactersFromSet: newLineSet + intoString: &name]) { if (index < 0) index = 0; @@ -1851,7 +1870,7 @@ + (NSArray *)timeZoneArray } } else - { + { NSString *zonedir = [NSTimeZone _getTimeZoneFile: @"WET"]; if (tzdir != nil) @@ -2367,21 +2386,21 @@ - (NSString *) localizedName: (NSTimeZoneNameStyle)style UCalendar *cal; UErrorCode err = U_ZERO_ERROR; - cal = ICUCalendarSetup (self, locale); + cal = ICUCalendarSetup(self, locale); if (cal == NULL) return nil; cLocale = [[locale localeIdentifier] UTF8String]; - result = NSZoneMalloc ([self zone], BUFFER_SIZE * sizeof(UChar)); - len = ucal_getTimeZoneDisplayName (cal, _NSToICUTZDisplayStyle(style), + result = NSZoneMalloc([self zone], BUFFER_SIZE * sizeof(UChar)); + len = ucal_getTimeZoneDisplayName(cal, _NSToICUTZDisplayStyle(style), cLocale, result, BUFFER_SIZE, &err); if (len > BUFFER_SIZE) { - result = NSZoneRealloc ([self zone], result, len * sizeof(UChar)); - ucal_getTimeZoneDisplayName (cal, _NSToICUTZDisplayStyle(style), + result = NSZoneRealloc([self zone], result, len * sizeof(UChar)); + ucal_getTimeZoneDisplayName(cal, _NSToICUTZDisplayStyle(style), cLocale, result, len, &err); } - + ucal_close(cal); return AUTORELEASE([[NSString alloc] initWithCharactersNoCopy: result length: len freeWhenDone: YES]); #else diff --git a/Source/NSValue.m b/Source/NSValue.m index ace17dac0a..f55f0fe393 100644 --- a/Source/NSValue.m +++ b/Source/NSValue.m @@ -35,6 +35,7 @@ #import "Foundation/NSMapTable.h" #import "Foundation/NSLock.h" #import "Foundation/NSData.h" +#import "GSPThread.h" @interface GSPlaceholderValue : NSValue @end @@ -78,10 +79,41 @@ @interface NSDataStatic : NSData // Help the compiler static GSPlaceholderValue *defaultPlaceholderValue; static NSMapTable *placeholderMap; -static NSLock *placeholderLock; +static gs_mutex_t placeholderLock = GS_MUTEX_INIT_STATIC; + @implementation NSValue ++ (void) atExit +{ + id o; + + /* The default placeholder array overrides -dealloc so we must get rid of + * it directly. + */ + o = defaultPlaceholderValue; + defaultPlaceholderValue = nil; + NSDeallocateObject(o); + + /* Deallocate all the placeholders in the map before destroying it. + */ + GS_MUTEX_LOCK(placeholderLock); + if (placeholderMap) + { + NSMapEnumerator mEnum = NSEnumerateMapTable(placeholderMap); + Class c; + id o; + + while (NSNextMapEnumeratorPair(&mEnum, (void *)&c, (void *)&o)) + { + NSDeallocateObject(o); + } + NSEndMapTableEnumeration(&mEnum); + DESTROY(placeholderMap); + } + GS_MUTEX_UNLOCK(placeholderLock); +} + + (void) initialize { if (self == [NSValue class]) @@ -102,12 +134,9 @@ + (void) initialize */ defaultPlaceholderValue = (GSPlaceholderValue*) NSAllocateObject(GSPlaceholderValueClass, 0, NSDefaultMallocZone()); - [[NSObject leakAt: (id*)&defaultPlaceholderValue] release]; placeholderMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 0); - [[NSObject leakAt: (id*)&placeholderMap] release]; - placeholderLock = [NSLock new]; - [[NSObject leakAt: (id*)&placeholderLock] release]; + [self registerAtExit]; } } @@ -132,9 +161,9 @@ + (id) allocWithZone: (NSZone*)z * locate the correct placeholder in the (lock protected) * table of placeholders. */ - [placeholderLock lock]; + GS_MUTEX_LOCK(placeholderLock); obj = (id)NSMapGet(placeholderMap, (void*)z); - if (obj == nil) + if (obj == nil && NO == [NSObject isExiting]) { /* * There is no placeholder object for this zone, so we @@ -143,7 +172,7 @@ + (id) allocWithZone: (NSZone*)z obj = (id)NSAllocateObject(GSPlaceholderValueClass, 0, z); NSMapInsert(placeholderMap, (void*)z, (void*)obj); } - [placeholderLock unlock]; + GS_MUTEX_UNLOCK(placeholderLock); return obj; } } @@ -720,11 +749,13 @@ - (const char*) objCType - (oneway void) release { + NSWarnLog(@"-release sent to uninitialised value"); return; // placeholders never get released. } - (id) retain { + NSWarnLog(@"-retain sent to uninitialised value"); return self; // placeholders never get retained. } @end From 050f44806c4d173eee3849e8ad416109d3522351 Mon Sep 17 00:00:00 2001 From: rfm Date: Thu, 14 Nov 2024 20:26:37 +0000 Subject: [PATCH 07/64] fix leaks --- Tests/base/GSMime/build.m | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/Tests/base/GSMime/build.m b/Tests/base/GSMime/build.m index c8e45350fa..823cab901a 100644 --- a/Tests/base/GSMime/build.m +++ b/Tests/base/GSMime/build.m @@ -25,29 +25,28 @@ int main(int argc,char **argv) NSAutoreleasePool *arp = [NSAutoreleasePool new]; NSData *data = nil; NSString *string = nil; - GSMimeDocument *doc = [[GSMimeDocument alloc] init]; + GSMimeDocument *doc = AUTORELEASE([[GSMimeDocument alloc] init]); GSMimeDocument *mul; - NSMutableDictionary *par = [[NSMutableDictionary alloc] init]; + GSMimeHeader *hdr; + NSMutableDictionary *par = AUTORELEASE([[NSMutableDictionary alloc] init]); [par setObject: @"my/type" forKey: @"type"]; [doc setContent: @"Hello\r\n"]; - [doc setHeader: [[GSMimeHeader alloc] initWithName: @"content-type" - value: @"text/plain" - parameters: par]]; + [doc setHeader: [GSMimeHeader headerWithName: @"content-type" + value: @"text/plain" + parameters: par]]; - [doc setHeader: - [[GSMimeHeader alloc] initWithName: @"content-transfer-encoding" - value: @"binary" - parameters: nil]]; + [doc setHeader: [GSMimeHeader headerWithName: @"content-transfer-encoding" + value: @"binary" + parameters: nil]]; data = [NSData dataWithContentsOfFile: @"mime8.dat"]; PASS([[doc rawMimeData] isEqual: data], "Can make a simple document"); string = @"ABCD credit card account − more information about Peach Pay."; - [doc setHeader: - [[GSMimeHeader alloc] initWithName: @"subject" - value: string - parameters: nil]]; + [doc setHeader: [GSMimeHeader headerWithName: @"subject" + value: string + parameters: nil]]; data = [doc rawMimeData]; PASS(data != nil, "Can use non-ascii character in subject"); doc = [GSMimeParser documentFromData: data]; @@ -60,10 +59,9 @@ int main(int argc,char **argv) PASS_EQUAL([[doc headerNamed: @"subject"] value], string, "Can restore non-ascii character in subject form serialized document"); - [doc setHeader: - [[GSMimeHeader alloc] initWithName: @"subject" - value: @"€" - parameters: nil]]; + [doc setHeader: [GSMimeHeader headerWithName: @"subject" + value: @"€" + parameters: nil]]; data = [doc rawMimeData]; const char *bytes = "MIME-Version: 1.0\r\n" "Content-Type: text/plain; type=\"my/type\"\r\n" From 2f3b258bd1e500ee7fa93c19cf92b748948dd7d4 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 10:44:29 +0000 Subject: [PATCH 08/64] Fix leaks --- Tests/base/coding/basictypes.m | 100 ++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 44 deletions(-) diff --git a/Tests/base/coding/basictypes.m b/Tests/base/coding/basictypes.m index 6291621e45..62760789da 100644 --- a/Tests/base/coding/basictypes.m +++ b/Tests/base/coding/basictypes.m @@ -88,53 +88,60 @@ -(id)initWithCoder:(NSCoder *)coder #define TEST_DECL(testType,testName) \ void testWriteBasicType_##testName (char *typeName, testType *toEncode) \ { \ - NSData *data; \ - NSMutableData *mData; \ - NSString *fileName; \ - long typeSize = sizeof(testType); \ - fileName = [[NSString stringWithFormat:@"%s-%li.type",typeName,typeSize] retain]; \ - if (![fm isReadableFileAtPath:fileName]) \ + ENTER_POOL\ + NSData *data; \ + NSMutableData *mData; \ + NSString *fileName; \ + long typeSize = sizeof(testType); \ +\ + fileName = [NSString stringWithFormat:@"%s-%li.type", typeName, typeSize]; \ + if (![fm isReadableFileAtPath: fileName]) \ { \ NSArchiver *arch; \ - mData = [[NSMutableData alloc] init]; \ +\ + mData = [NSMutableData data]; \ arch = [[NSArchiver alloc] initForWritingWithMutableData: mData]; \ - [arch encodeValueOfObjCType:@encode(testType) at:toEncode]; \ - [arch encodeObject:str]; \ - [mData writeToFile:fileName atomically:YES]; \ - data = [NSData dataWithContentsOfFile:fileName]; \ - PASS([data isEqual:mData], \ + [arch encodeValueOfObjCType: @encode(testType) at: toEncode]; \ + [arch encodeObject: str]; \ + [mData writeToFile: fileName atomically: YES]; \ + data = [NSData dataWithContentsOfFile: fileName]; \ + PASS([data isEqual: mData], \ "can write %s of size %li", typeName, typeSize); \ - [fileName release]; \ - [mData release]; \ - [arch release]; \ + RELEASE(arch); \ } \ + LEAVE_POOL\ } \ void testReadBasicType_##testName (char *pre, testType *expect, testType *toDecode) \ { \ - NSData *data; \ - NSUnarchiver *unArch; \ - NSString *str2; \ - NSString *fileName; \ - long typeSize = sizeof(testType); \ - fileName = [[NSString stringWithFormat:@"%s-%li.type",pre,typeSize] retain]; \ - if ([fm isReadableFileAtPath:fileName]) \ - { \ - data = [NSData dataWithContentsOfFile:fileName]; \ - unArch = [[NSUnarchiver alloc] initForReadingWithData:data]; \ - NS_DURING \ - [unArch decodeValueOfObjCType:@encode(testType) at:toDecode]; \ - NS_HANDLER \ - NSLog(@"%@ %@", [localException name], [localException reason]); \ - PASS(0, "can unarchive %s from %s", pre, [fileName UTF8String]); \ - NS_ENDHANDLER \ - str2 = [unArch decodeObject]; \ - PASS((VAL_TEST(*expect,*toDecode) && [str isEqual:str2]), \ - "can unarchive %s from %s", pre, [fileName UTF8String]); \ - } \ + ENTER_POOL\ + NSString *fileName; \ + long typeSize = sizeof(testType); \ +\ + fileName = [NSString stringWithFormat: @"%s-%li.type", pre, typeSize]; \ + if ([fm isReadableFileAtPath: fileName]) \ + { \ + NSUnarchiver *unArch; \ + NSData *data; \ + NSString *str2; \ +\ + data = [NSData dataWithContentsOfFile: fileName]; \ + unArch = [[NSUnarchiver alloc] initForReadingWithData: data]; \ + NS_DURING \ + [unArch decodeValueOfObjCType: @encode(testType) at: toDecode]; \ + NS_HANDLER \ + NSLog(@"%@ %@", [localException name], [localException reason]); \ + PASS(0, "can unarchive %s from %s", pre, [fileName UTF8String]) \ + NS_ENDHANDLER \ + str2 = [unArch decodeObject]; \ + PASS((VAL_TEST(*expect, *toDecode) && [str isEqual: str2]), \ + "can unarchive %s from %s", pre, [fileName UTF8String]) \ + DESTROY(unArch); \ + } \ else \ - { \ - PASS(1 == 2, "Archive %s not found.", [fileName UTF8String]); \ - } \ + { \ + PASS(1 == 2, "Archive %s not found.", [fileName UTF8String]) \ + } \ + LEAVE_POOL\ } #define VAL_TEST(testX,testY) testX == testY @@ -231,12 +238,17 @@ int main() [obj1 setValues]; data = [NSArchiver archivedDataWithRootObject: obj1]; obj2 = [NSUnarchiver unarchiveObjectWithData: data]; - PASS([obj1 testCInt:obj2], "archiving as int - dearchiving as NSInteger"); - PASS([obj1 testCUInt:obj2], "archiving as unsigned int - dearchiving as NSUInteger"); - PASS([obj1 testNSInteger:obj2], "archiving as NSInteger - dearchiving as int"); - PASS([obj1 testNSUInteger:obj2], "archiving as NSUInteger - dearchiving as unsigned int"); - PASS([obj1 testArray:obj2], "archiving as NSInteger array - dearchiving as long long"); - + PASS([obj1 testCInt: obj2], + "archiving as int - dearchiving as NSInteger") + PASS([obj1 testCUInt: obj2], + "archiving as unsigned int - dearchiving as NSUInteger") + PASS([obj1 testNSInteger: obj2], + "archiving as NSInteger - dearchiving as int") + PASS([obj1 testNSUInteger: obj2], + "archiving as NSUInteger - dearchiving as unsigned int") + PASS([obj1 testArray: obj2], + "archiving as NSInteger array - dearchiving as long long") + RELEASE(obj1); [pool release]; pool = nil; return 0; } From 6386ac5474b6e5097dcb37ae6f2148c87e4c0056 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 10:49:19 +0000 Subject: [PATCH 09/64] Fix leaks --- Tests/base/coding/decoding.m | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Tests/base/coding/decoding.m b/Tests/base/coding/decoding.m index e6e73d0322..84416431ec 100644 --- a/Tests/base/coding/decoding.m +++ b/Tests/base/coding/decoding.m @@ -34,7 +34,7 @@ - (BOOL) testEquality: (id)other; @interface NSObject (DecodingTests) + (NSObject*) createTestInstance; + (BOOL) verifyTestInstance: (NSObject *)instance - ofVersion: (int)version; + ofVersion: (int)version; - (BOOL) testEquality; @end @@ -43,13 +43,13 @@ + (NSObject *) createTestInstance { if (self == [NSException class]) { - return [[NSException alloc] initWithName: @"Test" - reason: @"Testing" - userInfo: nil]; + return AUTORELEASE([[NSException alloc] initWithName: @"Test" + reason: @"Testing" + userInfo: nil]); } else { - return [[self alloc] init]; + return AUTORELEASE([[self alloc] init]); } } @@ -86,14 +86,14 @@ - (BOOL) testEquality @implementation NSCharacterSet (DecodingTests) + (NSObject *) createTestInstance { - return [[self characterSetWithCharactersInString: @"qwertzuiop"] retain]; + return [self characterSetWithCharactersInString: @"qwertzuiop"]; } @end @implementation NSValue (DecodingTests) + (NSObject *) createTestInstance { - return [[self valueWithSize: NSMakeSize(1.1, 1.2)] retain]; + return [self valueWithSize: NSMakeSize(1.1, 1.2)]; } - (BOOL) testEquality: (id)other { @@ -113,7 +113,7 @@ - (BOOL) testEquality: (id)other @implementation NSNumber (DecodingTests) + (NSObject *) createTestInstance { - return [[self numberWithInt: 1] retain]; + return [self numberWithInt: 1]; } @end @@ -125,7 +125,7 @@ + (NSObject *) createTestInstance if (NSHostByteOrder() == NS_BigEndian) { - NSMutableData *m = [data mutableCopy]; + NSMutableData *m = AUTORELEASE([data mutableCopy]); uint8_t *p = (uint8_t*)[m mutableBytes]; uint8_t *e = p + [m length]; @@ -141,7 +141,7 @@ + (NSObject *) createTestInstance } else { - return [data retain]; + return data; } } @end @@ -149,14 +149,14 @@ + (NSObject *) createTestInstance @implementation NSDate (DecodingTests) + (NSObject *) createTestInstance { - return [[NSDate dateWithTimeIntervalSince1970: 4294967296.0] retain]; + return [NSDate dateWithTimeIntervalSince1970: 4294967296.0]; } @end @implementation NSURL (DecodingTests) + (NSObject *) createTestInstance { - return [[self alloc] initWithString: @"http://www.gnustep.org/"]; + return AUTORELEASE([[self alloc] initWithString: @"http://www.gnustep.org/"]); } @end From 36822d6eef2809234ecab41ba4bb8c5e17348295 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 11:00:57 +0000 Subject: [PATCH 10/64] Fix leaks --- Tests/base/Functions/runtime.m | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Tests/base/Functions/runtime.m b/Tests/base/Functions/runtime.m index f0b89b2117..cc858f5989 100644 --- a/Tests/base/Functions/runtime.m +++ b/Tests/base/Functions/runtime.m @@ -118,7 +118,7 @@ - (const char *) sel2 PASS(0 == class_getVersion(Nil), "class_getVersion() for Nil is 0"); - obj = [NSObject new]; + obj = AUTORELEASE([NSObject new]); cls = [SubClass1 class]; PASS(c1initialize != 0, "+initialize was called"); @@ -188,6 +188,7 @@ - (const char *) sel2 PASS(sel_isEqual(sel, sel_getUid("catMethod")), "method 1 has expected name"); } + free(methods); ivars = class_copyIvarList(cls, &count); PASS(count == 1, "SubClass1 has one ivar"); @@ -196,12 +197,14 @@ - (const char *) sel2 "ivar has correct name"); PASS(strcmp(ivar_getTypeEncoding(ivars[0]), @encode(int)) == 0, "ivar has correct type"); + free(ivars); protocols = class_copyProtocolList(cls, &count); PASS(count == 1, "SubClass1 has one protocol"); PASS(protocols[count] == 0, "protocol list is terminated"); PASS(strcmp(protocol_getName(protocols[0]), "SubProto") == 0, "protocol has correct name"); + free(protocols); cls = objc_allocateClassPair([NSString class], "runtime generated", 0); PASS(cls != Nil, "can allocate a class pair"); @@ -213,7 +216,7 @@ - (const char *) sel2 "able to add iVar 'iv3'"); PASS(class_addIvar(cls, "iv4", 1, 3, "c") == YES, "able to add iVar 'iv4'"); - objc_registerClassPair (cls); + objc_registerClassPair(cls); ivar = class_getInstanceVariable(cls, "iv1"); PASS(ivar != 0, "iv1 exists"); PASS(ivar_getOffset(ivar) == 64, "iv1 offset is 64"); From 1536c243313ac3568c8987be8d22b259f9f86930 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 12:20:05 +0000 Subject: [PATCH 11/64] Fix buffer overrun --- Source/Additions/GSMime.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Additions/GSMime.m b/Source/Additions/GSMime.m index 07010a517c..9c69887c8b 100644 --- a/Source/Additions/GSMime.m +++ b/Source/Additions/GSMime.m @@ -3045,7 +3045,7 @@ - (NSString*) _decodeHeader */ if (tmp > src) { - unsigned char buf[tmp - src]; + unsigned char buf[tmp - src + 1]; unsigned char *ptr; ptr = decodeWord(buf, src, tmp, encoding); From a1e17402cfbdd50b2a298401c506551904e7c27f Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 12:27:48 +0000 Subject: [PATCH 12/64] fix leaks --- Tests/base/GSMime/build.m | 3 +- Tests/base/GSMime/test01.m | 64 +++++++++++++++++++++----------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/Tests/base/GSMime/build.m b/Tests/base/GSMime/build.m index 823cab901a..734f728691 100644 --- a/Tests/base/GSMime/build.m +++ b/Tests/base/GSMime/build.m @@ -27,7 +27,6 @@ int main(int argc,char **argv) NSString *string = nil; GSMimeDocument *doc = AUTORELEASE([[GSMimeDocument alloc] init]); GSMimeDocument *mul; - GSMimeHeader *hdr; NSMutableDictionary *par = AUTORELEASE([[NSMutableDictionary alloc] init]); [par setObject: @"my/type" forKey: @"type"]; @@ -63,9 +62,11 @@ int main(int argc,char **argv) value: @"€" parameters: nil]]; data = [doc rawMimeData]; +/* const char *bytes = "MIME-Version: 1.0\r\n" "Content-Type: text/plain; type=\"my/type\"\r\n" "Subject: =?utf-8?B?4oKs?=\r\n\r\n"; +*/ PASS(find((char*)[data bytes], (unsigned)[data length], "?B?4oKs?=") > 0, "encodes utf-8 euro in subject"); diff --git a/Tests/base/GSMime/test01.m b/Tests/base/GSMime/test01.m index 22fe140ba8..62f0755465 100644 --- a/Tests/base/GSMime/test01.m +++ b/Tests/base/GSMime/test01.m @@ -8,8 +8,8 @@ int main() NSAutoreleasePool *arp = [NSAutoreleasePool new]; GSMimeParser *parser = [GSMimeParser mimeParser]; NSStringEncoding enc = [GSMimeDocument encodingFromCharset: @"utf-8"]; - NSData *data; - GSMimeDocument *doc = [[parser mimeDocument] retain]; + NSData *data; + GSMimeDocument *doc = [parser mimeDocument]; GSMimeHeader *hdr; NSString *val; NSString *raw; @@ -50,41 +50,46 @@ int main() PASS([doc contentType] == nil, "First Header not complete until next starts"); - data = [@"Content-id: <" dataUsingEncoding:enc]; - PASS([parser parse: data] && - [parser isInHeaders], - "Adding partial headers is ok"); + data = [@"Content-id: <" dataUsingEncoding: enc]; + PASS([parser parse: data] && [parser isInHeaders], + "Adding partial headers is ok") - PASS([[doc contentType] isEqual: @"application"] && - [[doc contentSubtype] isEqual:@"xxx"],"Parsed first header as expected"); + PASS([[doc contentType] isEqual: @"application"] + && [[doc contentSubtype] isEqual:@"xxx"],"Parsed first header as expected") data = [@"hello>\r\n" dataUsingEncoding: enc]; - PASS([parser parse: data] && - [parser isInHeaders], - "Completing partial header is ok"); + PASS([parser parse: data] && [parser isInHeaders], + "Completing partial header is ok") - PASS([doc contentID] == nil, "Partial header not complete until next starts"); + PASS([doc contentID] == nil, "Partial header not complete until next starts") data = [@"Folded\r\n : testing\r\n" dataUsingEncoding:enc]; - PASS([parser parse:data] && [parser isInHeaders], "Folded header is ok"); + PASS([parser parse: data] && [parser isInHeaders], "Folded header is ok") - PASS([@"" isEqual: [doc contentID]],"Parsed partial header as expected %s",[[doc contentID] UTF8String]); + PASS([@"" isEqual: [doc contentID]], + "Parsed partial header as expected %s", [[doc contentID] UTF8String]) - PASS([doc headerNamed: @"Folded"] == nil,"Folded header not complete until next starts"); + PASS([doc headerNamed: @"Folded"] == nil, + "Folded header not complete until next starts") - data = [@"\r" dataUsingEncoding:enc]; - PASS([parser parse:data] && [parser isInHeaders], "partial end-of-line is ok"); + data = [@"\r" dataUsingEncoding: enc]; + PASS([parser parse:data] && [parser isInHeaders], + "partial end-of-line is ok") - PASS([[[doc headerNamed:@"Folded"] value] isEqual: @"testing"],"Parsed folded header as expected %s",[[[doc headerNamed:@"Folded"] value] UTF8String]); + PASS([[[doc headerNamed:@"Folded"] value] isEqual: @"testing"], + "Parsed folded header as expected %s", + [[[doc headerNamed:@"Folded"] value] UTF8String]) data = [@"\n" dataUsingEncoding:enc]; - PASS([parser parse:data] && ![parser isInHeaders], "completing end-of-line is ok"); + PASS([parser parse:data] && ![parser isInHeaders], + "completing end-of-line is ok") - doc = [GSMimeDocument documentWithContent:[@"\"\\UFE66???\"" propertyList] - type:@"text/plain" - name:nil]; + doc = [GSMimeDocument documentWithContent: [@"\"\\UFE66???\"" propertyList] + type: @"text/plain" + name: nil]; [doc rawMimeData]; - PASS([[[doc headerNamed:@"content-type"] parameterForKey:@"charset"] isEqual:@"utf-8"],"charset is inferred"); + PASS([[[doc headerNamed: @"content-type"] parameterForKey: @"charset"] + isEqual: @"utf-8"], "charset is inferred") val = @"by mail.turbocat.net (Postfix, from userid 1002) id 90885422ECBF; Sat, 22 Dec 2007 15:40:10 +0100 (CET)"; if ([[NSUserDefaults standardUserDefaults] @@ -96,7 +101,8 @@ int main() { raw = @"Received: by mail.turbocat.net (Postfix, from userid 1002) id 90885422ECBF;\r\n Sat, 22 Dec 2007 15:40:10 +0100 (CET)\r\n"; } - hdr = [[GSMimeHeader alloc] initWithName: @"Received" value: val]; + hdr = AUTORELEASE([[GSMimeHeader alloc] + initWithName: @"Received" value: val]); data = [hdr rawMimeDataPreservingCase: YES]; // NSLog(@"Header: '%*.*s'", [data length], [data length], [data bytes]); PASS([data isEqual: [raw dataUsingEncoding: NSASCIIStringEncoding]], @@ -104,14 +110,14 @@ int main() data = [NSData dataWithContentsOfFile: @"HTTP1.dat"]; parser = [GSMimeParser mimeParser]; - PASS ([parser parse: data] == NO, "can parse HTTP 200 reponse in one go"); - PASS ([parser isComplete], "parse is complete"); + PASS([parser parse: data] == NO, "can parse HTTP 200 reponse in one go") + PASS([parser isComplete], "parse is complete") data = [NSData dataWithContentsOfFile: @"HTTP2.dat"]; parser = [GSMimeParser mimeParser]; - PASS ([parser parse: data] == NO, "can parse HTTP chunked in one go"); - PASS ([parser isComplete], "parse is complete"); - PASS ([parser isComplete], "parse is complete"); + PASS([parser parse: data] == NO, "can parse HTTP chunked in one go") + PASS([parser isComplete], "parse is complete") + PASS([parser isComplete], "parse is complete") PASS_EQUAL([[parser mimeDocument] convertToText], @"This is the data in the first chunk\r\nand this is the second one\r\n" From 072c17f315536ec5f77aebf7508f0aaf8796c8e4 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 12:28:14 +0000 Subject: [PATCH 13/64] Add some consistecy checks --- Headers/GNUstepBase/NSObject+GNUstepBase.h | 32 ++++++++---- Source/Additions/NSObject+GNUstepBase.m | 58 ++++++++++++++++++---- 2 files changed, 68 insertions(+), 22 deletions(-) diff --git a/Headers/GNUstepBase/NSObject+GNUstepBase.h b/Headers/GNUstepBase/NSObject+GNUstepBase.h index 150b5838f2..ec06173584 100644 --- a/Headers/GNUstepBase/NSObject+GNUstepBase.h +++ b/Headers/GNUstepBase/NSObject+GNUstepBase.h @@ -241,21 +241,31 @@ extern "C" { */ + (BOOL) isExiting; -/** This method informs the system that anAddress is a pointer whose content - * has been leaked and should be released and zeroed out (if clean-up is - * enabled) at process exit. If the content of the location is changed - * between the point where this method is called and the process exits, - * then the new content of the address is what will be released on clean-up. +/** This method informs the system that anObject should be retained to + * persist until the process exits. If clean-up is enabled the object + * should be released upon process exit. + * If this method is called while the process is already existing it + * returns nil, otherwise it returnes the retained argument. + * Raises an exception if anObject has already been leaked or if it is + * nil (unless the process is exiting). */ -+ (void) leaked: (id*)anAddress; - -/** Deprecated: use +leaked: instead. ++ (id) NS_RETURNS_RETAINED leak: (id)anObject; + +/** This method informs the system that the object at anAddress has been + * retained to persist until the process exits. If clean-up is enabled + * the object should be released (and the address content zeroed out) + * upon process exit. + * If this method is called while the process is already existing it releases + * the object and zeros out the memory location then returns nil, otherwise + * it returns the object found at the memory location. + * Raises an exception if anAddress (or the object at anAddress) has already + * been leaked or if it is nil (unless the process is exiting). */ -+ (id) NS_RETURNS_RETAINED leak: (id)anObject GS_DEPRECATED_FUNC; ++ (void) leaked: (id*)anAddress; -/** Deprecated: use +leaked: instead. +/** DEPRECATED ... use +leaked: instead. */ -+ (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress ;//GS_DEPRECATED_FUNC; ++ (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress; /** Sets the receiver to have its +atExit method called at the point when * the process terminates.
diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m index d2c1c757bb..25ce0d1c95 100644 --- a/Source/Additions/NSObject+GNUstepBase.m +++ b/Source/Additions/NSObject+GNUstepBase.m @@ -227,33 +227,56 @@ + (BOOL) isExiting return isExiting; } -+ (void) leaked: (id*)anAddress ++ (id) leakAt: (id*)anAddress { - struct exitLink *l; + struct exitLink *l; - NSAssert(*anAddress && [*anAddress isKindOfClass: [NSObject class]], - NSInvalidArgumentException); l = (struct exitLink*)malloc(sizeof(struct exitLink)); l->at = anAddress; - l->obj = *anAddress; + l->obj = [*anAddress retain]; l->sel = 0; setup(); [exitLock lock]; l->next = exited; exited = l; [exitLock unlock]; + return l->obj; } -+ (id) leakAt: (id*)anAddress ++ (void) leaked: (id*)anAddress { struct exitLink *l; + NSAssert(anAddress != NULL, NSInvalidArgumentException); + if (isExiting) + { + [*anAddress release]; + *anAddress = nil; + return nil; + } + NSAssert([*anAddress isKindOfClass: [NSObject class]], + NSInvalidArgumentException); + setup(); + [exitLock lock]; + for (l = exited; l != NULL; l = l->next) + { + if (l->at == anAddress) + { + [exitLock unlock]; + [NSException raise: NSInvalidArgumentException + format: @"Repeated use of leak address %p", anAddress]; + } + if (*anAddress != nil && *anAddress == l->obj) + { + [exitLock unlock]; + [NSException raise: NSInvalidArgumentException + format: @"Repeated use of leak object %p", *anAddress]; + } + } l = (struct exitLink*)malloc(sizeof(struct exitLink)); l->at = anAddress; - l->obj = [*anAddress retain]; + l->obj = *anAddress; l->sel = 0; - setup(); - [exitLock lock]; l->next = exited; exited = l; [exitLock unlock]; @@ -264,12 +287,25 @@ + (id) leak: (id)anObject { struct exitLink *l; + if (nil == anObject || isExiting) + { + return nil; + } + setup(); + [exitLock lock]; + for (l = exited; l != NULL; l = l->next) + { + if (l->obj == anObject || (l->at != nil && *l->at == anObject)) + { + [exitLock unlock]; + [NSException raise: NSInvalidArgumentException + format: @"Repeated use of leak object %p", anObject]; + } + } l = (struct exitLink*)malloc(sizeof(struct exitLink)); l->at = 0; l->obj = [anObject retain]; l->sel = 0; - setup(); - [exitLock lock]; l->next = exited; exited = l; [exitLock unlock]; From 2f9f0d6761fbe4a827bc0712db732377b6466694 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 13:00:56 +0000 Subject: [PATCH 14/64] Fix leaks --- Tests/base/GSXML/basic.m | 42 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Tests/base/GSXML/basic.m b/Tests/base/GSXML/basic.m index 04dc29821b..bd41558e32 100644 --- a/Tests/base/GSXML/basic.m +++ b/Tests/base/GSXML/basic.m @@ -6,30 +6,30 @@ #import "ObjectTesting.h" int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSFileManager *mgr; - GSXMLParser *parser; - GSXMLDocument *doc; - GSXMLNamespace *namespace; - NSMutableArray *iparams; - NSMutableArray *oparams; - GSXMLNode *node; - GSXMLRPC *rpc; - NSString *str; - NSString *testPath; - NSString *absolutePath; - NSData *dat; - - TEST_FOR_CLASS(@"GSXMLDocument",[GSXMLDocument alloc], + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSFileManager *mgr; + GSXMLParser *parser; + GSXMLDocument *doc; + GSXMLNamespace *namespace; + NSMutableArray *iparams; + NSMutableArray *oparams; + GSXMLNode *node; + GSXMLRPC *rpc; + NSString *str; + NSString *testPath; + NSString *absolutePath; + NSData *dat; + + TEST_FOR_CLASS(@"GSXMLDocument", AUTORELEASE([GSXMLDocument alloc]), "GSXMLDocument +alloc returns a GSXMLDocument"); - TEST_FOR_CLASS(@"GSXMLDocument",[GSXMLDocument documentWithVersion: @"1.0"], + TEST_FOR_CLASS(@"GSXMLDocument", [GSXMLDocument documentWithVersion: @"1.0"], "GSXMLDocument +documentWithVersion: returns a GSXMLDocument"); - TEST_FOR_CLASS(@"GSXMLNode",[GSXMLNode alloc], + TEST_FOR_CLASS(@"GSXMLNode", AUTORELEASE([GSXMLNode alloc]), "GSXMLNode +alloc returns a GSXMLNode"); - TEST_FOR_CLASS(@"GSXMLRPC",[GSXMLRPC alloc], + TEST_FOR_CLASS(@"GSXMLRPC", AUTORELEASE([GSXMLRPC alloc]), "GSXMLRPC +alloc returns a GSXMLRPC instance"); NS_DURING @@ -39,7 +39,7 @@ int main() PASS(node == nil, "GSXMLNode +new returns nil"); NS_ENDHANDLER - TEST_FOR_CLASS(@"GSXMLNamespace",[GSXMLNamespace alloc], + TEST_FOR_CLASS(@"GSXMLNamespace", AUTORELEASE([GSXMLNamespace alloc]), "GSXMLNamespace +alloc returns a GSXMLNamespace"); @@ -54,7 +54,6 @@ int main() node = [doc makeNodeWithNamespace: nil name: @"nicola" content: nil]; PASS (node != nil,"Can create a document node"); - [doc setRoot: node]; PASS([[doc root] isEqual: node],"Can set document node as root node"); @@ -85,7 +84,8 @@ int main() "A namespace remembers its prefix"); - rpc = [(GSXMLRPC*)[GSXMLRPC alloc] initWithURL: @"http://localhost/"]; + rpc = AUTORELEASE([(GSXMLRPC*)[GSXMLRPC alloc] + initWithURL: @"http://localhost/"]); PASS(rpc != nil, "Can initialise an RPC instance"); iparams = [NSMutableArray array]; From bdad4987ae7c0c6976511fed8c4e6fe7443d6594 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 15:43:47 +0000 Subject: [PATCH 15/64] Fix leaked FFI structure argument/returntype information --- Source/GSFFIInvocation.m | 3 +- Source/GSInvocation.h | 11 +++-- Source/GSPrivate.h | 12 +++-- Source/NSInvocation.m | 4 +- Source/cifframe.h | 8 ++- Source/cifframe.m | 102 ++++++++++++++++++++++----------------- 6 files changed, 80 insertions(+), 60 deletions(-) diff --git a/Source/GSFFIInvocation.m b/Source/GSFFIInvocation.m index a861754a4c..327c344e9c 100644 --- a/Source/GSFFIInvocation.m +++ b/Source/GSFFIInvocation.m @@ -295,8 +295,7 @@ - (id) initWithMethodSignature: (NSMethodSignature*)aSignature _sig = RETAIN(aSignature); _numArgs = [aSignature numberOfArguments]; _info = [aSignature methodInfo]; - _frame = cifframe_from_signature(_sig); - [_frame retain]; + [self setupFrameFFI: _sig]; _cframe = [_frame mutableBytes]; /* Make sure we have somewhere to store the return value if needed. diff --git a/Source/GSInvocation.h b/Source/GSInvocation.h index 6c1eef1802..60a6934dbe 100644 --- a/Source/GSInvocation.h +++ b/Source/GSInvocation.h @@ -27,6 +27,7 @@ #import "Foundation/NSInvocation.h" @class NSMutableData; +@class NSPointerArray; typedef struct { int offset; @@ -39,13 +40,17 @@ typedef struct { } NSArgumentInfo; -@interface GSFFIInvocation : NSInvocation +@interface GSFFIInvocation : NSInvocation { @public - uint8_t _retbuf[32]; // Store return values of up to 32 bytes here. - NSMutableData *_frame; + uint8_t _retbuf[32]; // Return values of up to 32 bytes here. + NSMutableData *_frame; // Frame information for invoking. + NSPointerArray *_extra; // Extra FFI data to be released. } @end +@interface GSFFIInvocation (FFI) +- (void) setupFrameFFI: (NSMethodSignature*)sig; +@end @interface GSFFCallInvocation : NSInvocation { diff --git a/Source/GSPrivate.h b/Source/GSPrivate.h index 5ce4fd8a14..5adc3a3b92 100644 --- a/Source/GSPrivate.h +++ b/Source/GSPrivate.h @@ -32,6 +32,7 @@ @class _GSMutableInsensitiveDictionary; @class NSNotification; +@class NSPointerArray; @class NSRecursiveLock; #if ( (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) ) && HAVE_VISIBILITY_ATTRIBUTE ) @@ -555,17 +556,18 @@ GSPrivateUnloadModule(FILE *errorStream, */ @interface GSCodeBuffer : NSObject { - unsigned size; - void *buffer; - void *executable; - id frame; + unsigned size; + void *buffer; + void *executable; + id frame; + NSPointerArray *extra; } + (GSCodeBuffer*) memoryWithSize: (NSUInteger)_size; - (void*) buffer; - (void*) executable; - (id) initWithSize: (NSUInteger)_size; - (void) protect; -- (void) setFrame: (id)aFrame; +- (void) setFrame: (id)aFrame extra: (NSPointerArray*)pa; @end /* For tuning socket connections diff --git a/Source/NSInvocation.m b/Source/NSInvocation.m index a5af4863c6..7c05f3dec9 100644 --- a/Source/NSInvocation.m +++ b/Source/NSInvocation.m @@ -70,6 +70,7 @@ - (void*) buffer - (void) dealloc { DESTROY(frame); + DESTROY(extra); if (size > 0) { #if defined(HAVE_FFI_PREP_CLOSURE_LOC) @@ -173,9 +174,10 @@ - (void) protect #endif } -- (void) setFrame: (id)aFrame +- (void) setFrame: (id)aFrame extra: (NSPointerArray*)pa { ASSIGN(frame, aFrame); + ASSIGN(extra, pa); } @end diff --git a/Source/cifframe.h b/Source/cifframe.h index c20e5155ab..1316cff2d1 100644 --- a/Source/cifframe.h +++ b/Source/cifframe.h @@ -52,16 +52,14 @@ typedef struct _cifframe_t { @class NSMutableData; -extern NSMutableData *cifframe_from_signature (NSMethodSignature *info); - -extern GSCodeBuffer* cifframe_closure (NSMethodSignature *sig, void (*func)()); +extern GSCodeBuffer* cifframe_closure(NSMethodSignature *sig, void (*func)()); extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size); extern void cifframe_get_arg(cifframe_t *cframe, int index, void *buffer, int size); extern void *cifframe_arg_addr(cifframe_t *cframe, int index); -extern BOOL cifframe_decode_arg (const char *type, void* buffer); -extern BOOL cifframe_encode_arg (const char *type, void* buffer); +extern BOOL cifframe_decode_arg(const char *type, void* buffer); +extern BOOL cifframe_encode_arg(const char *type, void* buffer); #endif diff --git a/Source/cifframe.m b/Source/cifframe.m index 928639ddc1..2ae37d42ff 100644 --- a/Source/cifframe.m +++ b/Source/cifframe.m @@ -39,6 +39,7 @@ #endif #include "cifframe.h" +#import "Foundation/NSPointerArray.h" #import "Foundation/NSException.h" #import "Foundation/NSData.h" #import "GSInvocation.h" @@ -91,7 +92,8 @@ #endif #endif -ffi_type *cifframe_type(const char *typePtr, const char **advance); +static ffi_type * +cifframe_type(const char *typePtr, const char **adv, NSPointerArray **extra); /* Best guess at the space needed for a structure, since we don't know for sure until it's calculated in ffi_prep_cif, which is too late */ @@ -122,30 +124,30 @@ return size; } - -NSMutableData * -cifframe_from_signature (NSMethodSignature *info) +static void +cifframe_from_signature(NSMethodSignature *info, + NSMutableData **frame, NSPointerArray **extra) { - unsigned size = sizeof(cifframe_t); - unsigned align = __alignof(double); - unsigned type_offset = 0; - unsigned offset = 0; - NSMutableData *result; - void *buf; - int i; - int numargs = [info numberOfArguments]; - ffi_type *rtype; - ffi_type *arg_types[numargs]; - cifframe_t *cframe; - - /* FIXME: in cifframe_type, return values/arguments that are structures - have custom ffi_types with are allocated separately. We should allocate - them in our cifframe so we don't leak memory. Or maybe we could - cache structure types? */ - rtype = cifframe_type([info methodReturnType], NULL); + unsigned size = sizeof(cifframe_t); + unsigned align = __alignof(double); + unsigned type_offset = 0; + unsigned offset = 0; + NSMutableData *result; + void *buf; + int i; + int numargs = [info numberOfArguments]; + ffi_type *rtype; + ffi_type *arg_types[numargs]; + cifframe_t *cframe; + + /* The extra parameter returns an array of any allocated memory which + * needs freeing at the end of the invocation. + */ + rtype = cifframe_type([info methodReturnType], NULL, extra); for (i = 0; i < numargs; i++) { - arg_types[i] = cifframe_type([info getArgumentTypeAtIndex: i], NULL); + arg_types[i] + = cifframe_type([info getArgumentTypeAtIndex: i], NULL, extra); } if (numargs > 0) @@ -220,8 +222,20 @@ } } } - return result; + *frame = result; +} + +@implementation GSFFIInvocation (FFI) +- (void) setupFrameFFI: (NSMethodSignature*)info +{ + NSMutableData *f = nil; + NSPointerArray *e = nil; + + cifframe_from_signature(info, &f, &e); + ASSIGN(_frame, f); + ASSIGN(_extra, e); } +@end void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size) @@ -250,8 +264,8 @@ /* * Get the ffi_type for this type */ -ffi_type * -cifframe_type(const char *typePtr, const char **advance) +static ffi_type * +cifframe_type(const char *typePtr, const char **advance, NSPointerArray **extra) { static ffi_type stypeNSPoint = { 0 }; static ffi_type stypeNSRange = { 0 }; @@ -309,7 +323,7 @@ else { const char *adv; - cifframe_type(typePtr, &adv); + cifframe_type(typePtr, &adv, extra); typePtr = adv; } break; @@ -328,7 +342,7 @@ { typePtr++; } - cifframe_type(typePtr, &adv); + cifframe_type(typePtr, &adv, extra); typePtr = adv; typePtr++; /* Skip end-of-array */ } @@ -433,8 +447,8 @@ /* An NSRect is an NSPoint and an NSSize, but those * two structures are actually identical. */ - elems[0] = cifframe_type(@encode(NSSize), NULL); - elems[1] = cifframe_type(@encode(NSPoint), NULL); + elems[0] = cifframe_type(@encode(NSSize), NULL, extra); + elems[1] = cifframe_type(@encode(NSPoint), NULL, extra); elems[2] = 0; ftype->elements = elems; ftype->type = FFI_TYPE_STRUCT; @@ -471,7 +485,7 @@ */ while (*typePtr != _C_STRUCT_E) { - local = cifframe_type(typePtr, &adv); + local = cifframe_type(typePtr, &adv, extra); typePtr = adv; NSCAssert(typePtr, @"End of signature while parsing"); ftype->elements[types++] = local; @@ -485,6 +499,13 @@ } ftype->elements[types] = NULL; typePtr++; /* Skip end-of-struct */ + if (nil == *extra) + { + *extra = [NSPointerArray pointerArrayWithOptions: + NSPointerFunctionsOpaquePersonality + | NSPointerFunctionsMallocMemory]; + } + [*extra addPointer: ftype]; } break; @@ -508,19 +529,11 @@ { ffi_type *local; int align = objc_alignof_type(typePtr); - local = cifframe_type(typePtr, &adv); + local = cifframe_type(typePtr, &adv, extra); typePtr = adv; NSCAssert(typePtr, @"End of signature while parsing"); if (align > max_align) { - if (ftype && ftype->type == FFI_TYPE_STRUCT - && ftype != &stypeNSPoint - && ftype != &stypeNSRange - && ftype != &stypeNSRect - && ftype != &stypeNSSize) - { - free(ftype); - } ftype = local; max_align = align; } @@ -557,21 +570,22 @@ } GSCodeBuffer* -cifframe_closure (NSMethodSignature *sig, void (*cb)()) +cifframe_closure(NSMethodSignature *sig, void (*cb)()) { - NSMutableData *frame; + NSMutableData *frame = nil; + NSPointerArray *extra = nil; cifframe_t *cframe; ffi_closure *cclosure; void *executable; GSCodeBuffer *memory; - /* Construct the frame (stored in an NSMutableDate object) and sety it + /* Construct the frame (stored in an NSMutableDate object) and set it * in a new closure. */ - frame = cifframe_from_signature(sig); + cifframe_from_signature(sig, &frame, &extra); cframe = [frame mutableBytes]; memory = [GSCodeBuffer memoryWithSize: sizeof(ffi_closure)]; - [memory setFrame: frame]; + [memory setFrame: frame extra: extra]; cclosure = [memory buffer]; executable = [memory executable]; if (cframe == NULL || cclosure == NULL) From 91be2c2c836c7e6294f309d4bbd9dae018a67807 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 15:44:39 +0000 Subject: [PATCH 16/64] Fix leaks --- Tests/base/Functions/NSZone.m | 4 ++-- Tests/base/KVC/array.m | 2 +- Tests/base/KVC/nil.m | 6 +++--- Tests/base/NSInvocation/test01.m | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Tests/base/Functions/NSZone.m b/Tests/base/Functions/NSZone.m index a55f0aef17..cc23597848 100644 --- a/Tests/base/Functions/NSZone.m +++ b/Tests/base/Functions/NSZone.m @@ -76,8 +76,8 @@ int main() "NSZoneFromPointer() returns zone where memory came from"); NS_DURING - [NSString allocWithZone:aZone]; - NSRecycleZone(aZone); + NSZoneMalloc(aZone, 42); + NSRecycleZone(aZone); PASS(1,"NSRecycleZone seems to operate"); NS_HANDLER PASS(0,"NSRecycleZone seems to operate"); diff --git a/Tests/base/KVC/array.m b/Tests/base/KVC/array.m index 32c65e24b4..09f169cbd6 100644 --- a/Tests/base/KVC/array.m +++ b/Tests/base/KVC/array.m @@ -45,7 +45,7 @@ int main(int argc,char **argv) result = [[array valueForKeyPath:@"@count"] intValue] == 2; PASS(result, "-[NSArray valueForKeyPath: @\"@count\"]"); - aiv = [ArrayIVar new]; + aiv = AUTORELEASE([ArrayIVar new]); ivar = [NSArray arrayWithObjects: @"Joe", @"Foo", @"Bar", @"Cat", nil]; [aiv setTestArray: ivar]; diff --git a/Tests/base/KVC/nil.m b/Tests/base/KVC/nil.m index 457b555e7a..0fd9e7c89d 100644 --- a/Tests/base/KVC/nil.m +++ b/Tests/base/KVC/nil.m @@ -43,9 +43,9 @@ int main() { NSAutoreleasePool *arp = [NSAutoreleasePool new]; - DefaultNil * defaultNil = [DefaultNil new]; - DeprecatedNil * deprecatedNil = [DeprecatedNil new]; - SetNil * setNil = [SetNil new]; + DefaultNil *defaultNil = AUTORELEASE([DefaultNil new]); + DeprecatedNil *deprecatedNil = AUTORELEASE([DeprecatedNil new]); + SetNil *setNil = AUTORELEASE([SetNil new]); PASS_EXCEPTION([defaultNil setValue: nil forKey: @"num"], NSInvalidArgumentException, "KVC handles setting nil for a scalar") diff --git a/Tests/base/NSInvocation/test01.m b/Tests/base/NSInvocation/test01.m index 16cbfd4ff7..872eaf8a7f 100644 --- a/Tests/base/NSInvocation/test01.m +++ b/Tests/base/NSInvocation/test01.m @@ -33,7 +33,7 @@ int main() tClass = NSClassFromString(@"InvokeTarget"); - tar = [tClass new]; + tar = AUTORELEASE([tClass new]); /* Test if the return value is retained. It is in the Apple OpenStep edition From 70b687d3fd40766bce250b9232eedd56580eb028 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 16:00:01 +0000 Subject: [PATCH 17/64] Fix leak. --- Source/NSUnarchiver.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/NSUnarchiver.m b/Source/NSUnarchiver.m index 22345a3e9a..784de669ea 100644 --- a/Source/NSUnarchiver.m +++ b/Source/NSUnarchiver.m @@ -488,6 +488,7 @@ - (id) initForReadingWithData: (NSData*)anObject { if (anObject == nil) { + RELEASE(self); [NSException raise: NSInvalidArgumentException format: @"nil data passed to initForReadingWithData:"]; } From 093ab72a475bcf89d1f1a2f248a552d71836b268 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 16:00:47 +0000 Subject: [PATCH 18/64] Fix leaks --- Tests/base/NSAffineTransform/basic.m | 16 ++++++++-------- Tests/base/NSArchiver/basic.m | 6 ++++-- Tests/base/NSArchiver/create.m | 18 ++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Tests/base/NSAffineTransform/basic.m b/Tests/base/NSAffineTransform/basic.m index 3c06a5487e..38937be613 100644 --- a/Tests/base/NSAffineTransform/basic.m +++ b/Tests/base/NSAffineTransform/basic.m @@ -30,10 +30,10 @@ static BOOL eq(double d1, double d2) int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSAffineTransform *testObj; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSAffineTransform *testObj; NSAffineTransformStruct flip = {1.0,0.0,0.0,-1.0,0.0,0.0}; - NSMutableArray *testObjs = [NSMutableArray new]; + NSMutableArray *testObjs = [NSMutableArray array]; NSAffineTransform *aa, *bb, *cc; NSAffineTransformStruct as = {2, 3, 4, 5, 10, 20}; NSAffineTransformStruct bs = {6, 7, 8, 9, 14, 15}; @@ -55,7 +55,7 @@ int main() NSPoint p; NSSize s; - testObj = [NSAffineTransform new]; + testObj = AUTORELEASE([NSAffineTransform new]); [testObjs addObject:testObj]; PASS(testObj != nil, "can create a new transfor"); @@ -109,19 +109,19 @@ int main() [bb setTransformStruct: bs]; /* Append matrix */ - cc = [aa copy]; + cc = AUTORELEASE([aa copy]); [cc appendTransform: bb]; cs = [cc transformStruct]; PASS((is_equal_struct(cs, answer1)), "appendTransform:") /* Prepend matrix */ - cc = [aa copy]; + cc = AUTORELEASE([aa copy]); [cc prependTransform: bb]; cs = [cc transformStruct]; PASS((is_equal_struct(cs, answer2)), "prependTransform:") /* scaling */ - cc = [aa copy]; + cc = AUTORELEASE([aa copy]); [cc scaleXBy: 3 yBy: 2]; cs = [cc transformStruct]; PASS((is_equal_struct(cs, answer3)), "scaleXBy:yBy:") @@ -132,7 +132,7 @@ int main() //print_matrix ("Trans X Scale X A", cs); /* rotation */ - cc = [aa copy]; + cc = AUTORELEASE([aa copy]); [cc rotateByDegrees: 2.5]; cs = [cc transformStruct]; PASS((is_equal_struct(cs, answer5)), "rotateByDegrees") diff --git a/Tests/base/NSArchiver/basic.m b/Tests/base/NSArchiver/basic.m index 743dd6a1fb..a797d80269 100644 --- a/Tests/base/NSArchiver/basic.m +++ b/Tests/base/NSArchiver/basic.m @@ -4,9 +4,11 @@ int main() { NSAutoreleasePool *arp = [NSAutoreleasePool new]; test_alloc(@"NSArchiver"); - test_NSObject(@"NSArchiver",[NSArray arrayWithObject:[[NSArchiver alloc] init]]); + test_NSObject(@"NSArchiver", + [NSArray arrayWithObject: AUTORELEASE([[NSArchiver alloc] init])]); test_alloc(@"NSUnarchiver"); - test_NSObject(@"NSUnarchiver",[NSArray arrayWithObject:[[NSUnarchiver alloc] init]]); + test_NSObject(@"NSUnarchiver", + [NSArray arrayWithObject: AUTORELEASE([[NSUnarchiver alloc] init])]); [arp release]; arp = nil; return 0; diff --git a/Tests/base/NSArchiver/create.m b/Tests/base/NSArchiver/create.m index d2b535da53..1ad38400ce 100644 --- a/Tests/base/NSArchiver/create.m +++ b/Tests/base/NSArchiver/create.m @@ -7,23 +7,21 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - id obj = [NSArchiver new]; - NSMutableData *data1; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + id obj = [NSArchiver new]; + NSMutableData *data1; PASS((obj != nil && [obj isKindOfClass:[NSArchiver class]] && [obj archiverData] != nil), "+new creates an empty NSArchiver"); [obj release]; - obj = [NSArchiver alloc]; data1 = [NSMutableData dataWithLength: 0]; - obj = [obj initForWritingWithMutableData: data1]; - PASS((obj != nil && [obj isKindOfClass:[NSArchiver class]] && data1 == [obj archiverData]), "-initForWritingWithMutableData seems ok"); + obj = AUTORELEASE([[NSArchiver alloc] initForWritingWithMutableData: data1]); + PASS((obj != nil && [obj isKindOfClass: [NSArchiver class]] + && data1 == [obj archiverData]), "-initForWritingWithMutableData seems ok"); PASS_EXCEPTION([[NSUnarchiver alloc] initForReadingWithData:nil];, - @"NSInvalidArgumentException", - "Creating an NSUnarchiver with nil data throws an exception"); - - + @"NSInvalidArgumentException", + "Creating an NSUnarchiver with nil data throws an exception"); [arp release]; arp = nil; return 0; From d7c9bdbce7beffdf499986e0261c821e362dc070 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 18:35:41 +0000 Subject: [PATCH 19/64] Fix nil to NULL --- Source/Additions/NSObject+GNUstepBase.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m index 25ce0d1c95..0e3c7b21ac 100644 --- a/Source/Additions/NSObject+GNUstepBase.m +++ b/Source/Additions/NSObject+GNUstepBase.m @@ -295,7 +295,7 @@ + (id) leak: (id)anObject [exitLock lock]; for (l = exited; l != NULL; l = l->next) { - if (l->obj == anObject || (l->at != nil && *l->at == anObject)) + if (l->obj == anObject || (l->at != NULL && *l->at == anObject)) { [exitLock unlock]; [NSException raise: NSInvalidArgumentException From 8209fa428fed1cf92070e339428713cc36bc57d0 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 18:47:45 +0000 Subject: [PATCH 20/64] Lazy initialisation of nonBase charset info to avoid recursion during startup --- Source/NSString.m | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Source/NSString.m b/Source/NSString.m index 561be82e3a..1f37e2edef 100644 --- a/Source/NSString.m +++ b/Source/NSString.m @@ -169,6 +169,7 @@ @interface GSPlaceholderString : NSString // Help the compiler static SEL cMemberSel = 0; static NSCharacterSet *nonBase = nil; static BOOL (*nonBaseImp)(id, SEL, unichar) = 0; +static gs_mutex_t nonBaseLock = GS_MUTEX_INIT_STATIC; static NSCharacterSet *wPathSeps = nil; static NSCharacterSet *uPathSeps = nil; @@ -231,8 +232,24 @@ static inline BOOL isWhiteSpace(unichar c) * to a number of issues with UTF-16 */ if ((u >= 0xdc00) && (u <= 0xdfff)) - return YES; - + { + return YES; + } + if (0 == nonBaseImp) + { + GS_MUTEX_LOCK(nonBaseLock); + if (nil == nonBase) + { + nonBase = RETAIN([NSCharacterSet nonBaseCharacterSet]); + nonBaseImp + = (BOOL(*)(id,SEL,unichar))[nonBase methodForSelector: cMemberSel]; + } + GS_MUTEX_UNLOCK(nonBaseLock); + if (0 == nonBaseImp) + { + return NO; // if charset is missing (prerhaps during process exit) + } + } return (*nonBaseImp)(nonBase, cMemberSel, u); } @@ -917,10 +934,6 @@ + (void) initialize gcrSel = @selector(getCharacters:range:); ranSel = @selector(rangeOfComposedCharacterSequenceAtIndex:); - nonBase = [NSCharacterSet nonBaseCharacterSet]; - nonBaseImp - = (BOOL(*)(id,SEL,unichar))[nonBase methodForSelector: cMemberSel]; - _DefaultStringEncoding = GSPrivateDefaultCStringEncoding(); _ByteEncodingOk = GSPrivateIsByteEncoding(_DefaultStringEncoding); From 77c66e3d95772fbda127d27e026b72cafe02af5b Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 20:48:09 +0000 Subject: [PATCH 21/64] Fix leaks --- Source/NSDictionary.m | 1 + Source/NSFileHandle.m | 4 +- Source/NSFileManager.m | 2 +- Source/NSInvocationOperation.m | 1 + Source/NSOperation.m | 10 +- Tests/base/NSArray/basic.m | 32 ++--- Tests/base/NSAttributedString/basic.m | 6 +- Tests/base/NSAttributedString/test00.m | 49 ++++---- Tests/base/NSAutoreleasePool/autorelease_eh.m | 31 ++--- Tests/base/NSBundle/basic.m | 3 +- Tests/base/NSCalendar/era.m | 39 ++++--- Tests/base/NSCalendarDate/basic.m | 4 +- Tests/base/NSCalendarDate/test02.m | 20 ++-- Tests/base/NSData/base64.m | 5 + Tests/base/NSData/basic.m | 15 +-- Tests/base/NSData/general.m | 110 +++++++++--------- Tests/base/NSDictionary/basic.m | 34 +++--- Tests/base/NSDictionary/create.m | 108 ++++++++--------- Tests/base/NSDistributedLock/basic.m | 2 +- Tests/base/NSFastEnumeration/basic.m | 44 +++---- Tests/base/NSFileHandle/general.m | 38 +++--- Tests/base/NSFileManager/general.m | 2 +- Tests/base/NSInvocationOperation/basic.m | 2 +- 23 files changed, 295 insertions(+), 267 deletions(-) diff --git a/Source/NSDictionary.m b/Source/NSDictionary.m index 647afd2ba9..9416e4ddaf 100644 --- a/Source/NSDictionary.m +++ b/Source/NSDictionary.m @@ -469,6 +469,7 @@ - (id) initWithObjects: (NSArray*)objects forKeys: (NSArray*)keys if (objectCount != [keys count]) { + RELEASE(self); [NSException raise: NSInvalidArgumentException format: @"init with obj and key arrays of different sizes"]; } diff --git a/Source/NSFileHandle.m b/Source/NSFileHandle.m index a0b6e5df5d..4a6672c66e 100644 --- a/Source/NSFileHandle.m +++ b/Source/NSFileHandle.m @@ -91,11 +91,11 @@ + (id) allocWithZone: (NSZone*)z { if (self == NSFileHandle_abstract_class) { - return NSAllocateObject (NSFileHandle_concrete_class, 0, z); + return NSAllocateObject(NSFileHandle_concrete_class, 0, z); } else { - return NSAllocateObject (self, 0, z); + return NSAllocateObject(self, 0, z); } } diff --git a/Source/NSFileManager.m b/Source/NSFileManager.m index 497faf426f..55552ebde2 100644 --- a/Source/NSFileManager.m +++ b/Source/NSFileManager.m @@ -989,7 +989,7 @@ - (NSDirectoryEnumerator*) enumeratorAtURL: (NSURL*)url errorHandler: handler for: self]; - return direnum; + return AUTORELEASE(direnum); } - (NSArray*) contentsOfDirectoryAtPath: (NSString*)path error: (NSError**)error diff --git a/Source/NSInvocationOperation.m b/Source/NSInvocationOperation.m index ba7e2d6727..ab80587600 100644 --- a/Source/NSInvocationOperation.m +++ b/Source/NSInvocationOperation.m @@ -121,6 +121,7 @@ - (id) result [_invocation getReturnValue: buffer]; result = [NSValue valueWithBytes: buffer objCType: returnType]; + free(buffer); } } return result; diff --git a/Source/NSOperation.m b/Source/NSOperation.m index 6a871dedaa..fb7584a4be 100644 --- a/Source/NSOperation.m +++ b/Source/NSOperation.m @@ -75,8 +75,6 @@ static void *isReadyCtxt = (void*)"isReady"; static void *queuePriorityCtxt = (void*)"queuePriority"; -static NSArray *empty = nil; - @interface NSOperation (Private) - (void) _finish; - (void) _updateReadyState; @@ -91,12 +89,6 @@ + (BOOL) automaticallyNotifiesObserversForKey: (NSString*)theKey return NO; } -+ (void) initialize -{ - empty = [NSArray new]; - RELEASE([NSObject leakAt: &empty]); -} - - (void) addDependency: (NSOperation *)op { if (NO == [op isKindOfClass: [NSOperation class]]) @@ -228,7 +220,7 @@ - (NSArray *) dependencies if (internal->dependencies == nil) { - a = empty; // OSX return an empty array + a = [NSArray array]; // OSX return an empty array } else { diff --git a/Tests/base/NSArray/basic.m b/Tests/base/NSArray/basic.m index 2c8cba8091..e19a09f1d9 100644 --- a/Tests/base/NSArray/basic.m +++ b/Tests/base/NSArray/basic.m @@ -4,44 +4,46 @@ int main() { - NSArray *obj; - NSMutableArray *testObjs = [[NSMutableArray alloc] init]; - NSString *str; - NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSArray *obj; + NSMutableArray *testObjs = [NSMutableArray array]; + NSString *str; + test_alloc(@"NSArray"); - obj = [NSArray new]; + obj = [NSArray array]; PASS((obj != nil && [obj count] == 0),"can create an empty array"); str = @"hello"; [testObjs addObject: obj]; - obj = [NSArray arrayWithObject:str]; - PASS((obj != nil && [obj count] == 1), "can create an array with one element"); + obj = [NSArray arrayWithObject: str]; + PASS((obj != nil && [obj count] == 1), + "can create an array with one element") [testObjs addObject: obj]; test_NSObject(@"NSArray", testObjs); test_NSCoding(testObjs); test_keyed_NSCoding(testObjs); - test_NSCopying(@"NSArray",@"NSMutableArray",testObjs,YES,NO); - test_NSMutableCopying(@"NSArray",@"NSMutableArray",testObjs); + test_NSCopying(@"NSArray", @"NSMutableArray", testObjs, YES, NO); + test_NSMutableCopying(@"NSArray", @"NSMutableArray", testObjs); obj = [NSArray arrayWithContentsOfFile: @"test.plist"]; - PASS((obj != nil && [obj count] > 0),"can create an array from file"); + PASS((obj != nil && [obj count] > 0),"can create an array from file") #if 1 /* The apple foundation is arguably buggy in that it seems to create a * mutable array ... we currently copy that */ - PASS([obj isKindOfClass: [NSMutableArray class]] == YES,"array mutable"); - PASS_RUNS([(NSMutableArray*)obj addObject: @"x"],"can add to array"); + PASS([obj isKindOfClass: [NSMutableArray class]] == YES, "array mutable") + PASS_RUNS([(NSMutableArray*)obj addObject: @"x"], "can add to array") #else - PASS([obj isKindOfClass: [NSMutableArray class]] == NO,"array immutable"); + PASS([obj isKindOfClass: [NSMutableArray class]] == NO, "array immutable") #endif obj = [obj objectAtIndex: 0]; - PASS([obj isKindOfClass: [NSMutableArray class]] == YES,"array mutable"); + PASS([obj isKindOfClass: [NSMutableArray class]] == YES, "array mutable") START_SET("NSArray subscripting") # ifndef __has_feature # define __has_feature(x) 0 # endif #if __has_feature(objc_subscripting) NSArray *a = @[ @"foo", @"bar" ]; - PASS([@"foo" isEqualToString:a[0]], "Array subscripting works"); + PASS([@"foo" isEqualToString:a[0]], "Array subscripting works") # else SKIP("No collection subscripting support in the compiler.") # endif diff --git a/Tests/base/NSAttributedString/basic.m b/Tests/base/NSAttributedString/basic.m index 2d10f4b81f..b5e15e4a25 100644 --- a/Tests/base/NSAttributedString/basic.m +++ b/Tests/base/NSAttributedString/basic.m @@ -3,8 +3,10 @@ #import "ObjectTesting.h" int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSArray *arr = [NSArray arrayWithObject:[NSAttributedString new]]; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSArray *arr; + + arr = [NSArray arrayWithObject: AUTORELEASE([NSAttributedString new])]; test_alloc(@"NSAttributedString"); test_NSObject(@"NSAttributedString", arr); diff --git a/Tests/base/NSAttributedString/test00.m b/Tests/base/NSAttributedString/test00.m index a0d8b095a9..af65166d24 100644 --- a/Tests/base/NSAttributedString/test00.m +++ b/Tests/base/NSAttributedString/test00.m @@ -5,46 +5,47 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSAttributedString *s; - NSString *key1, *val1, *str1; - NSRange r = NSMakeRange(0,6); - NSAttributedString *astr1, *astr2; - NSDictionary *dict1; - NSRange range = NSMakeRange(0,0); - id obj; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSAttributedString *s; + NSString *key1, *val1, *str1; + NSRange r = NSMakeRange(0,6); + NSAttributedString *astr1, *astr2; + NSDictionary *dict1; + NSRange range = NSMakeRange(0,0); + id obj; - s = [[[NSAttributedString alloc] initWithString: @"string"] autorelease]; - PASS_EQUAL([s string], @"string", "equality OK for string value"); - PASS([s length] == 6, "length reported correctly"); + s = AUTORELEASE([[NSAttributedString alloc] initWithString: @"string"]); + PASS_EQUAL([s string], @"string", "equality OK for string value") + PASS([s length] == 6, "length reported correctly") PASS_EQUAL([s attributesAtIndex: 0 effectiveRange: NULL], - [NSDictionary dictionary], "returnsempty attributes dictionary, not nil"); + [NSDictionary dictionary], "returnsempty attributes dictionary, not nil") key1 = @"Helvetica 12-point"; val1 = @"NSFontAttributeName"; str1 = @"Attributed string test"; - dict1 = [NSDictionary dictionaryWithObject:val1 forKey:key1]; + dict1 = [NSDictionary dictionaryWithObject: val1 forKey: key1]; - astr1 = [[NSAttributedString alloc] initWithString: str1 attributes: dict1]; - PASS(astr1 != nil && [astr1 isKindOfClass: [NSAttributedString class]] && - [[astr1 string] isEqual: str1],"-initWithString:attributes: works"); + astr1 = AUTORELEASE([[NSAttributedString alloc] + initWithString: str1 attributes: dict1]); + PASS(astr1 != nil && [astr1 isKindOfClass: [NSAttributedString class]] + && [[astr1 string] isEqual: str1], "-initWithString:attributes: works") obj = [astr1 attributesAtIndex: 0 effectiveRange: &range]; - PASS(obj != nil && [obj isKindOfClass: [NSDictionary class]] && - [obj count] == 1 && range.length != 0, - "-attributesAtIndex:effectiveRange: works"); + PASS(obj != nil && [obj isKindOfClass: [NSDictionary class]] + && [obj count] == 1 && range.length != 0, + "-attributesAtIndex:effectiveRange: works") obj = [astr1 attribute: key1 atIndex: 0 effectiveRange: &range]; PASS(obj != nil && [obj isEqual: val1] && range.length != 0, - "-attribute:atIndex:effectiveRange: works"); + "-attribute:atIndex:effectiveRange: works") obj = [astr1 attributedSubstringFromRange: r]; - PASS(obj != nil && [obj isKindOfClass: [NSAttributedString class]] && - [obj length] == r.length,"-attributedSubstringFromRange works"); + PASS(obj != nil && [obj isKindOfClass: [NSAttributedString class]] + && [obj length] == r.length, "-attributedSubstringFromRange works") - r = NSMakeRange(0,[astr1 length]); + r = NSMakeRange(0, [astr1 length]); astr2 = [astr1 attributedSubstringFromRange: r]; PASS(astr2 != nil && [astr1 isEqualToAttributedString: astr2], - "extract and compare using -isEqualToAttributedString works"); + "extract and compare using -isEqualToAttributedString works") [arp release]; arp = nil; return 0; diff --git a/Tests/base/NSAutoreleasePool/autorelease_eh.m b/Tests/base/NSAutoreleasePool/autorelease_eh.m index 06dcf655cb..87a9385fa6 100644 --- a/Tests/base/NSAutoreleasePool/autorelease_eh.m +++ b/Tests/base/NSAutoreleasePool/autorelease_eh.m @@ -3,13 +3,12 @@ #import @interface TestClass : NSObject -- (void)runTest; -- (void)exceptionThrowingMethod; - +- (void) runTest; +- (void) exceptionThrowingMethod; @end @implementation TestClass -- (void)runTest +- (void) runTest { int c = 0; int i; @@ -19,21 +18,26 @@ - (void)runTest NSAutoreleasePool *pool = [NSAutoreleasePool new]; NS_DURING - [self exceptionThrowingMethod]; + [self exceptionThrowingMethod]; NS_HANDLER - c++; + c++; NS_ENDHANDLER [pool release]; } - PASS(c == 10, "Caught the correct number of exceptions without breaking the autorelease pool\n"); + PASS(c == 10, "Caught the correct number of exceptions" + " without breaking the autorelease pool") } -- (void)exceptionThrowingMethod +- (void) exceptionThrowingMethod { - NSAutoreleasePool *pool = [NSAutoreleasePool new]; - [@"Hello" stringByAppendingString: @" something to create a autoreleased object"]; + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + + [@"Hello" stringByAppendingString: + @" something to create a autoreleased object"]; NSLog(@"Throwing an exception"); - [[NSException exceptionWithName: @"MyFunException" reason: @"it was always meant to happen" userInfo: [NSDictionary dictionary]] raise]; + [[NSException exceptionWithName: @"MyFunException" + reason: @"it was always meant to happen" + userInfo: [NSDictionary dictionary]] raise]; [pool release]; // Obviously this doesn't get run, but the [NSAutorelease new] at the top causes the problem } @@ -41,8 +45,9 @@ - (void)exceptionThrowingMethod int main(int argc, char** argv) { - NSAutoreleasePool *pool = [NSAutoreleasePool new]; - TestClass *testClass = [[TestClass new] autorelease]; + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + TestClass *testClass = [[TestClass new] autorelease]; + [testClass runTest]; [pool release]; PASS(1, "Destroying pools in the wrong order didn't break anything..."); diff --git a/Tests/base/NSBundle/basic.m b/Tests/base/NSBundle/basic.m index a15dd605cc..f686881e92 100644 --- a/Tests/base/NSBundle/basic.m +++ b/Tests/base/NSBundle/basic.m @@ -7,7 +7,8 @@ int main() NSAutoreleasePool *arp = [NSAutoreleasePool new]; test_alloc(@"NSBundle"); - test_NSObject(@"NSBundle", [NSArray arrayWithObject:[NSBundle new]]); + test_NSObject(@"NSBundle", + [NSArray arrayWithObject: AUTORELEASE([NSBundle new])]); [arp release]; arp = nil; return 0; } diff --git a/Tests/base/NSCalendar/era.m b/Tests/base/NSCalendar/era.m index 3abaacabec..787251cbc2 100644 --- a/Tests/base/NSCalendar/era.m +++ b/Tests/base/NSCalendar/era.m @@ -31,29 +31,38 @@ int main() START_SET("NSCalendar getEra:year:month:day:fromDate and getHour:minute:second:nanosecond:fromDate tests"); /* Test getEra:year:month:day:fromDate: */ - dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setLocale: [[NSLocale alloc] initWithLocaleIdentifier: - [NSLocale canonicalLocaleIdentifierFromString: @"en_US"]]]; + dateFormatter = AUTORELEASE([[NSDateFormatter alloc] init]); + [dateFormatter setLocale: AUTORELEASE([[NSLocale alloc] + initWithLocaleIdentifier: [NSLocale + canonicalLocaleIdentifierFromString: @"en_US"]])]; cal = [NSCalendar currentCalendar]; - [cal setTimeZone:[NSTimeZone timeZoneWithName: @"America/New_York"]]; + [cal setTimeZone: [NSTimeZone timeZoneWithName: @"America/New_York"]]; [dateFormatter setDateFormat: @"d MMM yyyy HH:mm:ss Z"]; - date = [dateFormatter dateFromString:@"22 Nov 1969 08:15:00 Z"]; + date = [dateFormatter dateFromString: @"22 Nov 1969 08:15:00 Z"]; - [cal getEra:&era year:&year month:&month day:&day fromDate:date]; + [cal getEra: &era year: &year month: &month day: &day fromDate: date]; - PASS(era == 1, "getEra:year:month:day:fromDate: returns correct era"); - PASS(year == 1969, "getEra:year:month:day:fromDate: returns correct year"); - PASS(month == 11, "getEra:year:month:day:fromDate: returns correct month"); - PASS(day == 22, "getEra:year:month:day:fromDate: returns correct day"); + PASS(era == 1, "getEra:year:month:day:fromDate: returns correct era") + PASS(year == 1969, "getEra:year:month:day:fromDate: returns correct year") + PASS(month == 11, "getEra:year:month:day:fromDate: returns correct month") + PASS(day == 22, "getEra:year:month:day:fromDate: returns correct day") /* Test getHour:minute:second:nanosecond:fromDate: */ - [cal getHour:&hour minute:&min second:&sec nanosecond:&nano fromDate:date]; + [cal getHour: &hour + minute: &min + second: &sec + nanosecond: &nano + fromDate: date]; - PASS(hour == 3, "getHour:minute:second:nanosecond:fromDate: returns correct hour"); - PASS(min == 15, "getHour:minute:second:nanosecond:fromDate: returns correct minute"); - PASS(sec == 0, "getHour:minute:second:nanosecond:fromDate: returns correct second"); - PASS(nano == 0, "getHour:minute:second:nanosecond:fromDate: returns correct nanosecond"); + PASS(hour == 3, "getHour:minute:second:nanosecond:fromDate:" + " returns correct hour") + PASS(min == 15, "getHour:minute:second:nanosecond:fromDate:" + " returns correct minute") + PASS(sec == 0, "getHour:minute:second:nanosecond:fromDate:" + " returns correct second") + PASS(nano == 0, "getHour:minute:second:nanosecond:fromDate:" + " returns correct nanosecond") END_SET("NSCalendar getEra:year:month:day:fromDate and getHour:minute:second:nanosecond:fromDate tests"); return 0; diff --git a/Tests/base/NSCalendarDate/basic.m b/Tests/base/NSCalendarDate/basic.m index 1ebe646299..280d42f7be 100644 --- a/Tests/base/NSCalendarDate/basic.m +++ b/Tests/base/NSCalendarDate/basic.m @@ -5,8 +5,8 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - id testObj = [NSCalendarDate new]; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + id testObj = AUTORELEASE([NSCalendarDate new]); test_NSObject(@"NSCalendarDate", [NSArray arrayWithObject: testObj]); test_NSCoding([NSArray arrayWithObject: testObj]); diff --git a/Tests/base/NSCalendarDate/test02.m b/Tests/base/NSCalendarDate/test02.m index ac2d2cede2..b9cdd4a5dd 100644 --- a/Tests/base/NSCalendarDate/test02.m +++ b/Tests/base/NSCalendarDate/test02.m @@ -9,15 +9,15 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSMutableArray *tmpArray; - NSMutableDictionary *myLocale; - NSCalendarDate *myBirthday; - NSCalendarDate *anotherDay; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSMutableArray *tmpArray; + NSMutableDictionary *myLocale; + NSCalendarDate *myBirthday; + NSCalendarDate *anotherDay; myLocale = westernLocale(); - tmpArray = [NSMutableArray new]; + tmpArray = [NSMutableArray array]; [tmpArray addObject: @"Gen"]; [tmpArray addObject: @"Feb"]; [tmpArray addObject: @"Mar"]; @@ -32,7 +32,7 @@ int main() [tmpArray addObject: @"Dic"]; [myLocale setObject: tmpArray forKey: NSShortMonthNameArray]; - ASSIGN(tmpArray,[NSMutableArray new]); + tmpArray = [NSMutableArray array]; [tmpArray addObject: @"Gennaio"]; [tmpArray addObject: @"Febbraio"]; [tmpArray addObject: @"Marzo"]; @@ -47,7 +47,7 @@ int main() [tmpArray addObject: @"Dicembre"]; [myLocale setObject: tmpArray forKey: NSMonthNameArray]; - ASSIGN(tmpArray,[NSMutableArray new]); + tmpArray = [NSMutableArray array]; [tmpArray addObject: @"Dom"]; [tmpArray addObject: @"Lun"]; [tmpArray addObject: @"Mar"]; @@ -57,7 +57,7 @@ int main() [tmpArray addObject: @"Sab"]; [myLocale setObject: tmpArray forKey: NSShortWeekDayNameArray]; - ASSIGN(tmpArray,[NSMutableArray new]); + tmpArray = [NSMutableArray array]; [tmpArray addObject: @"Domencia"]; [tmpArray addObject: @"Lunedi"]; [tmpArray addObject: @"Martedi"]; @@ -67,7 +67,7 @@ int main() [tmpArray addObject: @"Sabato"]; [myLocale setObject: tmpArray forKey: NSWeekDayNameArray]; - ASSIGN(tmpArray,[NSMutableArray new]); + tmpArray = [NSMutableArray array]; [tmpArray addObject: @"AM"]; [tmpArray addObject: @"PM"]; [myLocale setObject: tmpArray forKey: NSAMPMDesignation]; diff --git a/Tests/base/NSData/base64.m b/Tests/base/NSData/base64.m index f39813fa99..144b45efac 100644 --- a/Tests/base/NSData/base64.m +++ b/Tests/base/NSData/base64.m @@ -81,6 +81,7 @@ int main() strEnc = [data base64EncodedStringWithOptions:0]; data = [[NSData alloc] initWithBase64EncodedString: strEnc options: 0]; str2 = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding]; + [data release]; PASS_EQUAL(str1, str2, "Encode / Decode no lines") [str2 release]; @@ -90,6 +91,7 @@ int main() data = [[NSData alloc] initWithBase64EncodedString: strEnc options: NSDataBase64DecodingIgnoreUnknownCharacters]; str2 = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding]; + [data release]; PASS_EQUAL(str1, str2, "Encode / Decode 64 - LF") [str2 release]; @@ -99,6 +101,7 @@ int main() data = [[NSData alloc] initWithBase64EncodedString: strEnc options: NSDataBase64DecodingIgnoreUnknownCharacters]; str2 = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding]; + [data release]; PASS_EQUAL(str1, str2, "Encode / Decode 76 - LF") [str2 release]; @@ -108,6 +111,7 @@ int main() data = [[NSData alloc] initWithBase64EncodedString: strEnc options: NSDataBase64DecodingIgnoreUnknownCharacters]; str2 = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding]; + [data release]; PASS_EQUAL(str1, str2, "Encode / Decode 64 - CR") [str2 release]; @@ -117,6 +121,7 @@ int main() data = [[NSData alloc] initWithBase64EncodedString: strEnc options: NSDataBase64DecodingIgnoreUnknownCharacters]; str2 = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding]; + [data release]; PASS_EQUAL(str1, str2, "Encode / Decode 64 - implicit CR LF") [str2 release]; diff --git a/Tests/base/NSData/basic.m b/Tests/base/NSData/basic.m index db1b302ed8..e67411f2f6 100644 --- a/Tests/base/NSData/basic.m +++ b/Tests/base/NSData/basic.m @@ -4,18 +4,19 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - id testObject = [NSData new]; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + id testObject = AUTORELEASE([NSData new]); + test_alloc(@"NSData"); - test_NSObject(@"NSData",[NSArray arrayWithObject:testObject]); - test_NSCoding([NSArray arrayWithObject:testObject]); - test_keyed_NSCoding([NSArray arrayWithObject:testObject]); + test_NSObject(@"NSData", [NSArray arrayWithObject: testObject]); + test_NSCoding([NSArray arrayWithObject: testObject]); + test_keyed_NSCoding([NSArray arrayWithObject: testObject]); test_NSCopying(@"NSData", @"NSMutableData", - [NSArray arrayWithObject:testObject], NO, NO); + [NSArray arrayWithObject: testObject], NO, NO); test_NSMutableCopying(@"NSData", @"NSMutableData", - [NSArray arrayWithObject:testObject]); + [NSArray arrayWithObject: testObject]); [arp release]; arp = nil; return 0; diff --git a/Tests/base/NSData/general.m b/Tests/base/NSData/general.m index 54b24963a0..7d136aec77 100644 --- a/Tests/base/NSData/general.m +++ b/Tests/base/NSData/general.m @@ -6,67 +6,69 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - char *str1,*str2; - NSData *data1, *data2; - NSMutableData *mutable; - char *hold; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + char *str1, *str2; + NSData *data1, *data2; + NSMutableData *mutable; + char *hold; str1 = "Test string for data classes"; str2 = (char *) malloc(sizeof("Test string for data classes not copied")); strcpy(str2,"Test string for data classes not copied"); - mutable = [NSMutableData dataWithLength:100]; + mutable = [NSMutableData dataWithLength: 100]; hold = [mutable mutableBytes]; - /* hmpf is this correct */ - data1 = [NSData dataWithBytes:str1 length:(strlen(str1) * sizeof(void*))]; - PASS(data1 != nil && - [data1 isKindOfClass:[NSData class]] && - [data1 length] == (strlen(str1) * sizeof(void*)) && - [data1 bytes] != str1 && - strcmp(str1,[data1 bytes]) == 0, - "+dataWithBytes:length: works"); - - data2 = [NSData dataWithBytesNoCopy:str2 length:(strlen(str2) * sizeof(void*))]; - PASS(data2 != nil && [data2 isKindOfClass:[NSData class]] && - [data2 length] == (strlen(str2) * sizeof(void*)) && - [data2 bytes] == str2, - "+dataWithBytesNoCopy:length: works"); - - data1 = [NSData dataWithBytes:nil length:0]; - PASS(data1 != nil && [data1 isKindOfClass:[NSData class]] && - [data1 length] == 0, - "+dataWithBytes:length works with 0 length"); - - [data2 getBytes:hold range:NSMakeRange(2,6)]; - PASS(strcmp(hold,"st str") == 0, "-getBytes:range works"); - - PASS_EXCEPTION([data2 getBytes:hold - range:NSMakeRange(strlen(str2)*sizeof(void*),1)];, - NSRangeException, - "getBytes:range: with bad location"); - - PASS_EXCEPTION([data2 getBytes:hold - range:NSMakeRange(1,(strlen(str2)*sizeof(void*)))];, - NSRangeException, - "getBytes:range: with bad length"); - - PASS_EXCEPTION([data2 subdataWithRange:NSMakeRange((strlen(str2)*sizeof(void*)),1)];, - NSRangeException, - "-subdataWithRange: with bad location"); - - PASS_EXCEPTION([data2 subdataWithRange:NSMakeRange(1,(strlen(str2)*sizeof(void*)))];, - NSRangeException, - "-subdataWithRange: with bad length"); - - data2 = [NSData dataWithBytesNoCopy:str1 - length:(strlen(str1) * sizeof(void*)) - freeWhenDone:NO]; - PASS(data2 != nil && [data2 isKindOfClass:[NSData class]] && - [data2 length] == (strlen(str1) * sizeof(void*)) && - [data2 bytes] == str1, - "+dataWithBytesNoCopy:length:freeWhenDone: works"); + data1 = [NSData dataWithBytes: str1 length: strlen(str1) + 1]; + PASS(data1 != nil + && [data1 isKindOfClass: [NSData class]] + && [data1 length] == strlen(str1) + 1 + && [data1 bytes] != str1 + && strcmp(str1, [data1 bytes]) == 0, + "+dataWithBytes:length: works") + + data2 = [NSData dataWithBytesNoCopy: str2 + length: strlen(str2) + 1]; + PASS(data2 != nil && [data2 isKindOfClass: [NSData class]] + && [data2 length] == strlen(str2) + 1 + && [data2 bytes] == str2, + "+dataWithBytesNoCopy:length: works") + + data1 = [NSData dataWithBytes: nil length: 0]; + PASS(data1 != nil && [data1 isKindOfClass: [NSData class]] + && [data1 length] == 0, + "+dataWithBytes:length works with 0 length") + + [data2 getBytes: hold range: NSMakeRange(2,6)]; + PASS(strcmp(hold, "st str") == 0, "-getBytes:range works") + + PASS_EXCEPTION([data2 getBytes: hold + range: NSMakeRange(strlen(str2) + 1, 1)];, + NSRangeException, + "getBytes:range: with bad location") + + PASS_EXCEPTION([data2 getBytes: hold + range: NSMakeRange(1, strlen(str2) + 1)];, + NSRangeException, + "getBytes:range: with bad length") + + PASS_EXCEPTION([data2 subdataWithRange: + NSMakeRange(strlen(str2) + 1, 1)];, + NSRangeException, + "-subdataWithRange: with bad location") + + PASS_EXCEPTION([data2 subdataWithRange: + NSMakeRange(1, strlen(str2) + 1)];, + NSRangeException, + "-subdataWithRange: with bad length") + + data2 = [NSData dataWithBytesNoCopy: str1 + length: strlen(str1) + 1 + freeWhenDone: NO]; + PASS(data2 != nil && [data2 isKindOfClass: [NSData class]] + && [data2 length] == (strlen(str1) + 1) + && [data2 bytes] == str1, + "+dataWithBytesNoCopy:length:freeWhenDone: works") [arp release]; arp = nil; diff --git a/Tests/base/NSDictionary/basic.m b/Tests/base/NSDictionary/basic.m index 7d7ae415a0..7205cba2c0 100644 --- a/Tests/base/NSDictionary/basic.m +++ b/Tests/base/NSDictionary/basic.m @@ -7,22 +7,24 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSMutableArray *testObjs = [NSMutableArray new]; - NSDictionary *obj; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSMutableArray *testObjs = [NSMutableArray array]; + NSDictionary *obj; + test_alloc(@"NSDictionary"); - obj = [NSDictionary new]; - [testObjs addObject:obj]; - PASS(obj != nil && - [obj isKindOfClass:[NSDictionary class]] && - [obj count] == 0, - "can create an empty dictionary"); - obj = [NSDictionary dictionaryWithObject:@"Hello" forKey:@"Key"]; - [testObjs addObject:obj]; - PASS(obj != nil && - [obj isKindOfClass:[NSDictionary class]] && - [obj count] == 1, - "can create a dictionary with one element"); + obj = [NSDictionary dictionary]; + [testObjs addObject: obj]; + PASS(obj != nil + && [obj isKindOfClass: [NSDictionary class]] + && [obj count] == 0, + "can create an empty dictionary") + + obj = [NSDictionary dictionaryWithObject: @"Hello" forKey: @"Key"]; + [testObjs addObject: obj]; + PASS(obj != nil + && [obj isKindOfClass: [NSDictionary class]] + && [obj count] == 1, + "can create a dictionary with one element") test_NSObject(@"NSDictionary", testObjs); test_NSCoding(testObjs); @@ -36,7 +38,7 @@ int main() #if __has_feature(objc_subscripting) NSDictionary *dictionary = @{@123 : @123.4 , @"date" : @"today" }; - PASS([dictionary[@123] isEqual: @123.4], "Dictionary subscripting works"); + PASS([dictionary[@123] isEqual: @123.4], "Dictionary subscripting works") # else SKIP("No dictionary subscripting support in the compiler.") # endif diff --git a/Tests/base/NSDictionary/create.m b/Tests/base/NSDictionary/create.m index c9bee6aa51..a3b6bd83e4 100644 --- a/Tests/base/NSDictionary/create.m +++ b/Tests/base/NSDictionary/create.m @@ -4,75 +4,77 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSString *key1, *key2, *key3, *val1, *val2, *val3; - NSArray *keys1, *keys2, *keys3, *vals1, *vals2, *vals3; - NSDictionary *obj,*old; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSString *key1, *key2, *key3, *val1, *val2, *val3; + NSArray *keys1, *keys2, *keys3, *vals1, *vals2, *vals3; + NSDictionary *obj,*old; + old = nil; key1 = @"Key1"; key2 = @"Key2"; key3 = @"Key3"; - keys1 = [NSArray arrayWithObjects:key1, key2, nil]; - keys2 = [NSArray arrayWithObjects:key1, key2, key3, nil]; + keys1 = [NSArray arrayWithObjects: key1, key2, nil]; + keys2 = [NSArray arrayWithObjects: key1, key2, key3, nil]; /* duplicate keys */ - keys3 = [NSArray arrayWithObjects:key1, key2, key2, nil]; + keys3 = [NSArray arrayWithObjects: key1, key2, key2, nil]; val1 = @"Kidnapped"; val2 = @"tied up"; val3 = @"taken away and helf for ransom"; - vals1 = [NSArray arrayWithObjects:val1, val2, nil]; + vals1 = [NSArray arrayWithObjects: val1, val2, nil]; /* duplicate values */ - vals2 = [NSArray arrayWithObjects:val1, val2, val2, nil]; - vals3 = [NSArray arrayWithObjects:val1, val2, val3, nil]; - obj = [NSDictionary new]; - PASS(obj != nil && - [obj isKindOfClass:[NSDictionary class]] && - [obj count] == 0, - "+new creates an empty dictionary"); + vals2 = [NSArray arrayWithObjects: val1, val2, val2, nil]; + vals3 = [NSArray arrayWithObjects: val1, val2, val3, nil]; + obj = [NSDictionary dictionary]; + PASS(obj != nil + && [obj isKindOfClass: [NSDictionary class]] + && [obj count] == 0, + "+new creates an empty dictionary") obj = [NSDictionary dictionary]; - PASS(obj != nil && - [obj isKindOfClass:[NSDictionary class]] && - [obj count] == 0, - "+dictionary creates an empty dictionary"); + PASS(obj != nil + && [obj isKindOfClass: [NSDictionary class]] + && [obj count] == 0, + "+dictionary creates an empty dictionary") - PASS_EXCEPTION([NSDictionary dictionaryWithObject:val1 forKey:nil];, - NSInvalidArgumentException, - "+dictionaryWithObject:forKey: with nil key"); + PASS_EXCEPTION([NSDictionary dictionaryWithObject: val1 forKey: nil];, + NSInvalidArgumentException, + "+dictionaryWithObject:forKey: with nil key") - PASS_EXCEPTION([NSDictionary dictionaryWithObject:nil forKey:key1];, - NSInvalidArgumentException, - "+dictionaryWithObject:forKey: with nil value"); + PASS_EXCEPTION([NSDictionary dictionaryWithObject: nil forKey: key1];, + NSInvalidArgumentException, + "+dictionaryWithObject:forKey: with nil value") - obj = [NSDictionary dictionaryWithObject:val1 forKey:key1]; - PASS(obj != nil && - [obj isKindOfClass:[NSDictionary class]] && - [obj count] == 1, - "+dictionaryWithObject:forKey: builds minimal dictionary"); - - obj = [NSDictionary dictionaryWithObjects:vals1 forKeys:keys1]; - PASS(obj != nil && - [obj isKindOfClass:[NSDictionary class]] && - [obj count] == 2, - "+dictionaryWithObjects:forKeys: builds a dictionary"); - - PASS_EXCEPTION([NSDictionary dictionaryWithObjects:vals1 forKeys:keys2];, - NSInvalidArgumentException, - "+dictionaryWithObjects:forKeys: with arrays of different sizes"); - obj = [NSDictionary dictionaryWithObjects:vals2 forKeys:keys2]; - PASS(obj != nil && - [obj isKindOfClass:[NSDictionary class]] && - [obj count] == 3, - "we can have multiple identical objects in a dictionary"); + obj = [NSDictionary dictionaryWithObject: val1 forKey: key1]; + PASS(obj != nil + && [obj isKindOfClass: [NSDictionary class]] + && [obj count] == 1, + "+dictionaryWithObject:forKey: builds minimal dictionary") + + obj = [NSDictionary dictionaryWithObjects: vals1 forKeys: keys1]; + PASS(obj != nil + && [obj isKindOfClass: [NSDictionary class]] + && [obj count] == 2, + "+dictionaryWithObjects:forKeys: builds a dictionary") + + PASS_EXCEPTION([NSDictionary dictionaryWithObjects: vals1 forKeys: keys2];, + NSInvalidArgumentException, + "+dictionaryWithObjects:forKeys: with arrays of different sizes") + + obj = [NSDictionary dictionaryWithObjects: vals2 forKeys: keys2]; + PASS(obj != nil + && [obj isKindOfClass: [NSDictionary class]] + && [obj count] == 3, + "we can have multiple identical objects in a dictionary") - obj = [NSDictionary dictionaryWithObjects:vals3 forKeys:keys3]; - PASS(obj != nil && - [obj isKindOfClass:[NSDictionary class]] && - [obj count] == 2, - "we can't have multiple identical keys in a dictionary"); + obj = [NSDictionary dictionaryWithObjects: vals3 forKeys: keys3]; + PASS(obj != nil + && [obj isKindOfClass: [NSDictionary class]] + && [obj count] == 2, + "we can't have multiple identical keys in a dictionary") old = obj; - obj = [NSDictionary dictionaryWithDictionary:old]; - PASS(obj != nil && - [obj isEqual: old], "+dictionaryWithDictionary: copies dictionary"); + obj = [NSDictionary dictionaryWithDictionary: old]; + PASS(obj != nil + && [obj isEqual: old], "+dictionaryWithDictionary: copies dictionary") [arp release]; arp = nil; return 0; diff --git a/Tests/base/NSDistributedLock/basic.m b/Tests/base/NSDistributedLock/basic.m index 387fd07e8e..19735f0477 100644 --- a/Tests/base/NSDistributedLock/basic.m +++ b/Tests/base/NSDistributedLock/basic.m @@ -11,7 +11,7 @@ int main() NSDistributedLock *lock2; test_NSObject(@"NSDistributedLock", - [NSArray arrayWithObject: [NSDistributedLock new]]); + [NSArray arrayWithObject: AUTORELEASE([NSDistributedLock new])]); path = [[NSFileManager defaultManager] currentDirectoryPath]; path = [path stringByAppendingPathComponent: @"MyLock"]; diff --git a/Tests/base/NSFastEnumeration/basic.m b/Tests/base/NSFastEnumeration/basic.m index 13607769c4..9fd52d4f04 100644 --- a/Tests/base/NSFastEnumeration/basic.m +++ b/Tests/base/NSFastEnumeration/basic.m @@ -11,10 +11,10 @@ void fast_enumeration_mutation_add(id mutableCollection) NSUInteger i = 0; FOR_IN(id, o, mutableCollection) if (i == [mutableCollection count]/2) { - if ([mutableCollection isKindOfClass:[NSMutableDictionary class]]) { - [mutableCollection setObject:@"boom" forKey:@"boom"]; + if ([mutableCollection isKindOfClass: [NSMutableDictionary class]]) { + [mutableCollection setObject: @"boom" forKey: @"boom"]; } else { - [mutableCollection addObject:@"boom"]; + [mutableCollection addObject: @"boom"]; } } i++; @@ -26,10 +26,10 @@ void fast_enumeration_mutation_remove(id mutableCollection) NSUInteger i = 0; FOR_IN(id, o, mutableCollection) if (i == [mutableCollection count]/2) { - if ([mutableCollection isKindOfClass:[NSMutableDictionary class]]) { - [mutableCollection removeObjectForKey:o]; + if ([mutableCollection isKindOfClass: [NSMutableDictionary class]]) { + [mutableCollection removeObjectForKey: o]; } else { - [mutableCollection removeObject:o]; + [mutableCollection removeObject: o]; } } i++; @@ -38,25 +38,27 @@ void fast_enumeration_mutation_remove(id mutableCollection) void test_fast_enumeration(id collection, NSArray *objects) { - NSMutableArray *returnedObjects = [[NSMutableArray alloc] init]; + NSMutableArray *returnedObjects = [NSMutableArray array]; + FOR_IN(id, o, collection) - [returnedObjects addObject:o]; + [returnedObjects addObject: o]; END_FOR_IN(collection) - if (!([collection isKindOfClass:[NSArray class]] || - [collection isKindOfClass:[NSOrderedSet class]])) { - [returnedObjects sortUsingSelector:@selector(compare:)]; - } - PASS_EQUAL(returnedObjects, objects, "fast enumeration returns all objects"); - + if (!([collection isKindOfClass: [NSArray class]] + || [collection isKindOfClass: [NSOrderedSet class]])) + { + [returnedObjects sortUsingSelector: @selector(compare:)]; + } + PASS_EQUAL(returnedObjects, objects, "fast enumeration returns all objects") + id mutableCollection = [collection mutableCopy]; PASS_EXCEPTION( fast_enumeration_mutation_add(mutableCollection), NSGenericException, - "Fast enumeration mutation add properly calls @\"NSGenericException\""); + "Fast enumeration mutation add properly calls @\"NSGenericException\"") PASS_EXCEPTION( fast_enumeration_mutation_remove(mutableCollection), NSGenericException, - "Fast enumeration mutation remove properly calls @\"NSGenericException\""); + "Fast enumeration mutation remove properly calls @\"NSGenericException\"") [mutableCollection release]; } @@ -67,26 +69,26 @@ int main() NSMutableArray *objects = [NSMutableArray array]; int i; for (i = 0; i < 10000; i++) { - [objects addObject:[NSString stringWithFormat:@"%.4d", i]]; + [objects addObject: [NSString stringWithFormat: @"%.4d", i]]; } START_SET("NSArray") - id array = [NSArray arrayWithArray:objects]; + id array = [NSArray arrayWithArray: objects]; test_fast_enumeration(array, objects); END_SET("NSArray") START_SET("NSSet") - id set = [NSSet setWithArray:objects]; + id set = [NSSet setWithArray: objects]; test_fast_enumeration(set, objects); END_SET("NSSet") START_SET("NSOrderedSet") - id orderedSet = [NSOrderedSet orderedSetWithArray:objects]; + id orderedSet = [NSOrderedSet orderedSetWithArray: objects]; test_fast_enumeration(orderedSet, objects); END_SET("NSOrderedSet") START_SET("NSDictionary") - id dict = [NSDictionary dictionaryWithObjects:objects forKeys:objects]; + id dict = [NSDictionary dictionaryWithObjects: objects forKeys: objects]; test_fast_enumeration(dict, objects); END_SET("NSDictionary") diff --git a/Tests/base/NSFileHandle/general.m b/Tests/base/NSFileHandle/general.m index f3beb325d3..9240432356 100644 --- a/Tests/base/NSFileHandle/general.m +++ b/Tests/base/NSFileHandle/general.m @@ -36,43 +36,43 @@ int main() NSFileHandle *stdInFH = [NSFileHandle fileHandleWithStandardInput]; NSFileHandle *stdNullFH = [NSFileHandle fileHandleWithNullDevice]; NSFileHandle *t1FH, *t2FH; - NSString *tPath = [NSString stringWithFormat:@"%@/%@",NSTemporaryDirectory(),[[NSProcessInfo processInfo]globallyUniqueString]]; - NSData *t1Data = [tPath dataUsingEncoding:NSUTF8StringEncoding]; + NSString *tPath = [NSString stringWithFormat: @"%@/%@",NSTemporaryDirectory(),[[NSProcessInfo processInfo]globallyUniqueString]]; + NSData *t1Data = [tPath dataUsingEncoding: NSUTF8StringEncoding]; NSData *t2Data; - PASS([stdInFH isKindOfClass:[NSFileHandle class]], - "NSFileHandle understands +fileHandleWithStandardInput"); + PASS([stdInFH isKindOfClass: [NSFileHandle class]], + "NSFileHandle understands +fileHandleWithStandardInput") PASS([stdInFH fileDescriptor]==0, - "NSFileHandle +fileHandleWithStandardInput has 0 as fileDescriptor"); + "NSFileHandle +fileHandleWithStandardInput has 0 as fileDescriptor") - PASS([stdOutFH isKindOfClass:[NSFileHandle class]], - "NSFileHandle understands +fileHandleWithStandardOutput"); + PASS([stdOutFH isKindOfClass: [NSFileHandle class]], + "NSFileHandle understands +fileHandleWithStandardOutput") PASS([stdOutFH fileDescriptor]==1, - "NSFileHandle +fileHandleWithStandardOutput has 1 as fileDescriptor"); + "NSFileHandle +fileHandleWithStandardOutput has 1 as fileDescriptor") - PASS([stdErrFH isKindOfClass:[NSFileHandle class]], - "NSFileHandle understands +fileHandleWithStandardError"); + PASS([stdErrFH isKindOfClass: [NSFileHandle class]], + "NSFileHandle understands +fileHandleWithStandardError") PASS([stdErrFH fileDescriptor]==2, "NSFileHandle +fileHandleWithStandardError has 2 as fileDescriptor"); - PASS([stdNullFH isKindOfClass:[NSFileHandle class]], - "NSFileHandle understands +fileHandleWithNullDevice"); + PASS([stdNullFH isKindOfClass: [NSFileHandle class]], + "NSFileHandle understands +fileHandleWithNullDevice") - t1FH = [[NSFileHandle alloc] initWithFileDescriptor: 0]; - PASS([t1FH isKindOfClass:[NSFileHandle class]], - "NSFileHandle understands -initWithFileDescriptor:"); + t1FH = AUTORELEASE([[NSFileHandle alloc] initWithFileDescriptor: 0]); + PASS([t1FH isKindOfClass: [NSFileHandle class]], + "NSFileHandle understands -initWithFileDescriptor:") t1FH = [NSFileHandle fileHandleForWritingAtPath: tPath]; - PASS(t1FH == nil, - "NSFileHandle +fileHandleForWritingAtPath: with non-existing file return nil"); + PASS(t1FH == nil, "NSFileHandle +fileHandleForWritingAtPath:" + " with non-existing file return nil") [@"" writeToFile: tPath atomically: YES]; t1FH = [NSFileHandle fileHandleForWritingAtPath: tPath]; - PASS([t1FH isKindOfClass:[NSFileHandle class]], + PASS([t1FH isKindOfClass: [NSFileHandle class]], "NSFileHandle understands +fileHandleForWritingAtPath:"); t2FH = [NSFileHandle fileHandleForReadingAtPath: tPath]; - PASS([t2FH isKindOfClass:[NSFileHandle class]], + PASS([t2FH isKindOfClass: [NSFileHandle class]], "NSFileHandle understands +fileHandleForReadingAtPath:"); [t1FH writeData: t1Data]; diff --git a/Tests/base/NSFileManager/general.m b/Tests/base/NSFileManager/general.m index fb2ca6ee43..e47a21fdb1 100644 --- a/Tests/base/NSFileManager/general.m +++ b/Tests/base/NSFileManager/general.m @@ -56,7 +56,7 @@ int main() NSAutoreleasePool *arp = [NSAutoreleasePool new]; NSFileManager *mgr = [NSFileManager defaultManager]; NSString *dir = @"NSFileManagerTestDir"; - MyHandler *handler = [MyHandler new]; + MyHandler *handler = AUTORELEASE([MyHandler new]); NSDictionary *attr; NSString *dirInDir; NSString *str1; diff --git a/Tests/base/NSInvocationOperation/basic.m b/Tests/base/NSInvocationOperation/basic.m index 678d282b92..d6ac9332b2 100644 --- a/Tests/base/NSInvocationOperation/basic.m +++ b/Tests/base/NSInvocationOperation/basic.m @@ -16,7 +16,7 @@ int main() NSInteger length; NSString *hello = @"hello"; NSString *uppercaseHello; - NSOperationQueue *queue = [NSOperationQueue new]; + NSOperationQueue *queue = AUTORELEASE([NSOperationQueue new]); op = [[NSInvocationOperation alloc] initWithTarget: hello selector: @selector(length) From 088b76bed153177354fe18ffe987447676977ba5 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 21:21:41 +0000 Subject: [PATCH 22/64] Fix leaks --- Source/NSString.m | 1 + Tests/base/NSString/NSString_custom.m | 8 +- Tests/base/NSString/NSString_tests.h | 6 +- Tests/base/NSString/NSString_zero_hash.m | 2 +- .../NSString/enumerateSubstringsInRange.m | 102 +++++++++--------- Tests/base/NSString/nuls_in_strings.m | 2 +- Tests/base/NSString/test05.m | 6 +- Tests/base/NSString/test08.m | 6 +- Tests/base/NSString/utf8.m | 2 +- Tests/base/Unicode/test00.m | 1 + 10 files changed, 71 insertions(+), 65 deletions(-) diff --git a/Source/NSString.m b/Source/NSString.m index 1f37e2edef..904df8064f 100644 --- a/Source/NSString.m +++ b/Source/NSString.m @@ -6592,6 +6592,7 @@ - (void) enumerateSubstringsInRange: (NSRange)range &stop); } } + ubrk_close(breakIterator); #else NSWarnLog(@"NSStringEnumerationByWords and NSStringEnumerationBySentences" @" are not supported when GNUstep-base is compiled without ICU."); diff --git a/Tests/base/NSString/NSString_custom.m b/Tests/base/NSString/NSString_custom.m index 2c46dbbc02..b7a957ccb6 100644 --- a/Tests/base/NSString/NSString_custom.m +++ b/Tests/base/NSString/NSString_custom.m @@ -23,6 +23,8 @@ @implementation CustomString length: (NSUInteger)l encoding: (NSStringEncoding)encoding { + if (characters) free(characters); + characters = NULL; if (l > 0) { if (encoding == NSUnicodeStringEncoding) @@ -37,7 +39,7 @@ @implementation CustomString s = [[NSString alloc] initWithBytes: c length: l encoding: encoding]; - if (s == nil) return nil; + if (s == nil) {RELEASE(self); return nil;} l = [s length] * sizeof(unichar); characters = malloc(l); [s getCharacters: characters]; @@ -53,6 +55,8 @@ @implementation CustomString encoding: (NSStringEncoding)encoding freeWhenDone: (BOOL)freeWhenDone { + if (characters) free(characters); + characters = NULL; if (l > 0) { if (encoding == NSUnicodeStringEncoding) @@ -68,7 +72,7 @@ @implementation CustomString length: l encoding: encoding freeWhenDone: freeWhenDone]; - if (s == nil) return nil; + if (s == nil) {RELEASE(self); return nil;} l = [s length] * sizeof(unichar); characters = malloc(l); [s getCharacters: characters]; diff --git a/Tests/base/NSString/NSString_tests.h b/Tests/base/NSString/NSString_tests.h index bb7a6f3510..f99fc99202 100644 --- a/Tests/base/NSString/NSString_tests.h +++ b/Tests/base/NSString/NSString_tests.h @@ -39,7 +39,7 @@ Basic sanity test. */ BOOL test_initWithCString(void) { - NSString *test1 = [[stringClass alloc] initWithCString: "ascii"]; + NSString *test1 = AUTORELEASE([[stringClass alloc] initWithCString: "ascii"]); NSString *sanity = @"ascii"; if (!test1) @@ -117,9 +117,9 @@ test_encoding(void) NSData *d = [[NSData alloc] initWithBytes: "foo" length: 3]; NSString *s = [[stringClass alloc] initWithData: d encoding: 0]; - PASS(s == nil, "-initWithData:encoding: gives nil for invalid encodings") - DESTROY(d); + PASS(s == nil, "-initWithData:encoding: gives nil for invalid encodings") + DESTROY(s); } test_encodings_helper(NSASCIIStringEncoding, diff --git a/Tests/base/NSString/NSString_zero_hash.m b/Tests/base/NSString/NSString_zero_hash.m index cc40e2d484..2309e54e62 100644 --- a/Tests/base/NSString/NSString_zero_hash.m +++ b/Tests/base/NSString/NSString_zero_hash.m @@ -31,7 +31,7 @@ Generate a (hopefully ASCII printable) string with a given hash. h = [s hash]; PASS(h != 0, "[NSConstantString hash] does not return 0"); - s = [[NSString alloc] initWithString: s]; + s = [NSString stringWithString: s]; h = [s hash]; PASS(h != 0, "[NSString hash] does not return 0"); diff --git a/Tests/base/NSString/enumerateSubstringsInRange.m b/Tests/base/NSString/enumerateSubstringsInRange.m index 3a7e49dca9..af9756b448 100644 --- a/Tests/base/NSString/enumerateSubstringsInRange.m +++ b/Tests/base/NSString/enumerateSubstringsInRange.m @@ -17,25 +17,25 @@ BOOL correctCallCount; __block NSUInteger callCount = 0; - mutableString = [NSMutableString stringWithString:@"Hello World"]; + mutableString = [NSMutableString stringWithString: @"Hello World"]; results = [NSMutableArray array]; range = NSMakeRange(0, mutableString.length); expectedResults = @[ @"Hello", @"World" ]; [mutableString - enumerateSubstringsInRange:range - options:NSStringEnumerationByWords - usingBlock:^(NSString *substring, NSRange substringRange, + enumerateSubstringsInRange: range + options: NSStringEnumerationByWords + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { - [results addObject:substring]; + [results addObject: substring]; callCount++; - if ([substring isEqualToString:@"Hello"]) + if ([substring isEqualToString: @"Hello"]) { // Simulate a mutation that affects subsequent // enumeration "Hello " is changed to "Hello" [mutableString - deleteCharactersInRange:NSMakeRange( + deleteCharactersInRange: NSMakeRange( substringRange.location + substringRange.length, 1)]; @@ -44,14 +44,14 @@ }]; [mutableString - enumerateSubstringsInRange:NSMakeRange(5, mutableString.length - 5) - options:NSStringEnumerationByWords - usingBlock:^(NSString *substring, NSRange substringRange, + enumerateSubstringsInRange: NSMakeRange(5, mutableString.length - 5) + options: NSStringEnumerationByWords + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { - [results addObject:substring]; + [results addObject: substring]; }]; - correctResults = [results isEqualToArray:expectedResults]; + correctResults = [results isEqualToArray: expectedResults]; correctCallCount = (callCount == 1); // Ensure only one call before stopping PASS(correctResults && correctCallCount, @@ -74,11 +74,11 @@ expected = @[ @"Hello", @"World" ]; [string - enumerateSubstringsInRange:range - options:NSStringEnumerationByWords - usingBlock:^(NSString *substring, NSRange substringRange, + enumerateSubstringsInRange: range + options: NSStringEnumerationByWords + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { - [results addObject:substring]; + [results addObject: substring]; }]; PASS_EQUAL(results, expected, "Should correctly enumerate words."); @@ -96,11 +96,11 @@ range = NSMakeRange(0, 0); [string - enumerateSubstringsInRange:range - options:NSStringEnumerationByWords - usingBlock:^(NSString *substring, NSRange substringRange, + enumerateSubstringsInRange: range + options: NSStringEnumerationByWords + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { - [results addObject:substring]; + [results addObject: substring]; }]; PASS(results.count == 0, @@ -119,11 +119,11 @@ void testLocationOffset() { expected = @[ @"World", @"Continued"]; [string - enumerateSubstringsInRange:range - options:NSStringEnumerationByWords - usingBlock:^(NSString *substring, NSRange substringRange, + enumerateSubstringsInRange: range + options: NSStringEnumerationByWords + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { - [results addObject:substring]; + [results addObject: substring]; }]; PASS_EQUAL(results, expected, "Should correctly enumerate words with location offset."); @@ -143,19 +143,19 @@ void testLocationOffset() { __block BOOL didStop = NO; [string - enumerateSubstringsInRange:range - options:NSStringEnumerationByWords - usingBlock:^(NSString *substring, NSRange substringRange, + enumerateSubstringsInRange: range + options: NSStringEnumerationByWords + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { - if ([substring isEqualToString:@"Hello"]) + if ([substring isEqualToString: @"Hello"]) { *stop = YES; didStop = YES; } - [results addObject:substring]; + [results addObject: substring]; }]; - PASS(didStop && [results count] == 1 && [results[0] isEqualToString:@"Hello"], + PASS(didStop && [results count] == 1 && [results[0] isEqualToString: @"Hello"], "Enumeration should stop after 'Hello'."); } @@ -168,17 +168,17 @@ void testLocationOffset() { NSString *s1 = @"Line 1\nLine 2"; __block NSUInteger currentIteration = 0; [s1 - enumerateSubstringsInRange:(NSRange){.location = 0, .length = [s1 length]} - options:NSStringEnumerationByLines - usingBlock:^(NSString *substring, NSRange substringRange, + enumerateSubstringsInRange: (NSRange){.location = 0, .length = [s1 length]} + options: NSStringEnumerationByLines + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { // *stop = YES; if (currentIteration == 0) - PASS([substring isEqual:@"Line 1"], + PASS([substring isEqual: @"Line 1"], "First line of \"Line 1\\nLine 2\" is \"Line 1\""); if (currentIteration == 1) PASS( - [substring isEqual:@"Line 2"], + [substring isEqual: @"Line 2"], "Second line of \"Line 1\\nLine 2\" is \"Line 2\""); currentIteration++; }]; @@ -190,17 +190,17 @@ void testLocationOffset() { NSString *s1 = @"Paragraph 1\nParagraph 2"; __block NSUInteger currentIteration = 0; - [s1 enumerateSubstringsInRange:(NSRange){.location = 0, .length = [s1 length]} - options:NSStringEnumerationByParagraphs - usingBlock:^(NSString *substring, NSRange substringRange, + [s1 enumerateSubstringsInRange: (NSRange){.location = 0, .length = [s1 length]} + options: NSStringEnumerationByParagraphs + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { // *stop = YES; if (currentIteration == 0) - PASS([substring isEqual:@"Paragraph 1"], + PASS([substring isEqual: @"Paragraph 1"], "First paragraph of \"Paragraph 1\\nParagraph " "2\" is \"Paragraph 1\""); if (currentIteration == 1) - PASS([substring isEqual:@"Paragraph 2"], + PASS([substring isEqual: @"Paragraph 2"], "Second paragraph of \"Paragraph 1\\nParagraph " "2\" is \"Paragraph 2\""); currentIteration++; @@ -219,16 +219,16 @@ void testLocationOffset() { NSString *s1 = @"Word1 word2."; __block NSUInteger currentIteration = 0; - [s1 enumerateSubstringsInRange:(NSRange){.location = 0, .length = [s1 length]} - options:NSStringEnumerationByWords - usingBlock:^(NSString *substring, NSRange substringRange, + [s1 enumerateSubstringsInRange: (NSRange){.location = 0, .length = [s1 length]} + options: NSStringEnumerationByWords + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { // *stop = YES; if (currentIteration == 0) - PASS([substring isEqual:@"Word1"], + PASS([substring isEqual: @"Word1"], "First word of \"Word1 word2.\" is \"Word1\""); if (currentIteration == 1) - PASS([substring isEqual:@"word2"], + PASS([substring isEqual: @"word2"], "Second word of \"Word1 word2.\" is \"word2\""); currentIteration++; }]; @@ -239,17 +239,17 @@ void testLocationOffset() { NSString *s1 = @"Sentence 1. Sentence 2."; __block NSUInteger currentIteration = 0; - [s1 enumerateSubstringsInRange:(NSRange){.location = 0, .length = [s1 length]} - options:NSStringEnumerationBySentences - usingBlock:^(NSString *substring, NSRange substringRange, + [s1 enumerateSubstringsInRange: (NSRange){.location = 0, .length = [s1 length]} + options: NSStringEnumerationBySentences + usingBlock: ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { // *stop = YES; if (currentIteration == 0) - PASS([substring isEqual:@"Sentence 1. "], + PASS([substring isEqual: @"Sentence 1. "], "First sentence of \"Sentence 1. Sentence 2.\" " "is \"Sentence 1. \""); if (currentIteration == 1) - PASS([substring isEqual:@"Sentence 2."], + PASS([substring isEqual: @"Sentence 2."], "Second sentence of \"Sentence 1. Sentence 2.\" " "is \"Sentence 2.\""); currentIteration++; @@ -268,4 +268,4 @@ void testLocationOffset() { { return 0; } -#endif \ No newline at end of file +#endif diff --git a/Tests/base/NSString/nuls_in_strings.m b/Tests/base/NSString/nuls_in_strings.m index 443d636a81..87a19c2ba8 100644 --- a/Tests/base/NSString/nuls_in_strings.m +++ b/Tests/base/NSString/nuls_in_strings.m @@ -16,7 +16,7 @@ int main(int argc, char **argv) unichar characters[3]={'a',0,'b'}; NSRange r; - normalString = [[NSString alloc] initWithCharacters: characters length: 3]; + normalString = AUTORELEASE([[NSString alloc] initWithCharacters: characters length: 3]); PASS([constantString length] == 3, "nuls in constant strings"); PASS([normalString length] == 3, "nuls in non-constant strings"); diff --git a/Tests/base/NSString/test05.m b/Tests/base/NSString/test05.m index 164386fab0..cc9c3985af 100644 --- a/Tests/base/NSString/test05.m +++ b/Tests/base/NSString/test05.m @@ -9,16 +9,16 @@ int main() unichar theUniChar[1] = {0xe5}; theString = [NSString stringWithCharacters:theUniChar length:1]; - PASS([theString isEqual:[[NSString alloc] initWithCString: [theString cStringUsingEncoding: NSISOLatin1StringEncoding] encoding: NSISOLatin1StringEncoding]],"foo"); + PASS([theString isEqual: AUTORELEASE([[NSString alloc] initWithCString: [theString cStringUsingEncoding: NSISOLatin1StringEncoding] encoding: NSISOLatin1StringEncoding])],"foo"); NS_DURING - PASS([theString isEqual:[[NSString alloc] initWithCString: [theString cString]]],"foo"); + PASS([theString isEqual: AUTORELEASE([[NSString alloc] initWithCString: [theString cString]])],"foo"); NS_HANDLER PASS(1,"bar"); NS_ENDHANDLER NS_DURING - PASS([theString isEqual:[[NSMutableString alloc] initWithCString: [theString cString]]],"foo2"); + PASS([theString isEqual: AUTORELEASE([[NSMutableString alloc] initWithCString: [theString cString]])],"foo2"); NS_HANDLER PASS(1,"bar2"); NS_ENDHANDLER diff --git a/Tests/base/NSString/test08.m b/Tests/base/NSString/test08.m index 6a4fa557cd..21f225e83b 100644 --- a/Tests/base/NSString/test08.m +++ b/Tests/base/NSString/test08.m @@ -47,15 +47,15 @@ int main (int argc, const char * argv[]) PASS([s1 compare: s2 options: NSNumericSearch] == NSOrderedDescending, "11 is greater than 2"); - a1 = [[NSArray alloc] initWithObjects: + a1 = [NSArray arrayWithObjects: @"2", @"1", @"10", @"11", @"20", @"3", nil]; - a = [[NSArray alloc] initWithObjects: + a = [NSArray arrayWithObjects: @"1", @"10", @"11", @"2", @"20", @"3", nil]; a2 = [a1 sortedArrayUsingSelector: @selector(compare:)]; PASS_EQUAL(a2, a, "text sort"); - a = [[NSArray alloc] initWithObjects: + a = [NSArray arrayWithObjects: @"1", @"2", @"3", @"10", @"11", @"20", nil]; a2 = [a1 sortedArrayUsingSelector: @selector(numericCompare:)]; PASS_EQUAL(a2, a, "numeric sort"); diff --git a/Tests/base/NSString/utf8.m b/Tests/base/NSString/utf8.m index 35cbff82ca..da064e2ea7 100644 --- a/Tests/base/NSString/utf8.m +++ b/Tests/base/NSString/utf8.m @@ -45,7 +45,7 @@ int main(void) uni[0] = 0xdbff; uni[1] = 0xdfff; - exp = [[NSString alloc] initWithCharacters: uni length: 2]; + exp = AUTORELEASE([[NSString alloc] initWithCharacters: uni length: 2]); buf[0] = 0xf4; buf[1] = 0x8f; buf[2] = 0xbf; diff --git a/Tests/base/Unicode/test00.m b/Tests/base/Unicode/test00.m index 25869082ae..0e32b50672 100644 --- a/Tests/base/Unicode/test00.m +++ b/Tests/base/Unicode/test00.m @@ -21,6 +21,7 @@ int main() cstr = [[NSString alloc] initWithData: adat encoding: NSUTF8StringEncoding]; PASS((cstr != nil && [cstr isKindOfClass: [NSString class]]), "We can convert to UTF8 Encoding"); + RELEASE(cstr); [arp release]; arp = nil; return 0; From 75ae2da4989a61cea43d104656a35b6b1de50e41 Mon Sep 17 00:00:00 2001 From: rfm Date: Sat, 16 Nov 2024 11:41:12 +0000 Subject: [PATCH 23/64] Fix bug when emptying an empty array --- Headers/GNUstepBase/GSIArray.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Headers/GNUstepBase/GSIArray.h b/Headers/GNUstepBase/GSIArray.h index b11edc90a9..bdf883d51b 100644 --- a/Headers/GNUstepBase/GSIArray.h +++ b/Headers/GNUstepBase/GSIArray.h @@ -574,13 +574,16 @@ GSIArrayRemoveItemsFromIndex(GSIArray array, unsigned index) GS_STATIC_INLINE void GSIArrayRemoveAllItems(GSIArray array) { -#ifndef GSI_ARRAY_NO_RELEASE - while (array->count--) + if (array->count) { - GSI_ARRAY_RELEASE(array, array->ptr[array->count]); - } +#ifndef GSI_ARRAY_NO_RELEASE + while (array->count--) + { + GSI_ARRAY_RELEASE(array, array->ptr[array->count]); + } #endif - array->count = 0; + array->count = 0; + } } GS_STATIC_INLINE void From 1e5c30dc50335bcfa2faf1e76834a32b9afb01bf Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 21:33:40 +0000 Subject: [PATCH 24/64] Avoid possible leak caused by exception during property list parsing --- Source/NSPropertyList.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/NSPropertyList.m b/Source/NSPropertyList.m index 45264eaac5..43b31cfcb9 100644 --- a/Source/NSPropertyList.m +++ b/Source/NSPropertyList.m @@ -2734,8 +2734,9 @@ + (id) propertyListWithData: (NSData*)data GSBinaryPLParser *p = [GSBinaryPLParser alloc]; p = [p initWithData: data mutability: anOption]; - result = [p rootObject]; - RELEASE(p); + /* to avoid a leak on exception, autorelease before parse + */ + result = [AUTORELEASE(p) rootObject]; } break; From 9573539795b9786acf5d0bd666e2640298c0e24c Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 21:49:24 +0000 Subject: [PATCH 25/64] Fix buffer overrun --- Source/NSHTTPCookie.m | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Source/NSHTTPCookie.m b/Source/NSHTTPCookie.m index 6decc8baa2..418e2cb403 100644 --- a/Source/NSHTTPCookie.m +++ b/Source/NSHTTPCookie.m @@ -197,19 +197,21 @@ + (NSMutableArray *) _parseField: (NSString *)field + (NSArray *) cookiesWithResponseHeaderFields: (NSDictionary *)headerFields forURL: (NSURL *)URL { - NSEnumerator *henum = [headerFields keyEnumerator]; - NSMutableArray *a = [NSMutableArray array]; - NSString *header; + NSEnumerator *henum = [headerFields keyEnumerator]; + NSMutableArray *a = [NSMutableArray array]; + NSString *header; while ((header = [henum nextObject])) { - NSMutableArray *suba - = [self _parseField: [headerFields objectForKey: header] - forHeader: header andURL: URL]; + NSString *field = [headerFields objectForKey: header]; + NSMutableArray *suba = [self _parseField: field + forHeader: header + andURL: URL]; if (suba) - [a addObjectsFromArray: suba]; + { + [a addObjectsFromArray: suba]; + } } - return a; } @@ -825,7 +827,7 @@ static BOOL skipSpace(pldata *pld) } RELEASE(key); RELEASE(val); - if (pld->ptr[pld->pos] == ';') + if (pld->pos < pld->end && pld->ptr[pld->pos] == ';') { pld->pos++; } From 87c50830e239414fcfe893eddc2433f06d423823 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 22:31:41 +0000 Subject: [PATCH 26/64] Fix some more leaks --- Tests/base/NSHTTPCookie/basic.m | 13 ++++--- Tests/base/NSKVOSupport/general.m | 57 +++++++++++++++------------- Tests/base/NSKeyedArchiver/basic.m | 9 ++++- Tests/base/NSKeyedArchiver/create.m | 20 +++++----- Tests/base/NSKeyedArchiver/general.m | 45 +++++++++++----------- 5 files changed, 78 insertions(+), 66 deletions(-) diff --git a/Tests/base/NSHTTPCookie/basic.m b/Tests/base/NSHTTPCookie/basic.m index e89ceda130..b380249123 100644 --- a/Tests/base/NSHTTPCookie/basic.m +++ b/Tests/base/NSHTTPCookie/basic.m @@ -4,13 +4,14 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSDictionary *dict; - NSArray *cookies; - NSURL *url; - NSHTTPCookie *cookie; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSDictionary *dict; + NSArray *cookies; + NSURL *url; + NSHTTPCookie *cookie; - TEST_FOR_CLASS(@"NSHTTPCookie", [NSHTTPCookie alloc], + cookie = AUTORELEASE([NSHTTPCookie new]); + TEST_FOR_CLASS(@"NSHTTPCookie", cookie, "NSHTTPCookie +alloc returns an NSHTTPCookie"); dict = [NSDictionary dictionaryWithObjectsAndKeys: @"myname", @"Name", diff --git a/Tests/base/NSKVOSupport/general.m b/Tests/base/NSKVOSupport/general.m index c215bde328..c9080f2223 100644 --- a/Tests/base/NSKVOSupport/general.m +++ b/Tests/base/NSKVOSupport/general.m @@ -103,10 +103,10 @@ - (void)setContext:(void *)newContext; @end @implementation TestKVOChange -+ (id)changeWithKeypath:(NSString *)keypath - object:(id)object - info:(NSDictionary *)info - context:(void *)context ++ (id) changeWithKeypath: (NSString *)keypath + object: (id)object + info: (NSDictionary *)info + context: (void *)context { TestKVOChange *change = [[[self alloc] init] autorelease]; [change setKeypath: keypath]; @@ -116,55 +116,60 @@ + (id)changeWithKeypath:(NSString *)keypath return change; } -- (NSString *)keypath { - return _keypath; +- (NSString *) keypath +{ + return _keypath; } -- (void)setKeypath:(NSString *)newKeypath +- (void) setKeypath: (NSString *)newKeypath { - if (_keypath != newKeypath) + if (_keypath != newKeypath) { - [_keypath release]; - _keypath = [newKeypath copy]; + [_keypath release]; + _keypath = [newKeypath copy]; } } -- (id)object +- (id) object { - return _object; + return _object; } -- (void)setObject:(id)newObject +- (void) setObject: (id)newObject { ASSIGN(_object, newObject); } - (NSDictionary *)info { - return _info; + return _info; } -- (void)setInfo:(NSDictionary *)newInfo +- (void) setInfo: (NSDictionary *)newInfo { - ASSIGN(_info, [newInfo copy]); + if (newInfo != _info) + { + [_info release]; + _info = [newInfo copy]; + } } -- (void *)context +- (void *) context { - return _context; + return _context; } -- (void)setContext:(void *)newContext +- (void) setContext:(void *)newContext { - _context = newContext; + _context = newContext; } -- (void)dealloc +- (void) dealloc { - [_object release]; - [_keypath release]; - [_info release]; - [super dealloc]; + [_object release]; + [_keypath release]; + [_info release]; + [super dealloc]; } @end @@ -216,7 +221,7 @@ - (NSSet *)changesForKeypath:(NSString *)keypath [_lock lock]; NSSet *paths = [[_changedKeypaths objectForKey:keypath] copy]; [_lock unlock]; - return paths; + return AUTORELEASE(paths); } - (void)clear { diff --git a/Tests/base/NSKeyedArchiver/basic.m b/Tests/base/NSKeyedArchiver/basic.m index d5272c66fa..d1de1421ce 100644 --- a/Tests/base/NSKeyedArchiver/basic.m +++ b/Tests/base/NSKeyedArchiver/basic.m @@ -3,10 +3,15 @@ int main() { NSAutoreleasePool *arp = [NSAutoreleasePool new]; + test_alloc_only(@"NSKeyedArchiver"); - test_NSObject(@"NSKeyedArchiver",[NSArray arrayWithObject:[[NSKeyedArchiver alloc] initForWritingWithMutableData: [NSMutableData data]]]); + test_NSObject(@"NSKeyedArchiver", [NSArray arrayWithObject: + AUTORELEASE([[NSKeyedArchiver alloc] initForWritingWithMutableData: + [NSMutableData data]])]); test_alloc_only(@"NSKeyedUnarchiver"); - test_NSObject(@"NSKeyedUnarchiver",[NSArray arrayWithObject:[[NSKeyedUnarchiver alloc] initForReadingWithData: [NSKeyedArchiver archivedDataWithRootObject: [NSData data]]]]); + test_NSObject(@"NSKeyedUnarchiver", [NSArray arrayWithObject: + AUTORELEASE([[NSKeyedUnarchiver alloc] initForReadingWithData: + [NSKeyedArchiver archivedDataWithRootObject: [NSData data]]])]); [arp release]; arp = nil; return 0; diff --git a/Tests/base/NSKeyedArchiver/create.m b/Tests/base/NSKeyedArchiver/create.m index 25f57fda91..cb59681f39 100644 --- a/Tests/base/NSKeyedArchiver/create.m +++ b/Tests/base/NSKeyedArchiver/create.m @@ -7,18 +7,20 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - id obj; - NSMutableData *data1; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + id obj; + NSMutableData *data1; - obj = [NSKeyedArchiver alloc]; data1 = [NSMutableData dataWithLength: 0]; - obj = [obj initForWritingWithMutableData: data1]; - PASS((obj != nil && [obj isKindOfClass:[NSKeyedArchiver class]]), "-initForWritingWithMutableData seems ok"); + obj = AUTORELEASE([[NSKeyedArchiver alloc] + initForWritingWithMutableData: data1]); + PASS((obj != nil && [obj isKindOfClass: [NSKeyedArchiver class]]), + "-initForWritingWithMutableData seems ok") - PASS_EXCEPTION([[NSUnarchiver alloc] initForReadingWithData:nil];, - @"NSInvalidArgumentException", - "Creating an NSUnarchiver with nil data throws an exception"); + PASS_EXCEPTION(AUTORELEASE([[NSUnarchiver alloc] + initForReadingWithData: nil]);, + @"NSInvalidArgumentException", + "Creating an NSUnarchiver with nil data throws an exception") [arp release]; arp = nil; return 0; diff --git a/Tests/base/NSKeyedArchiver/general.m b/Tests/base/NSKeyedArchiver/general.m index 46b654312b..c7d5d3efea 100644 --- a/Tests/base/NSKeyedArchiver/general.m +++ b/Tests/base/NSKeyedArchiver/general.m @@ -27,8 +27,9 @@ int main() u = [NSURL URLWithString: @"http://www.w3.org/"]; ms = [NSMutableSet set]; [ms addObject: u]; - data2 = [NSMutableData new]; - archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: data2]; + data2 = [NSMutableData data]; + archiver = AUTORELEASE([[NSKeyedArchiver alloc] + initForWritingWithMutableData: data2]); [archiver setOutputFormat: NSPropertyListXMLFormat_v1_0]; [archiver encodeObject: ms forKey: @"root"]; [archiver finishEncoding]; @@ -38,28 +39,25 @@ int main() PASS([[[ms anyObject] absoluteString] isEqual: @"http://www.w3.org/"], "Can archive and restore a URL"); - [archiver release]; - [data2 release]; - - - PASS_RUNS(val1 = [NSString stringWithCString:"Archiver.dat"]; - val2 = [NSString stringWithCString:"A Goodbye"]; - val3 = [NSString stringWithCString:"Testing all strings"]; - val4 = [NSNumber numberWithUnsignedInt: 100]; - vals1 = [[[NSArray arrayWithObject:val1] - arrayByAddingObject:val2] - arrayByAddingObject: val4]; - vals2 = [vals1 arrayByAddingObject: val2];, - "We can build basic strings and arrays for tests"); + PASS_RUNS( + val1 = [NSString stringWithCString:"Archiver.dat"]; + val2 = [NSString stringWithCString:"A Goodbye"]; + val3 = [NSString stringWithCString:"Testing all strings"]; + val4 = [NSNumber numberWithUnsignedInt: 100]; + vals1 = [[[NSArray arrayWithObject: val1] + arrayByAddingObject: val2] + arrayByAddingObject: val4]; + vals2 = [vals1 arrayByAddingObject: val2];, + "We can build basic strings and arrays for tests") - PASS([NSKeyedArchiver archiveRootObject:vals2 toFile:val1], + PASS([NSKeyedArchiver archiveRootObject: vals2 toFile: val1], "archiveRootObject:toFile: seems ok"); - data1 = [NSKeyedArchiver archivedDataWithRootObject:vals2]; + data1 = [NSKeyedArchiver archivedDataWithRootObject: vals2]; PASS((data1 != nil && [data1 length] != 0), "archivedDataWithRootObject: seems ok"); - a = [NSKeyedUnarchiver unarchiveObjectWithData:data1]; + a = [NSKeyedUnarchiver unarchiveObjectWithData: data1]; NSLog(@"From data: original array %@, decoded array %@",vals2, a); PASS((a != nil && [a isKindOfClass:[NSArray class]] && [a isEqual:vals2]), "unarchiveObjectWithData: seems ok"); @@ -70,17 +68,18 @@ int main() "unarchiveObjectWithFile: seems ok"); // encode - data2 = [[NSMutableData alloc] initWithCapacity: 10240]; - archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: data2]; + data2 = [NSMutableData dataWithCapacity: 10240]; + archiver = AUTORELEASE([[NSKeyedArchiver alloc] + initForWritingWithMutableData: data2]); [archiver encodeObject: val3 forKey: @"string"]; [archiver finishEncoding]; // decode... - unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: data2]; - s = [[unarchiver decodeObjectForKey: @"string"] retain]; + unarchiver = AUTORELEASE([[NSKeyedUnarchiver alloc] + initForReadingWithData: data2]); + s = [unarchiver decodeObjectForKey: @"string"]; PASS((s != nil && [s isKindOfClass:[NSString class]] && [s isEqual: val3]), "encodeObject:forKey: seems okay"); - [data2 release]; NSLog(@"Original string: %@, unarchived string: %@",val3, s); From aedd13dc94ffba2b6f31de49a27c185e53052e25 Mon Sep 17 00:00:00 2001 From: rfm Date: Sat, 16 Nov 2024 13:34:56 +0000 Subject: [PATCH 27/64] More leaks fixed --- Tests/base/NSKVOSupport/kvoToMany.m | 5 +- Tests/base/NSLock/RecursiveLock.m | 2 +- Tests/base/NSLock/condlock.m | 17 ++-- Tests/base/NSLock/doubleLocking.m | 22 ++--- Tests/base/NSLock/tryLock.m | 22 ++--- Tests/base/NSLock/unbalancedUnlock.m | 2 +- Tests/base/NSMethodSignature/general.m | 2 +- Tests/base/NSMutableAttributedString/basic.m | 7 +- Tests/base/NSMutableAttributedString/test00.m | 89 ++++++++++--------- Tests/base/NSMutableAttributedString/test01.m | 28 ++++-- Tests/base/NSMutableCharacterSet/basic.m | 3 +- Tests/base/NSMutableData/basic.m | 3 +- Tests/base/NSMutableData/general.m | 64 ++++++------- Tests/base/NSMutableDictionary/basic.m | 2 +- Tests/base/NSMutableDictionary/general.m | 8 +- Tests/base/NSMutableIndexSet/test0.m | 6 +- Tests/base/NSMutableString/basic.m | 25 +++--- Tests/base/NSNotification/basic.m | 12 +-- Tests/base/NSNotification/dynamic.m | 8 +- 19 files changed, 174 insertions(+), 153 deletions(-) diff --git a/Tests/base/NSKVOSupport/kvoToMany.m b/Tests/base/NSKVOSupport/kvoToMany.m index b612d1dbcb..d68f958ef5 100644 --- a/Tests/base/NSKVOSupport/kvoToMany.m +++ b/Tests/base/NSKVOSupport/kvoToMany.m @@ -873,8 +873,11 @@ - (void)dealloc { START_SET("NSArrayShouldThrowWhenTryingToObserveIndexesOutOfRange"); - NSArray *test = [NSArray arrayWithObjects: [Observee new], [Observee new], nil]; + NSArray *o1 = AUTORELEASE([Observee new]); + NSArray *o2 = AUTORELEASE([Observee new]); + NSArray *test = [NSArray arrayWithObjects: o1, o2, nil]; TestObserver *observer = [TestObserver new]; + PASS_EXCEPTION([test addObserver:observer toObjectsAtIndexes:[NSIndexSet indexSetWithIndex:4] forKeyPath:@"bareArray" diff --git a/Tests/base/NSLock/RecursiveLock.m b/Tests/base/NSLock/RecursiveLock.m index 930508faaf..678fee126b 100644 --- a/Tests/base/NSLock/RecursiveLock.m +++ b/Tests/base/NSLock/RecursiveLock.m @@ -6,7 +6,7 @@ int main() { NSAutoreleasePool *arp = [NSAutoreleasePool new]; BOOL ret; - NSLock *lock = [NSRecursiveLock new]; + NSLock *lock = AUTORELEASE([NSRecursiveLock new]); ret = [lock tryLock]; if (ret) diff --git a/Tests/base/NSLock/condlock.m b/Tests/base/NSLock/condlock.m index e429535fd0..58b8a32a7e 100644 --- a/Tests/base/NSLock/condlock.m +++ b/Tests/base/NSLock/condlock.m @@ -65,18 +65,20 @@ - (void) consumeFromQueue: (Queue*)q int main(void) { - [NSAutoreleasePool new]; + ENTER_POOL { - Queue *q = [Queue new]; - NSMutableArray *sent = [NSMutableArray new]; - received = [NSMutableArray new]; - unsigned int i; + Queue *q = AUTORELEASE([Queue new]); + NSMutableArray *sent = [NSMutableArray array]; + unsigned int i; + + received = [NSMutableArray array]; [NSThread detachNewThreadSelector: @selector(consumeFromQueue:) - toTarget: [Consumer new] - withObject: q]; + toTarget: [Consumer new] + withObject: q]; for (i = 0; i < 10000; i++) { id obj = [NSNumber numberWithUnsignedInt: i]; + [sent addObject: obj]; if (i % 10 == 0) { @@ -91,5 +93,6 @@ int main(void) [NSThread sleepForTimeInterval: 2.0]; PASS([sent isEqual: received], "Condition lock"); } + LEAVE_POOL return 0; } diff --git a/Tests/base/NSLock/doubleLocking.m b/Tests/base/NSLock/doubleLocking.m index 6f100915e3..0ffb2ffb80 100644 --- a/Tests/base/NSLock/doubleLocking.m +++ b/Tests/base/NSLock/doubleLocking.m @@ -22,7 +22,7 @@ int main() helpers = [helpers stringByAppendingPathComponent: @"obj"]; command = [helpers stringByAppendingPathComponent: @"doubleNSLock"]; - task = [[NSTask alloc] init]; + task = AUTORELEASE([[NSTask alloc] init]); ePipe = [[NSPipe pipe] retain]; [task setLaunchPath: command]; [task setStandardError: ePipe]; @@ -34,8 +34,8 @@ int main() } data = [hdl availableData]; NSLog(@"Data was %*.*s", [data length], [data length], [data bytes]); - string = [NSString alloc]; - string = [string initWithData: data encoding: NSISOLatin1StringEncoding]; + string = AUTORELEASE([[NSString alloc] + initWithData: data encoding: NSISOLatin1StringEncoding]); PASS([string rangeOfString: @"deadlock"].length > 0, "NSLock reported deadlock as expected"); if (NO == testPassed) @@ -46,8 +46,8 @@ int main() [task waitUntilExit]; command = [helpers stringByAppendingPathComponent: @"doubleNSConditionLock"]; - task = [[NSTask alloc] init]; - ePipe = [[NSPipe pipe] retain]; + task = AUTORELEASE([[NSTask alloc] init]); + ePipe = [NSPipe pipe]; [task setLaunchPath: command]; [task setStandardError: ePipe]; hdl = [ePipe fileHandleForReading]; @@ -58,8 +58,8 @@ int main() } data = [hdl availableData]; NSLog(@"Data was %*.*s", [data length], [data length], [data bytes]); - string = [NSString alloc]; - string = [string initWithData: data encoding: NSISOLatin1StringEncoding]; + string = AUTORELEASE([[NSString alloc] + initWithData: data encoding: NSISOLatin1StringEncoding]); PASS([string rangeOfString: @"deadlock"].length > 0, "NSConditionLock reported deadlock as expected"); if (NO == testPassed) @@ -69,23 +69,23 @@ int main() } [task waitUntilExit]; - ASSIGN(lock,[NSRecursiveLock new]); + lock = AUTORELEASE([NSRecursiveLock new]); [lock lock]; [lock lock]; [lock unlock]; [lock unlock]; - ASSIGN(lock,[NSLock new]); + lock = AUTORELEASE([NSLock new]); PASS([lock tryLock] == YES, "NSLock can tryLock"); PASS([lock tryLock] == NO, "NSLock says NO for recursive tryLock"); [lock unlock]; - ASSIGN(lock,[NSConditionLock new]); + lock = AUTORELEASE([NSConditionLock new]); PASS([lock tryLock] == YES, "NSConditionLock can tryLock"); PASS([lock tryLock] == NO, "NSConditionLock says NO for recursive tryLock"); [lock unlock]; - ASSIGN(lock,[NSRecursiveLock new]); + lock = AUTORELEASE([NSRecursiveLock new]); PASS([lock tryLock] == YES, "NSRecursiveLock can tryLock"); PASS([lock tryLock] == YES, "NSRecursiveLock says YES for recursive tryLock"); [lock unlock]; diff --git a/Tests/base/NSLock/tryLock.m b/Tests/base/NSLock/tryLock.m index b2edbedf4a..2818d75091 100644 --- a/Tests/base/NSLock/tryLock.m +++ b/Tests/base/NSLock/tryLock.m @@ -3,24 +3,24 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - BOOL ret; - id lock; + NSAutoreleasePool *arp = [NSAutoreleasePool new]; + BOOL ret; + id lock = nil; - lock = [NSLock new]; + lock = AUTORELEASE([NSLock new]); ret = [lock tryLock]; if (ret) [lock unlock]; PASS(ret, "NSLock with tryLock, then unlocking"); - ASSIGN(lock,[NSLock new]); + lock = AUTORELEASE([NSLock new]); [lock tryLock]; ret = [lock tryLock]; if (ret) [lock unlock]; PASS(ret == NO, "Recursive try lock with NSLock should return NO"); - ASSIGN(lock,[NSConditionLock new]); + lock = AUTORELEASE([NSConditionLock new]); [lock lock]; ret = [lock tryLock]; if (ret) @@ -38,34 +38,34 @@ int main() [lock unlock]; PASS(ret == NO, "Recursive tryLockWhenCondition: with NSConditionLock (2) should return NO"); - ASSIGN(lock,[NSRecursiveLock new]); + lock = AUTORELEASE([NSRecursiveLock new]); [lock tryLock]; ret = [lock tryLock]; if (ret) [lock unlock]; PASS(ret == YES, "Recursive try lock with NSRecursiveLock should return YES"); - ASSIGN(lock,[NSLock new]); + lock = AUTORELEASE([NSLock new]); ret = [lock lockBeforeDate: [NSDate dateWithTimeIntervalSinceNow: 1]]; if (ret) [lock unlock]; PASS(ret, "NSLock lockBeforeDate: works"); - ASSIGN(lock,[NSLock new]); + lock = AUTORELEASE([NSLock new]); [lock tryLock]; ret = [lock lockBeforeDate: [NSDate dateWithTimeIntervalSinceNow: 1]]; if (ret) [lock unlock]; PASS(ret == NO, "Recursive lockBeforeDate: with NSLock returns NO"); - ASSIGN(lock,[NSConditionLock new]); + lock = AUTORELEASE([NSConditionLock new]); [lock tryLock]; ret = [lock lockBeforeDate: [NSDate dateWithTimeIntervalSinceNow: 1]]; if (ret) [lock unlock]; PASS(ret == NO, "Recursive lockBeforeDate: with NSConditionLock returns NO"); - ASSIGN(lock,[NSRecursiveLock new]); + lock = AUTORELEASE([NSRecursiveLock new]); [lock tryLock]; ret = [lock lockBeforeDate: [NSDate dateWithTimeIntervalSinceNow: 1]]; if (ret) diff --git a/Tests/base/NSLock/unbalancedUnlock.m b/Tests/base/NSLock/unbalancedUnlock.m index 5c9b04a1a3..216bec4c0a 100644 --- a/Tests/base/NSLock/unbalancedUnlock.m +++ b/Tests/base/NSLock/unbalancedUnlock.m @@ -6,7 +6,7 @@ int main() { START_SET("Unbalanced unlocking") - NSLock *lock = [NSLock new]; + NSLock *lock = AUTORELEASE([NSLock new]); NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; BOOL mode = [defs boolForKey: @"GSMacOSXCompatible"]; diff --git a/Tests/base/NSMethodSignature/general.m b/Tests/base/NSMethodSignature/general.m index eccffe6bec..ae18b0faa7 100644 --- a/Tests/base/NSMethodSignature/general.m +++ b/Tests/base/NSMethodSignature/general.m @@ -198,7 +198,7 @@ -(const char *)runtimeSignatureForSelector:(SEL)selector void test_compare_server_signature(void) { - id objct = [MyClass new]; + id objct = AUTORELEASE([MyClass new]); id proxy = [NSConnection rootProxyForConnectionWithRegisteredName: SRV_NAME host: nil]; if (proxy) diff --git a/Tests/base/NSMutableAttributedString/basic.m b/Tests/base/NSMutableAttributedString/basic.m index 400c6b44b6..8f3911247c 100644 --- a/Tests/base/NSMutableAttributedString/basic.m +++ b/Tests/base/NSMutableAttributedString/basic.m @@ -3,9 +3,10 @@ #import "ObjectTesting.h" int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSArray *arr = [NSArray arrayWithObject:[NSMutableAttributedString new]]; + ENTER_POOL + NSArray *arr; + arr = [NSArray arrayWithObject: AUTORELEASE([NSMutableAttributedString new])]; test_alloc(@"NSMutableAttributedString"); test_NSObject(@"NSMutableAttributedString", arr); test_NSCoding(arr); @@ -13,7 +14,7 @@ int main() test_NSCopying(@"NSAttributedString",@"NSMutableAttributedString",arr,NO, NO); test_NSMutableCopying(@"NSAttributedString",@"NSMutableAttributedString",arr); - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSMutableAttributedString/test00.m b/Tests/base/NSMutableAttributedString/test00.m index c21c58e8ad..b0a361f487 100644 --- a/Tests/base/NSMutableAttributedString/test00.m +++ b/Tests/base/NSMutableAttributedString/test00.m @@ -63,12 +63,13 @@ -(BOOL) checkAttributes: (NSDictionary *)attr range: (NSRange)range int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; + ENTER_POOL NSMutableAttributedString *attrStr; NSString *baseString = @"0123456789"; NSDictionary *red, *gray, *blue; NSMutableAttributedString *s; + s = [[[NSMutableAttributedString alloc] initWithString: @"string"] autorelease]; [s _sanity]; @@ -97,8 +98,8 @@ int main() gray = [NSDictionary dictionaryWithObject:@"Gray" forKey:@"Color"]; blue = [NSDictionary dictionaryWithObject:@"Blue" forKey:@"Color"]; - attrStr = [[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]; + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; PASS([[attrStr string] isEqual:baseString] && [attrStr checkAttributes:red range:NSMakeRange(0,10)], @@ -109,8 +110,8 @@ int main() PASS([attrStr checkAttributes:blue range:NSMakeRange(0,10)], "-setAttributes:range: works for the whole string"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(0,5)]; [attrStr _sanity]; @@ -118,8 +119,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(5,5)], "-setAttributes:range: works for the first half of the string"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(3,5)]; [attrStr _sanity]; @@ -135,8 +136,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(8,2)], "-setAttributes:range: works for same attributes in middle of string"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(5,5)]; [attrStr _sanity]; @@ -144,8 +145,8 @@ int main() [attrStr checkAttributes:blue range:NSMakeRange(5,5)], "-setAttributes:range: works for the last half of the string"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(0,3)]; [attrStr _sanity]; @@ -158,8 +159,8 @@ int main() [attrStr checkAttributes:gray range:NSMakeRange(7,3)], "-setAttributes:range: works in three parts of the string"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(0,5)]; [attrStr _sanity]; @@ -173,8 +174,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(9,1)], "-setAttributes:range: works with overlapping"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr= AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(1,2)]; [attrStr _sanity]; @@ -191,8 +192,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(9,1)], "-setAttributes:range: works with overlapping (2)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(2,5)]; [attrStr _sanity]; @@ -203,8 +204,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(7,3)], "-setAttributes:range: works with replacing"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(1,8)]; [attrStr _sanity]; @@ -221,8 +222,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(9,1)], "-setAttributes:range: works with chinese boxes"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(1,3)]; [attrStr _sanity]; @@ -233,8 +234,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(5,5)], "-setAttributes:range: works with extending at the end (diff color)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:gray range:NSMakeRange(1,3)]; [attrStr _sanity]; @@ -245,8 +246,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(5,5)], "-setAttributes:range: works with extending at the end (diff color)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(2,3)]; [attrStr _sanity]; @@ -257,8 +258,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(5,5)], "-setAttributes:range: works with extending at the beginning (diff color)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:gray range:NSMakeRange(2,3)]; [attrStr _sanity]; @@ -270,8 +271,8 @@ int main() "-setAttributes:range: works with extending at the beginning (same color)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(1,3)]; [attrStr _sanity]; @@ -283,8 +284,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(4,6)], "-setAttributes:range: works with subset at the end (diff color)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:gray range:NSMakeRange(1,3)]; [attrStr _sanity]; @@ -295,8 +296,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(4,6)], "-setAttributes:range: works with subset at the end (same color)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(2,3)]; [attrStr _sanity]; @@ -308,8 +309,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(5,5)], "-setAttributes:range: works with subset at the beginning (diff color)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:gray range:NSMakeRange(2,3)]; [attrStr _sanity]; @@ -320,8 +321,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(5,5)], "-setAttributes:range: works with subset at the beginning (same color)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:gray range:NSMakeRange(2,1)]; [attrStr _sanity]; @@ -334,8 +335,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(6,4)], "-setAttributes:range: works with subsets (diff color)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(2,1)]; [attrStr _sanity]; @@ -348,8 +349,8 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(6,4)], "-setAttributes:range: works with subsets (same color)"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(2,1)]; [attrStr _sanity]; @@ -364,8 +365,8 @@ int main() PASS([attrStr checkAttributes:gray range:NSMakeRange(0,10)], "-setAttributes:range: works with setting attributes for the whole string"); - ASSIGN(attrStr,[[NSMutableAttributedString alloc] initWithString:baseString - attributes:red]); + attrStr = AUTORELEASE([[NSMutableAttributedString alloc] + initWithString: baseString attributes: red]); [attrStr _sanity]; [attrStr setAttributes:blue range:NSMakeRange(0,1)]; [attrStr _sanity]; @@ -377,7 +378,7 @@ int main() [attrStr checkAttributes:red range:NSMakeRange(3,7)], "-setAttributes:range: works with nearby attributes"); - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSMutableAttributedString/test01.m b/Tests/base/NSMutableAttributedString/test01.m index 60ea4fce80..9be82082b8 100644 --- a/Tests/base/NSMutableAttributedString/test01.m +++ b/Tests/base/NSMutableAttributedString/test01.m @@ -44,6 +44,18 @@ -(BOOL)checkAttributes:(NSDictionary *)attr range:(NSRange)range } @end +@interface NSMutableAttributedString (autoreleased) ++ (NSMutableAttributedString*) stringWithString: (NSString*)s + attributes: (NSDictionary*)a; +@end +@implementation NSMutableAttributedString (autoreleased) ++ (NSMutableAttributedString*) stringWithString: (NSString*)s + attributes: (NSDictionary*)a +{ + return AUTORELEASE([[self alloc] initWithString: s attributes: a]); +} +@end + int main() { NSAutoreleasePool *arp = [NSAutoreleasePool new]; @@ -55,25 +67,25 @@ int main() [[[NSMutableAttributedString new] autorelease] _sanity]; - as = [[NSMutableAttributedString alloc] initWithString:base1 attributes:nil]; + as = [NSMutableAttributedString stringWithString:base1 attributes:nil]; [as replaceCharactersInRange:NSMakeRange(2,2) withString:@""]; [as _sanity]; PASS([[as string] isEqual:@"ba-1"], "-replaceCharactersInRange: withString: works with zero length string"); - as = [[NSMutableAttributedString alloc] initWithString:base1 attributes:nil]; + as = [NSMutableAttributedString stringWithString:base1 attributes:nil]; [as replaceCharactersInRange:NSMakeRange(2,2) withString:base2]; [as _sanity]; PASS([[as string] isEqual:@"babase-2-1"], "-replaceCharactersInRange:withString: works in middle of string"); - as = [[NSMutableAttributedString alloc] initWithString:base1 attributes:nil]; + as = [NSMutableAttributedString stringWithString:base1 attributes:nil]; [as replaceCharactersInRange:NSMakeRange(6,0) withString:base2]; [as _sanity]; PASS([[as string] isEqual:@"base-1base-2"], "-replaceCharactersInRange:withString: works at end of string works"); - as = [[NSMutableAttributedString alloc] initWithString:base1 attributes:nil]; + as = [NSMutableAttributedString stringWithString:base1 attributes:nil]; [as replaceCharactersInRange:NSMakeRange(0,0) withString:base2]; [as _sanity]; PASS([[as string] isEqual:@"base-2base-1"], @@ -82,7 +94,7 @@ int main() attrE = [NSDictionary dictionary]; attr1 = [NSDictionary dictionaryWithObject:@"a" forKey:@"1"]; attr2 = [NSDictionary dictionaryWithObject:@"b" forKey:@"2"]; - as = [[NSMutableAttributedString alloc] initWithString:base1 + as = [NSMutableAttributedString stringWithString:base1 attributes:attr1]; [as setAttributes:attr2 range:NSMakeRange(2,4)]; [as replaceCharactersInRange:NSMakeRange(0,6) withString:@""]; @@ -92,7 +104,7 @@ int main() PASS([as checkAttributes:attrE range:NSMakeRange(0,4)], "-replaceCharactersInRange:withString: keeps attributes if entire string is replaced"); - as = [[NSMutableAttributedString alloc] initWithString:base1 + as = [NSMutableAttributedString stringWithString:base1 attributes:attr1]; [as replaceCharactersInRange:NSMakeRange(0,6) withString:base2]; [as _sanity]; @@ -107,7 +119,7 @@ int main() BOOL removeAll,replaceAll; NSDictionary *aBegin,*aEnd; - as = [[NSMutableAttributedString alloc] initWithString:@"aabbccdd" + as = [NSMutableAttributedString stringWithString:@"aabbccdd" attributes:attr2]; removeAll = (start == 0 && length == 8); [as setAttributes:attr1 range:NSMakeRange(2,2)]; @@ -134,7 +146,7 @@ int main() "attribute/(replaceCharacters... with zero length string) interaction _sanity checks %i %i",start, length); } - as = [[NSMutableAttributedString alloc] initWithString:@"aabbccdd" + as = [NSMutableAttributedString stringWithString:@"aabbccdd" attributes:attr2]; replaceAll = (start == 0 && length == 8); [as setAttributes:attr1 range:NSMakeRange(2,2)]; diff --git a/Tests/base/NSMutableCharacterSet/basic.m b/Tests/base/NSMutableCharacterSet/basic.m index 7de9b397d6..78b0e2cefb 100644 --- a/Tests/base/NSMutableCharacterSet/basic.m +++ b/Tests/base/NSMutableCharacterSet/basic.m @@ -5,7 +5,8 @@ int main() { NSAutoreleasePool *arp = [NSAutoreleasePool new]; - id testObj = [NSMutableCharacterSet new]; + id testObj = AUTORELEASE([NSMutableCharacterSet new]); + test_alloc(@"NSMutableCharacterSet"); test_NSObject(@"NSMutableCharacterSet",[NSArray arrayWithObject:testObj]); test_NSCoding([NSArray arrayWithObject:testObj]); diff --git a/Tests/base/NSMutableData/basic.m b/Tests/base/NSMutableData/basic.m index c5fd17e9b1..d8bf135b26 100644 --- a/Tests/base/NSMutableData/basic.m +++ b/Tests/base/NSMutableData/basic.m @@ -5,7 +5,8 @@ int main() { NSAutoreleasePool *arp = [NSAutoreleasePool new]; - id testObject = [NSMutableData new]; + id testObject = [NSMutableData data]; + test_alloc(@"NSMutableData"); test_NSObject(@"NSData",[NSArray arrayWithObject:testObject]); test_NSCoding([NSArray arrayWithObject:testObject]); diff --git a/Tests/base/NSMutableData/general.m b/Tests/base/NSMutableData/general.m index 8050c0f1c3..a0604df436 100644 --- a/Tests/base/NSMutableData/general.m +++ b/Tests/base/NSMutableData/general.m @@ -6,52 +6,52 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - char *str1,*str2,*tmp; - NSData *data1; + ENTER_POOL + char *str1, *str2, *tmp; + NSData *data1; NSMutableData *mutable; unsigned char *hold; str1 = "Test string for data classes"; - str2 = (char *) malloc(sizeof("insert")); - strcpy(str2,"insert"); + str2 = (char *)malloc(sizeof("insert")); + strcpy(str2, "insert"); - mutable = [NSMutableData dataWithLength:100]; + mutable = [NSMutableData dataWithLength: 100]; hold = [mutable mutableBytes]; - /* hmpf is this correct */ - data1 = [NSData dataWithBytes:str1 length:(strlen(str1) * sizeof(void*))]; - PASS(data1 != nil && - [data1 isKindOfClass:[NSData class]] && - [data1 length] == (strlen(str1) * sizeof(void*)) && - [data1 bytes] != str1 && - strcmp(str1,[data1 bytes]) == 0, - "+dataWithBytes:length: works"); + data1 = [NSData dataWithBytes: str1 length: (strlen(str1) + 1)]; + PASS(data1 != nil + && [data1 isKindOfClass: [NSData class]] + && [data1 length] == (strlen(str1) + 1) + && [data1 bytes] != str1 + && strcmp(str1, [data1 bytes]) == 0, + "+dataWithBytes:length: works") mutable = [NSMutableData data]; - PASS(mutable != nil && - [mutable isKindOfClass:[NSMutableData class]] && - [mutable length] == 0, - "+data creates empty mutable data"); + PASS(mutable != nil + && [mutable isKindOfClass: [NSMutableData class]] + && [mutable length] == 0, + "+data creates empty mutable data") - [mutable setData:data1]; - PASS(mutable != nil && - [mutable length] == (strlen(str1) * sizeof(void*)), - "-setData: works"); + [mutable setData: data1]; + PASS(mutable != nil + && [mutable length] == (strlen(str1) + 1), + "-setData: works") - [mutable replaceBytesInRange:NSMakeRange(22,6) withBytes:str2]; + [mutable replaceBytesInRange: NSMakeRange(22, 6) withBytes: str2]; tmp = (char *)malloc([mutable length]); - [mutable getBytes:tmp range:NSMakeRange(22,6)]; + [mutable getBytes: tmp range: NSMakeRange(22, 6)]; tmp[6] = '\0'; - PASS(mutable != nil && - strcmp(tmp,str2) == 0, - "-replaceBytesInRange:withBytes suceeds"); + PASS(mutable != nil + && strcmp(tmp, str2) == 0, + "-replaceBytesInRange:withBytes suceeds") free(tmp); - PASS_EXCEPTION([mutable replaceBytesInRange:NSMakeRange([mutable length]+1,6) - withBytes:str2];, - NSRangeException,"-replaceBytesInRange:withBytes out of range raises exception"); - + PASS_EXCEPTION([mutable + replaceBytesInRange: NSMakeRange([mutable length]+1, 6) withBytes: str2];, + NSRangeException, + "-replaceBytesInRange:withBytes out of range raises exception") - [arp release]; arp = nil; + free(str2); + LEAVE_POOL return 0; } diff --git a/Tests/base/NSMutableDictionary/basic.m b/Tests/base/NSMutableDictionary/basic.m index 52667308aa..ecba146c2b 100644 --- a/Tests/base/NSMutableDictionary/basic.m +++ b/Tests/base/NSMutableDictionary/basic.m @@ -7,7 +7,7 @@ int main() NSAutoreleasePool *arp = [NSAutoreleasePool new]; NSMutableDictionary *testObj; - testObj = [NSMutableDictionary new]; + testObj = [NSMutableDictionary dictionary]; test_NSObject(@"NSMutableDictionary", [NSArray arrayWithObject:testObj]); diff --git a/Tests/base/NSMutableDictionary/general.m b/Tests/base/NSMutableDictionary/general.m index 80ccf10b59..9a5f5a147a 100644 --- a/Tests/base/NSMutableDictionary/general.m +++ b/Tests/base/NSMutableDictionary/general.m @@ -8,7 +8,7 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; + ENTER_POOL NSString *key1, *key2, *key3, *val1, *val2, *val3; NSArray *keys1, *keys2, *keys3, *vals1, *vals2, *vals3; id obj; @@ -28,7 +28,7 @@ int main() vals3 = [NSArray arrayWithObjects:val1,val2,val3,nil]; - dict = [NSMutableDictionary new]; + dict = [NSMutableDictionary dictionary]; PASS(dict != nil && [dict isKindOfClass:[NSMutableDictionary class]] && [dict count] == 0, @@ -207,7 +207,7 @@ int main() [obj isEqual:dict], "-description gives us a text property-list"); - dict = [NSMutableDictionary new]; + dict = [NSMutableDictionary dictionary]; [dict setObject:@"hello" forKey:@"world"]; PASS(dict != nil && [dict isKindOfClass:[NSMutableDictionary class]] && @@ -218,6 +218,6 @@ int main() PASS([[dict valueForKey:@"Lücke"] isEqualToString:@"hello"], "unicode keys work with setValue:forKey:"); - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSMutableIndexSet/test0.m b/Tests/base/NSMutableIndexSet/test0.m index f71fd9fd87..1858ddb740 100644 --- a/Tests/base/NSMutableIndexSet/test0.m +++ b/Tests/base/NSMutableIndexSet/test0.m @@ -3,8 +3,8 @@ #include int main() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSMutableIndexSet *set = [[NSMutableIndexSet alloc] init]; + ENTER_POOL + NSMutableIndexSet *set = AUTORELEASE([NSMutableIndexSet new]); [set addIndex:1]; [set addIndex:2]; @@ -22,6 +22,6 @@ int main() PASS([set containsIndexesInRange:NSMakeRange(0,2)], "contains range"); - [pool release]; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSMutableString/basic.m b/Tests/base/NSMutableString/basic.m index 1912675dec..715c62ed35 100644 --- a/Tests/base/NSMutableString/basic.m +++ b/Tests/base/NSMutableString/basic.m @@ -31,7 +31,7 @@ - (id) initWithBytesNoCopy: (void *)c length: l encoding: encoding freeWhenDone: freeWhenDone]; - if (s == nil) return nil; + if (s == nil) {RELEASE(self); return nil;} l = [s length] * sizeof(unichar); characters = malloc(l); [s getCharacters: characters]; @@ -66,22 +66,22 @@ - (unichar) characterAtIndex: (NSUInteger)index int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; + ENTER_POOL unichar u0 = 'a'; unichar u1 = 0xfe66; NSMutableString *testObj,*base,*ext,*want, *str1, *str2; unichar chars[3]; test_alloc(@"NSMutableString"); - testObj = [[NSMutableString alloc] initWithCString:"Hello\n"]; - test_NSCoding([NSArray arrayWithObject:testObj]); - test_keyed_NSCoding([NSArray arrayWithObject:testObj]); + testObj = AUTORELEASE([[NSMutableString alloc] initWithCString:"Hello\n"]); + test_NSCoding([NSArray arrayWithObject: testObj]); + test_keyed_NSCoding([NSArray arrayWithObject: testObj]); test_NSCopying(@"NSString",@"NSMutableString", - [NSArray arrayWithObject:testObj],NO,NO); + [NSArray arrayWithObject: testObj],NO,NO); test_NSMutableCopying(@"NSString",@"NSMutableString", - [NSArray arrayWithObject:testObj]); + [NSArray arrayWithObject: testObj]); - base = [[NSMutableString alloc] initWithCString:"hello"]; + base = [NSMutableString stringWithCString:"hello"]; ext = [@"\"\\UFE66???\"" propertyList]; want = [@"\"hello\\UFE66???\"" propertyList]; [base appendString:ext]; @@ -89,11 +89,11 @@ int main() && [want length] == 9 && [base isEqual:want], "We can append a unicode string to a C string"); - PASS([[[NSMutableString alloc] initWithCharacters: &u0 length: 1] + PASS([AUTORELEASE([[NSMutableString alloc] initWithCharacters: &u0 length: 1]) isKindOfClass: [NSMutableString class]], "initWithCharacters:length: creates mutable string for ascii"); - PASS([[[NSMutableString alloc] initWithCharacters: &u1 length: 1] + PASS([AUTORELEASE([[NSMutableString alloc] initWithCharacters: &u1 length: 1]) isKindOfClass: [NSMutableString class]], "initWithCharacters:length: creates mutable string for unicode"); @@ -101,7 +101,7 @@ int main() appendString: @"bar"];, "can append to string from NSMutableString +stringWithString:"); - testObj = [@"hello" mutableCopy]; + testObj = AUTORELEASE([@"hello" mutableCopy]); [testObj replaceCharactersInRange: NSMakeRange(1,1) withString: @"a"]; PASS([testObj isEqual: @"hallo"], "replaceCharactersInRange:withString: works in middle of string"); @@ -179,7 +179,6 @@ int main() PASS_EQUAL(str, @"Text Message", "remove combining-tilde") } - [testObj release]; - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSNotification/basic.m b/Tests/base/NSNotification/basic.m index c62e65accb..3e2fd64cc7 100644 --- a/Tests/base/NSNotification/basic.m +++ b/Tests/base/NSNotification/basic.m @@ -22,10 +22,9 @@ - (BOOL) isEqualForTestcase: (id)other int main() { - NSNotification *obj; - NSMutableArray *testObjs = [[NSMutableArray alloc] init]; - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - + ENTER_POOL + NSNotification *obj; + NSMutableArray *testObjs = [NSMutableArray array]; NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys: @"obj", @"key", nil]; NSNotification *o1 = [NSNotification notificationWithName: @"hello" @@ -34,18 +33,19 @@ int main() NSNotification *o2 = [NSNotification notificationWithName: @"hello" object: @"there" userInfo: info]; + PASS([o1 hash] == [o2 hash], "equal notification hashes") PASS_EQUAL(o1, o2, "equal notifications") test_alloc(@"NSNotification"); - obj = [NSNotification new]; + obj = AUTORELEASE([NSNotification new]); [testObjs addObject: obj]; test_NSObject(@"NSNotification", testObjs); test_NSCoding(testObjs); test_keyed_NSCoding(testObjs); test_NSCopying(@"NSNotification",@"NSNotification",testObjs,NO,NO); - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSNotification/dynamic.m b/Tests/base/NSNotification/dynamic.m index b5f5e829d9..95c33f3f46 100644 --- a/Tests/base/NSNotification/dynamic.m +++ b/Tests/base/NSNotification/dynamic.m @@ -20,18 +20,18 @@ - (void) bar: (NSNotification*)n int main(void) { + ENTER_POOL NSNotificationCenter *nc; - id t = [Toggle new]; + id t = AUTORELEASE([Toggle new]); - [NSAutoreleasePool new]; - nc = [NSNotificationCenter new]; + nc = AUTORELEASE([NSNotificationCenter new]); [nc addObserver: t selector: @selector(foo:) name: nil object: nil]; class_replaceMethod([Toggle class], @selector(foo:), class_getMethodImplementation([Toggle class], @selector(bar:)), "v@:@"); [nc postNotificationName: @"foo" object: t]; - [t release]; PASS(YES == notifiedCurrent, "implementation not cached"); + LEAVE_POOL return 0; } From c7f0c27dd75d044c40d3136e540f86261e79e8f9 Mon Sep 17 00:00:00 2001 From: rfm Date: Sat, 16 Nov 2024 14:07:33 +0000 Subject: [PATCH 28/64] More leaks fixed --- Tests/base/NSNumber/test00.m | 6 ++--- Tests/base/NSNumberFormatter/basic.m | 2 +- Tests/base/NSObject/test01.m | 2 +- Tests/base/NSObject/test02.m | 12 +++++---- Tests/base/NSOperation/basic.m | 20 +++++++------- Tests/base/NSOrderedSet/basic.m | 2 +- .../NSPersonNameComponentsFormatter/basic.m | 17 +++++++----- Tests/base/NSPointerArray/create.m | 26 ++++++++++--------- 8 files changed, 47 insertions(+), 40 deletions(-) diff --git a/Tests/base/NSNumber/test00.m b/Tests/base/NSNumber/test00.m index 097e22b64c..9794ef2c1e 100644 --- a/Tests/base/NSNumber/test00.m +++ b/Tests/base/NSNumber/test00.m @@ -132,9 +132,9 @@ int main() PASS(200 == [val1 unsignedShortValue], "NSDecimalNumber unsignedShortValue works") - val1 = [[NSNumber alloc] initWithLongLong: LLONG_MIN]; - val2 = [[NSNumber alloc] initWithUnsignedLongLong: - (unsigned long long)LLONG_MAX + 1]; + val1 = AUTORELEASE([[NSNumber alloc] initWithLongLong: LLONG_MIN]); + val2 = AUTORELEASE([[NSNumber alloc] initWithUnsignedLongLong: + (unsigned long long)LLONG_MAX + 1]); PASS([val1 compare: val2] == NSOrderedAscending, "comparison of min signed with max unsigned works") diff --git a/Tests/base/NSNumberFormatter/basic.m b/Tests/base/NSNumberFormatter/basic.m index 7858b7557b..8b2082eebd 100644 --- a/Tests/base/NSNumberFormatter/basic.m +++ b/Tests/base/NSNumberFormatter/basic.m @@ -13,7 +13,7 @@ int main() [NSNumberFormatter setDefaultFormatterBehavior: NSNumberFormatterBehavior10_0]; - TEST_FOR_CLASS(@"NSNumberFormatter",[NSNumberFormatter alloc], + TEST_FOR_CLASS(@"NSNumberFormatter", AUTORELEASE([NSNumberFormatter alloc]), "+[NSNumberFormatter alloc] returns a NSNumberFormatter"); fmt = [[[NSNumberFormatter alloc] init] autorelease]; diff --git a/Tests/base/NSObject/test01.m b/Tests/base/NSObject/test01.m index bb89461329..0e89de0b27 100644 --- a/Tests/base/NSObject/test01.m +++ b/Tests/base/NSObject/test01.m @@ -48,7 +48,7 @@ int main() ![[[NSArray new] autorelease] isClass]), "-isClass returns NO on an instance"); - evilObject = [MyEvilClass new]; + evilObject = AUTORELEASE([MyEvilClass new]); [evilObject setInfo:1]; PASS(![evilObject isClass], "-isClass returns NO on an instance (special test for broken libobjc)"); diff --git a/Tests/base/NSObject/test02.m b/Tests/base/NSObject/test02.m index 943cf4319a..ff99fa097b 100644 --- a/Tests/base/NSObject/test02.m +++ b/Tests/base/NSObject/test02.m @@ -36,20 +36,22 @@ - (void) doNothingCategory int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; + ENTER_POOL + id instance = AUTORELEASE([NicolaTest new]); + PASS([NicolaTest conformsToProtocol:@protocol(DoingNothing)], "+conformsToProtocol returns YES on an implemented protocol"); PASS([NicolaTest conformsToProtocol:@protocol(DoingNothingCategory)], "+conformsToProtocol returns YES on a protocol implemented in a category"); PASS(![NicolaTest conformsToProtocol:@protocol(NSCoding)], "+conformsToProtocol returns NO on an unimplemented protocol"); - PASS([[NicolaTest new] conformsToProtocol:@protocol(DoingNothing)], + PASS([instance conformsToProtocol:@protocol(DoingNothing)], "-conformsToProtocol returns YES on an implemented protocol"); - PASS([[NicolaTest new] conformsToProtocol:@protocol(DoingNothingCategory)], + PASS([instance conformsToProtocol:@protocol(DoingNothingCategory)], "-conformsToProtocol returns YES on a protocol implemented in a category"); - PASS(![[NicolaTest new] conformsToProtocol:@protocol(NSCoding)], + PASS(![instance conformsToProtocol:@protocol(NSCoding)], "-conformsToProtocol returns NO on an unimplemented protocol"); - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSOperation/basic.m b/Tests/base/NSOperation/basic.m index 869d845d71..e8c84ba2cf 100644 --- a/Tests/base/NSOperation/basic.m +++ b/Tests/base/NSOperation/basic.m @@ -12,13 +12,13 @@ int main() { + ENTER_POOL id obj1; id obj2; - NSMutableArray *testObjs = [[NSMutableArray alloc] init]; - NSAutoreleasePool *arp = [NSAutoreleasePool new]; + NSMutableArray *testObjs = [NSMutableArray array]; test_alloc(@"NSOperation"); - obj1 = [NSOperation new]; + obj1 = AUTORELEASE([NSOperation new]); PASS((obj1 != nil), "can create an operation"); [testObjs addObject: obj1]; test_NSObject(@"NSOperation", testObjs); @@ -36,7 +36,7 @@ int main() PASS(([obj1 queuePriority] == NSOperationQueuePriorityVeryHigh), "operation has very high priority"); - obj2 = [NSOperation new]; + obj2 = AUTORELEASE([NSOperation new]); [obj2 addDependency: obj1]; PASS(([[obj2 dependencies] isEqual: testObjs]), "operation has added dependency"); @@ -53,8 +53,7 @@ int main() "dependency removal works"); PASS(([obj2 isReady] == YES), "operation without dependency is ready"); - [obj1 release]; - obj1 = [NSOperation new]; + obj1 = AUTORELEASE([NSOperation new]); [testObjs replaceObjectAtIndex: 0 withObject: obj1]; [obj2 addDependency: obj1]; # if __has_feature(blocks) @@ -72,8 +71,7 @@ int main() PASS(([obj2 isReady] == YES), "operation with finished dependency is ready"); [obj2 removeDependency: obj1]; - [obj1 release]; - obj1 = [NSOperation new]; + obj1 = AUTORELEASE([NSOperation new]); [testObjs replaceObjectAtIndex: 0 withObject: obj1]; [obj2 addDependency: obj1]; [obj2 cancel]; @@ -92,7 +90,7 @@ int main() test_alloc(@"NSOperationQueue"); - obj1 = [NSOperationQueue new]; + obj1 = AUTORELEASE([NSOperationQueue new]); PASS((obj1 != nil), "can create an operation queue"); [testObjs removeAllObjects]; [testObjs addObject: obj1]; @@ -121,11 +119,11 @@ int main() NSInvalidArgumentException, "NSOperationQueue cannot be given negative count"); - obj2 = [NSOperation new]; + obj2 = AUTORELEASE([NSOperation new]); [obj1 addOperation: obj2]; [NSThread sleepForTimeInterval: 1.0]; PASS(([obj2 isFinished] == YES), "queue ran operation"); - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSOrderedSet/basic.m b/Tests/base/NSOrderedSet/basic.m index 5351641f8b..3fa4e979a0 100644 --- a/Tests/base/NSOrderedSet/basic.m +++ b/Tests/base/NSOrderedSet/basic.m @@ -120,7 +120,7 @@ int main() NSOrderedSet *testObj, *testObj2; NSMutableOrderedSet *mutableTest1, *mutableTest2; - NSMutableArray *testObjs = [NSMutableArray new]; + NSMutableArray *testObjs = [NSMutableArray array]; NSData *data = [stringData dataUsingEncoding: NSUTF8StringEncoding]; NSMutableSet *testSet; diff --git a/Tests/base/NSPersonNameComponentsFormatter/basic.m b/Tests/base/NSPersonNameComponentsFormatter/basic.m index d48703b1cc..102cd1a12d 100644 --- a/Tests/base/NSPersonNameComponentsFormatter/basic.m +++ b/Tests/base/NSPersonNameComponentsFormatter/basic.m @@ -6,16 +6,21 @@ int main() { START_SET("NSPersonNameComponentsFormatter base"); - NSPersonNameComponents *pnc = [[NSPersonNameComponents alloc] init]; + NSPersonNameComponents *pnc; + NSPersonNameComponents *pnc2; + NSPersonNameComponentsFormatter *fmt; + + pnc = AUTORELEASE([[NSPersonNameComponents alloc] init]); [pnc setGivenName: @"Gregory"]; [pnc setMiddleName: @"John"]; [pnc setFamilyName: @"Casamento"]; [pnc setNameSuffix: @"PhD"]; [pnc setNamePrefix: @"Dr."]; - NSPersonNameComponentsFormatter *fmt = [[NSPersonNameComponentsFormatter alloc] init]; - NSPersonNameComponents *pnc2 = [fmt personNameComponentsFromString: - @"Dr. Gregory John Casamento PhD"]; + fmt = AUTORELEASE([[NSPersonNameComponentsFormatter alloc] init]); + pnc2 = [fmt personNameComponentsFromString: + @"Dr. Gregory John Casamento PhD"]; + PASS([[pnc givenName] isEqualToString: [pnc2 givenName]], "First name matches"); PASS([[pnc middleName] isEqualToString: @@ -27,7 +32,7 @@ int main() PASS([[pnc namePrefix] isEqualToString: [pnc2 namePrefix]], "Prefix name matches"); - fmt = [[NSPersonNameComponentsFormatter alloc] init]; + fmt = AUTORELEASE([[NSPersonNameComponentsFormatter alloc] init]); pnc2 = [fmt personNameComponentsFromString: @"Gregory John Casamento PhD"]; PASS([[pnc givenName] isEqualToString: @@ -39,7 +44,7 @@ int main() PASS([[pnc nameSuffix] isEqualToString: [pnc2 nameSuffix]], "Suffix name matches"); - fmt = [[NSPersonNameComponentsFormatter alloc] init]; + fmt = AUTORELEASE([[NSPersonNameComponentsFormatter alloc] init]); pnc2 = [fmt personNameComponentsFromString: @"Gregory John Casamento"]; PASS([[pnc givenName] isEqualToString: diff --git a/Tests/base/NSPointerArray/create.m b/Tests/base/NSPointerArray/create.m index 14e8acd4db..5af2c0b7b8 100644 --- a/Tests/base/NSPointerArray/create.m +++ b/Tests/base/NSPointerArray/create.m @@ -4,11 +4,9 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSMutableString *ms; + ENTER_POOL NSString *val1, *val2, *val3; - NSPointerArray *obj, *old; - NSUInteger rc; + NSPointerArray *obj; id vals[3]; val1 = @"Hello"; @@ -19,9 +17,9 @@ int main() vals[1] = val2; vals[2] = val3; - obj = [[NSPointerArray new] autorelease]; + obj = AUTORELEASE([NSPointerArray new]); PASS(obj != nil - && [obj isKindOfClass:[NSPointerArray class]] + && [obj isKindOfClass: [NSPointerArray class]] && [obj count] == 0, "+new creates an empty pointer array"); @@ -36,13 +34,17 @@ int main() PASS([obj count] == 5 && [obj pointerAtIndex: 2] == (void*)vals[0], "+insertPointer:atIndex: works"); - obj = [NSPointerArray pointerArrayWithWeakObjects]; - ms = [@"hello" mutableCopy]; - rc = [ms retainCount]; - [obj addPointer: ms]; - PASS(rc == [ms retainCount], "array with weak references doesn't retain"); + LEAVE_POOL + + ENTER_POOL + NSPointerArray *pa = [NSPointerArray weakObjectsPointerArray]; + NSMutableString *ms = AUTORELEASE([@"hello" mutableCopy]); + NSUInteger rc = [ms retainCount]; + + [pa addPointer: ms]; + PASS(rc == [ms retainCount], "array with weak references doesn't retain") + LEAVE_POOL - [arp release]; arp = nil; return 0; } From d68e8be8ee0ea0374461bf53b69b1a2e4f9c1482 Mon Sep 17 00:00:00 2001 From: rfm Date: Sat, 16 Nov 2024 15:45:38 +0000 Subject: [PATCH 29/64] Fix leaks --- Source/NSPredicate.m | 215 +++++++++++++++++++------------------------ 1 file changed, 96 insertions(+), 119 deletions(-) diff --git a/Source/NSPredicate.m b/Source/NSPredicate.m index a10d2d434d..d07557d6ba 100644 --- a/Source/NSPredicate.m +++ b/Source/NSPredicate.m @@ -133,36 +133,26 @@ @interface GSKeyPathExpression : NSExpression } @end -@interface GSKeyPathCompositionExpression : NSExpression +@interface GSBinaryExpression : NSExpression { @public NSExpression *_left; NSExpression *_right; } +- (NSExpression *) leftExpression; +- (NSExpression *) rightExpression; @end -@interface GSUnionSetExpression : NSExpression -{ - @public - NSExpression *_left; - NSExpression *_right; -} +@interface GSKeyPathCompositionExpression : GSBinaryExpression @end -@interface GSIntersectSetExpression : NSExpression -{ - @public - NSExpression *_left; - NSExpression *_right; -} +@interface GSUnionSetExpression : GSBinaryExpression @end -@interface GSMinusSetExpression : NSExpression -{ - @public - NSExpression *_left; - NSExpression *_right; -} +@interface GSIntersectSetExpression : GSBinaryExpression +@end + +@interface GSMinusSetExpression : GSBinaryExpression @end @interface GSSubqueryExpression : NSExpression @@ -224,10 +214,9 @@ + (NSPredicate *) predicateWithFormat: (NSString *)format GSPredicateScanner *s; NSPredicate *p; - s = [[GSPredicateScanner alloc] initWithString: format - args: args]; + s = AUTORELEASE([[GSPredicateScanner alloc] initWithString: format + args: args]); p = [s parse]; - RELEASE(s); return p; } @@ -357,10 +346,9 @@ + (NSPredicate *) predicateWithFormat: (NSString *)format } } } - s = [[GSPredicateScanner alloc] initWithString: format - args: arr]; + s = AUTORELEASE([[GSPredicateScanner alloc] initWithString: format + args: arr]); p = [s parse]; - RELEASE(s); return p; } @@ -519,7 +507,7 @@ - (id) initWithType: (NSCompoundPredicateType)type - (void) dealloc { RELEASE(_subs); - [super dealloc]; + DEALLOC } - (id) copyWithZone: (NSZone *)z @@ -755,7 +743,7 @@ - (void) dealloc; { RELEASE(_left); RELEASE(_right); - [super dealloc]; + DEALLOC } - (NSComparisonPredicateModifier) comparisonPredicateModifier @@ -1245,10 +1233,10 @@ + (NSExpression *) expressionForConstantValue: (id)obj { GSConstantValueExpression *e; - e = [[GSConstantValueExpression alloc] - initWithExpressionType: NSConstantValueExpressionType]; + e = AUTORELEASE([[GSConstantValueExpression alloc] + initWithExpressionType: NSConstantValueExpressionType]); ASSIGN(e->_obj, obj); - return AUTORELEASE(e); + return e; } + (NSExpression *) expressionForEvaluatedObject @@ -1262,8 +1250,8 @@ + (NSExpression *) expressionForFunction: (NSString *)name GSFunctionExpression *e; NSString *s; - e = [[GSFunctionExpression alloc] - initWithExpressionType: NSFunctionExpressionType]; + e = AUTORELEASE([[GSFunctionExpression alloc] + initWithExpressionType: NSFunctionExpressionType]); s = [NSString stringWithFormat: @"_eval_%@:", name]; e->_selector = NSSelectorFromString(s); if (![e respondsToSelector: e->_selector]) @@ -1279,7 +1267,7 @@ + (NSExpression *) expressionForFunction: (NSString *)name else if ([name isEqualToString: @"_mul"]) e->_op = @"*"; else if ([name isEqualToString: @"_div"]) e->_op = @"/"; else if ([name isEqualToString: @"_pow"]) e->_op = @"**"; - return AUTORELEASE(e); + return e; } + (NSExpression *) expressionForKeyPath: (NSString *)path @@ -1291,10 +1279,10 @@ + (NSExpression *) expressionForKeyPath: (NSString *)path [NSException raise: NSInvalidArgumentException format: @"Keypath is not NSString: %@", path]; } - e = [[GSKeyPathExpression alloc] - initWithExpressionType: NSKeyPathExpressionType]; + e = AUTORELEASE([[GSKeyPathExpression alloc] + initWithExpressionType: NSKeyPathExpressionType]); ASSIGN(e->_keyPath, path); - return AUTORELEASE(e); + return e; } + (NSExpression *) expressionForKeyPathCompositionWithLeft: (NSExpression*)left @@ -1302,21 +1290,21 @@ + (NSExpression *) expressionForKeyPathCompositionWithLeft: (NSExpression*)left { GSKeyPathCompositionExpression *e; - e = [[GSKeyPathCompositionExpression alloc] - initWithExpressionType: NSKeyPathCompositionExpressionType]; + e = AUTORELEASE([[GSKeyPathCompositionExpression alloc] + initWithExpressionType: NSKeyPathCompositionExpressionType]); ASSIGN(e->_left, left); ASSIGN(e->_right, right); - return AUTORELEASE(e); + return e; } + (NSExpression *) expressionForVariable: (NSString *)string { GSVariableExpression *e; - e = [[GSVariableExpression alloc] - initWithExpressionType: NSVariableExpressionType]; + e = AUTORELEASE([[GSVariableExpression alloc] + initWithExpressionType: NSVariableExpressionType]); ASSIGN(e->_variable, string); - return AUTORELEASE(e); + return e; } // 10.5 methods... @@ -1325,23 +1313,23 @@ + (NSExpression *) expressionForIntersectSet: (NSExpression *)left { GSIntersectSetExpression *e; - e = [[GSIntersectSetExpression alloc] - initWithExpressionType: NSIntersectSetExpressionType]; + e = AUTORELEASE([[GSIntersectSetExpression alloc] + initWithExpressionType: NSIntersectSetExpressionType]); ASSIGN(e->_left, left); ASSIGN(e->_right, right); - return AUTORELEASE(e); + return e; } + (NSExpression *) expressionForAggregate: (NSArray *)subExpressions { GSAggregateExpression *e; - e = [[GSAggregateExpression alloc] - initWithExpressionType: NSAggregateExpressionType]; + e = AUTORELEASE([[GSAggregateExpression alloc] + initWithExpressionType: NSAggregateExpressionType]); ASSIGN(e->_collection, [NSSet setWithArray: subExpressions]); - return AUTORELEASE(e); + return e; } + (NSExpression *) expressionForUnionSet: (NSExpression *)left @@ -1349,12 +1337,12 @@ + (NSExpression *) expressionForUnionSet: (NSExpression *)left { GSUnionSetExpression *e; - e = [[GSUnionSetExpression alloc] - initWithExpressionType: NSUnionSetExpressionType]; + e = AUTORELEASE([[GSUnionSetExpression alloc] + initWithExpressionType: NSUnionSetExpressionType]); ASSIGN(e->_left, left); ASSIGN(e->_right, right); - return AUTORELEASE(e); + return e; } + (NSExpression *) expressionForMinusSet: (NSExpression *)left @@ -1362,12 +1350,12 @@ + (NSExpression *) expressionForMinusSet: (NSExpression *)left { GSMinusSetExpression *e; - e = [[GSMinusSetExpression alloc] - initWithExpressionType: NSMinusSetExpressionType]; + e = AUTORELEASE([[GSMinusSetExpression alloc] + initWithExpressionType: NSMinusSetExpressionType]); ASSIGN(e->_left, left); ASSIGN(e->_right, right); - return AUTORELEASE(e); + return e; } // end 10.5 methods @@ -1587,7 +1575,7 @@ - (id) expressionValueWithObject: (id)object - (void) dealloc { RELEASE(_obj); - [super dealloc]; + DEALLOC } - (id) copyWithZone: (NSZone*)zone @@ -1651,7 +1639,7 @@ - (NSString *) variable - (void) dealloc; { RELEASE(_variable); - [super dealloc]; + DEALLOC } - (id) copyWithZone: (NSZone*)zone @@ -1700,7 +1688,7 @@ - (NSString *) keyPath - (void) dealloc; { RELEASE(_keyPath); - [super dealloc]; + DEALLOC } - (id) copyWithZone: (NSZone*)zone @@ -1719,6 +1707,37 @@ - (id) _expressionWithSubstitutionVariables: (NSDictionary *)variables @end +@implementation GSBinaryExpression + +- (id) copyWithZone: (NSZone*)zone +{ + GSBinaryExpression *copy; + + copy = (GSBinaryExpression *)[super copyWithZone: zone]; + copy->_left = [_left copyWithZone: zone]; + copy->_right = [_right copyWithZone: zone]; + return copy; +} + +- (void) dealloc +{ + RELEASE(_left); + RELEASE(_right); + DEALLOC +} + +- (NSExpression *) leftExpression +{ + return _left; +} + +- (NSExpression *) rightExpression +{ + return _right; +} + +@end + @implementation GSKeyPathCompositionExpression - (NSString *) description @@ -1738,23 +1757,6 @@ - (NSString *) keyPath return nil; } -- (void) dealloc -{ - RELEASE(_left); - RELEASE(_right); - [super dealloc]; -} - -- (id) copyWithZone: (NSZone*)zone -{ - GSKeyPathCompositionExpression *copy; - - copy = (GSKeyPathCompositionExpression *)[super copyWithZone: zone]; - copy->_left = [_left copyWithZone: zone]; - copy->_right = [_right copyWithZone: zone]; - return copy; -} - - (id) _expressionWithSubstitutionVariables: (NSDictionary*)variables { NSExpression *left; @@ -1766,16 +1768,6 @@ - (id) _expressionWithSubstitutionVariables: (NSDictionary*)variables right: right]; } -- (NSExpression *) leftExpression -{ - return _left; -} - -- (NSExpression *) rightExpression -{ - return _right; -} - @end // Macro for checking set related expressions @@ -1808,16 +1800,6 @@ - (NSString *) description return [NSString stringWithFormat: @"%@.%@", _left, _right]; } -- (NSExpression *) leftExpression -{ - return _left; -} - -- (NSExpression *) rightExpression -{ - return _right; -} - - (id) expressionValueWithObject: (id)object context: (NSMutableDictionary *)context { @@ -1844,16 +1826,6 @@ - (NSString *) description return [NSString stringWithFormat: @"%@.%@", _left, _right]; } -- (NSExpression *) leftExpression -{ - return _left; -} - -- (NSExpression *) rightExpression -{ - return _right; -} - - (id) expressionValueWithObject: (id)object context: (NSMutableDictionary *)context { @@ -1880,16 +1852,6 @@ - (NSString *) description return [NSString stringWithFormat: @"%@.%@", _left, _right]; } -- (NSExpression *) leftExpression -{ - return _left; -} - -- (NSExpression *) rightExpression -{ - return _right; -} - - (id) expressionValueWithObject: (id)object context: (NSMutableDictionary *)context { @@ -1914,6 +1876,21 @@ @implementation GSSubqueryExpression @implementation GSAggregateExpression +- (id) copyWithZone: (NSZone*)zone +{ + GSAggregateExpression *copy; + + copy = (GSAggregateExpression *)[super copyWithZone: zone]; + copy->_collection = [_collection copyWithZone: zone]; + return copy; +} + +- (void) dealloc +{ + DESTROY(_collection); + DEALLOC +} + - (NSString *) description { return [NSString stringWithFormat: @"%@", _collection]; @@ -2016,7 +1993,7 @@ - (void) dealloc; { RELEASE(_args); RELEASE(_function); - [super dealloc]; + DEALLOC } - (id) copyWithZone: (NSZone*)zone @@ -3173,8 +3150,8 @@ - (instancetype) initWithBlock: (GSBlockPredicateBlock)block - (instancetype) predicateWithSubstitutionVariables: (GS_GENERIC_CLASS(NSDictionary,NSString*,id)*)variables { - return [[[GSBoundBlockPredicate alloc] initWithBlock: _block - bindings: variables] autorelease]; + return AUTORELEASE([[GSBoundBlockPredicate alloc] initWithBlock: _block + bindings: variables]); } - (BOOL) evaluateWithObject: (id)object @@ -3194,7 +3171,7 @@ - (void) dealloc { [(id)_block release]; _block = NULL; - [super dealloc]; + DEALLOC } - (NSString*) predicateFormat @@ -3226,7 +3203,7 @@ - (BOOL) evaluateWithObject: (id)object - (void) dealloc { DESTROY(_bindings); - [super dealloc]; + DEALLOC } @end From 5b46efa8cd0ac0749b8951e6a2f51c4ee2a85d25 Mon Sep 17 00:00:00 2001 From: rfm Date: Sat, 16 Nov 2024 21:11:56 +0000 Subject: [PATCH 30/64] More leak fixes --- Source/NSRegularExpression.m | 4 ++-- Source/NSURL.m | 26 ++++++++++++++++++-------- Tests/base/NSProgress/basic.m | 13 +++++++------ Tests/base/NSProxy/basic.m | 4 ++-- Tests/base/NSProxy/test00.m | 8 +++++--- Tests/base/NSProxy/test01.m | 2 +- Tests/base/NSRegularExpression/basic.m | 17 ++++++----------- Tests/base/NSRunLoop/basic.m | 14 +++++++------- Tests/base/NSRunLoop/dispatch.m | 2 +- Tests/base/NSScanner/test00.m | 2 +- Tests/base/NSSet/basic.m | 4 ++-- Tests/base/NSSortDescriptor/basic.m | 8 ++++---- Tests/base/NSTask/basic.m | 8 ++++---- Tests/base/NSURL/basic.m | 6 ++++-- 14 files changed, 64 insertions(+), 54 deletions(-) diff --git a/Source/NSRegularExpression.m b/Source/NSRegularExpression.m index ca359f4f0b..fb407496eb 100644 --- a/Source/NSRegularExpression.m +++ b/Source/NSRegularExpression.m @@ -131,6 +131,7 @@ - (id) initWithPattern: (NSString*)aPattern exp = [NSException exceptionWithName: NSInvalidArgumentException reason: @"nil argument" userInfo: nil]; + RELEASE(self); [exp raise]; } @@ -961,10 +962,9 @@ - (NSString*) replacementStringForResult: (NSTextCheckingResult*)result return nil; } utext_clone(&ret->txt, output, TRUE, TRUE, &s); + utext_close(output); uregex_close(r); - utext_close(&txt); - utext_close(output); utext_close(&replacement); return AUTORELEASE(ret); } diff --git a/Source/NSURL.m b/Source/NSURL.m index 341f7d6ac8..c4c350f1e3 100644 --- a/Source/NSURL.m +++ b/Source/NSURL.m @@ -658,14 +658,17 @@ - (id) initFileURLWithPath: (NSString *)aPath isDirectory: (BOOL)isDir relativeToURL: (NSURL *)baseURL { - NSFileManager *mgr = [NSFileManager defaultManager]; - BOOL flag = NO; + NSFileManager *mgr = [NSFileManager defaultManager]; + BOOL flag = NO; if (nil == aPath) { + NSString *name = NSStringFromClass([self class]); + + RELEASE(self); [NSException raise: NSInvalidArgumentException format: @"[%@ %@] nil string parameter", - NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; + name, NSStringFromSelector(_cmd)]; } if ([aPath isAbsolutePath] == NO) { @@ -803,16 +806,22 @@ - (id) initWithString: (NSString*)aUrlString } if ([aUrlString isKindOfClass: [NSString class]] == NO) { + NSString *name = NSStringFromClass([self class]); + + RELEASE(self); [NSException raise: NSInvalidArgumentException format: @"[%@ %@] bad string parameter", - NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; + name, NSStringFromSelector(_cmd)]; } if (aBaseUrl != nil && [aBaseUrl isKindOfClass: [NSURL class]] == NO) { + NSString *name = NSStringFromClass([self class]); + RELEASE(self); + [NSException raise: NSInvalidArgumentException format: @"[%@ %@] bad base URL parameter", - NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; + name, NSStringFromSelector(_cmd)]; } ASSIGNCOPY(_urlString, aUrlString); ASSIGN(_baseURL, [aBaseUrl absoluteURL]); @@ -2301,14 +2310,14 @@ + (void) initialize // Creating URL components... + (instancetype) componentsWithString: (NSString *)urlString { - return AUTORELEASE([[NSURLComponents alloc] initWithString: urlString]); + return AUTORELEASE([[NSURLComponents alloc] initWithString: urlString]); } + (instancetype) componentsWithURL: (NSURL *)url resolvingAgainstBaseURL: (BOOL)resolve { - return AUTORELEASE([[NSURLComponents alloc] initWithURL: url - resolvingAgainstBaseURL: resolve]); + return AUTORELEASE([[NSURLComponents alloc] initWithURL: url + resolvingAgainstBaseURL: resolve]); } - (instancetype) init @@ -2342,6 +2351,7 @@ - (instancetype) initWithString: (NSString *)URLString } else { + RELEASE(self); return nil; } } diff --git a/Tests/base/NSProgress/basic.m b/Tests/base/NSProgress/basic.m index 5e9fa40a04..48045e7b06 100644 --- a/Tests/base/NSProgress/basic.m +++ b/Tests/base/NSProgress/basic.m @@ -5,11 +5,12 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; + ENTER_POOL NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + [dict setObject:@"value" forKey:@"key"]; - NSProgress *progress = [[NSProgress alloc] initWithParent: nil - userInfo: dict]; + NSProgress *progress = AUTORELEASE([[NSProgress alloc] initWithParent: nil + userInfo: dict]); PASS(progress != nil, "[NSProgress initWithParent:userInfo:] returns instance"); @@ -42,14 +43,14 @@ int main() NSProgress *new_progress = [NSProgress progressWithTotalUnitCount:100 parent:progress pendingUnitCount:50]; - [new_progress addChild:[[NSProgress alloc] initWithParent: nil userInfo: nil] - withPendingUnitCount:50]; + [new_progress addChild: AUTORELEASE([[NSProgress alloc] + initWithParent: nil userInfo: nil]) withPendingUnitCount:50]; [currentProgress resignCurrent]; PASS([NSProgress currentProgress] == nil, "Current progress is nil after resign current"); - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSProxy/basic.m b/Tests/base/NSProxy/basic.m index 5a977c73cb..e2a60cc221 100644 --- a/Tests/base/NSProxy/basic.m +++ b/Tests/base/NSProxy/basic.m @@ -16,7 +16,7 @@ int main() theClass = [NSProxy class]; PASS(theClass != Nil, "%s exists",prefix); - obj0 = [NSProxy alloc]; + obj0 = AUTORELEASE([NSProxy alloc]); PASS(obj0 != nil, "%s has working alloc",prefix); PASS_EXCEPTION([obj0 isKindOfClass:theClass];, NSInvalidArgumentException, "NSProxy -isKindOfClass raises exception"); @@ -25,7 +25,7 @@ int main() NSInvalidArgumentException, "NSProxy -isKindOfClass raises exception"); - obj1 = [NSProxy allocWithZone:testZone]; + obj1 = AUTORELEASE([NSProxy allocWithZone:testZone]); PASS(obj1 != nil, "%s has working allocWithZone:",prefix); #ifndef OBJC_CAP_ARC PASS(NSZoneFromPointer(obj1) == testZone, "%s uses zone for alloc",prefix); diff --git a/Tests/base/NSProxy/test00.m b/Tests/base/NSProxy/test00.m index 023e61aa0c..ad34436f58 100644 --- a/Tests/base/NSProxy/test00.m +++ b/Tests/base/NSProxy/test00.m @@ -74,10 +74,12 @@ int main() id sub = @"Remote"; PASS(theClass == [NSProxy class], "uses +class to return self"); - PASS([[NSProxy alloc] isProxy] == YES, + obj = [NSProxy alloc]; + PASS([obj isProxy] == YES, "%s implements -isProxy to return YES",prefix); - PASS([[NSProxy alloc] description] != nil, "%s implements -description",prefix); - obj = [[MyProxy alloc] init]; + PASS([obj description] != nil, "%s implements -description",prefix); + RELEASE(obj); + obj = AUTORELEASE([[MyProxy alloc] init]); PASS(obj != nil, "Can create a MyProxy instance"); PASS([obj isEqual: obj], "proxy isEqual: to self without remote"); [obj setRemote: rem]; diff --git a/Tests/base/NSProxy/test01.m b/Tests/base/NSProxy/test01.m index b998b38d80..e0eccfcfb3 100644 --- a/Tests/base/NSProxy/test01.m +++ b/Tests/base/NSProxy/test01.m @@ -188,7 +188,7 @@ - (void) forwardInvocation:(NSInvocation *)inv NSRange r0; NSRange r1; - obj = [[MyProxy alloc] init]; + obj = AUTORELEASE([[MyProxy alloc] init]); [obj setRemote:rem]; [obj voidPvoid]; //shoudn't raise diff --git a/Tests/base/NSRegularExpression/basic.m b/Tests/base/NSRegularExpression/basic.m index 4225134415..d63f6cb2f9 100644 --- a/Tests/base/NSRegularExpression/basic.m +++ b/Tests/base/NSRegularExpression/basic.m @@ -69,15 +69,12 @@ int main() [dflts setVolatileDomain: domain forName: @"GSTestDomain"]; # endif - id testObj = [[NSRegularExpression alloc] initWithPattern: @"^a" - options: 0 - error: NULL]; + id testObj = AUTORELEASE([[NSRegularExpression alloc] + initWithPattern: @"^a" options: 0 error: NULL]); test_NSObject(@"NSRegularExpression", - [NSArray arrayWithObject: - [[NSRegularExpression alloc] initWithPattern: @"^a" - options: 0 - error: NULL]]); + [NSArray arrayWithObject: AUTORELEASE([[NSRegularExpression + alloc] initWithPattern: @"^a" options: 0 error: NULL])]); test_NSCopying(@"NSRegularExpression",@"NSRegularExpression", [NSArray arrayWithObject:testObj],NO,NO); @@ -138,10 +135,8 @@ int main() PASS_EQUAL(replacement, @"c", "Custom replacement: Returns correct replacement"); - NSRegularExpression *testObj2 = - [[NSRegularExpression alloc] initWithPattern: @"bc" - options: 0 - error: NULL]; + NSRegularExpression *testObj2 = AUTORELEASE([[NSRegularExpression alloc] + initWithPattern: @"bc" options: 0 error: NULL]); r = [testObj2 firstMatchInString: @"abcdeabcde" options: 0 range: NSMakeRange(5, 5)]; diff --git a/Tests/base/NSRunLoop/basic.m b/Tests/base/NSRunLoop/basic.m index cf9947118e..2f3f605b96 100644 --- a/Tests/base/NSRunLoop/basic.m +++ b/Tests/base/NSRunLoop/basic.m @@ -5,17 +5,17 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - id testObj; + ENTER_POOL + id testObj; PASS([NSRunLoop new] == nil, "run loop initialises to nil"); testObj = [NSRunLoop currentRunLoop]; - test_NSObject(@"NSRunLoop", [NSArray arrayWithObject:testObj]); + test_NSObject(@"NSRunLoop", [NSArray arrayWithObject: testObj]); - PASS([NSTimer new] == nil, "timer initialises to nil"); - ASSIGN(testObj, [[NSTimer alloc] initWithFireDate: 0 interval: 0 target: [NSObject class] selector: @selector(description) userInfo: nil repeats: NO]); - test_NSObject(@"NSTimer", [NSArray arrayWithObject:testObj]); + PASS(AUTORELEASE([NSTimer new]) == nil, "timer initialises to nil"); + testObj = AUTORELEASE([[NSTimer alloc] initWithFireDate: 0 interval: 0 target: [NSObject class] selector: @selector(description) userInfo: nil repeats: NO]); + test_NSObject(@"NSTimer", [NSArray arrayWithObject: testObj]); - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSRunLoop/dispatch.m b/Tests/base/NSRunLoop/dispatch.m index b0561cb2c7..ac3b737779 100644 --- a/Tests/base/NSRunLoop/dispatch.m +++ b/Tests/base/NSRunLoop/dispatch.m @@ -83,7 +83,7 @@ - (void)timeout: (NSTimer*)t - (void) run { NSDate *until = [NSDate dateWithTimeIntervalSinceNow: 1.0]; - Counter *c = [Counter new]; + Counter *c = AUTORELEASE([Counter new]); [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self selector: @selector(timeout:) diff --git a/Tests/base/NSScanner/test00.m b/Tests/base/NSScanner/test00.m index 2323008d25..518cec2b8f 100644 --- a/Tests/base/NSScanner/test00.m +++ b/Tests/base/NSScanner/test00.m @@ -49,7 +49,7 @@ int main() PASS(scanThreeWords(str,charSet), "scanning three words separated by newlines and spaces"); - charSet = [charSet mutableCopy]; + charSet = AUTORELEASE([charSet mutableCopy]); [charSet addCharactersInString:@";"]; str = @"one ;two ;three ;"; PASS(scanThreeWords(str,charSet), diff --git a/Tests/base/NSSet/basic.m b/Tests/base/NSSet/basic.m index 60b0cd8c9b..8fbd781de1 100644 --- a/Tests/base/NSSet/basic.m +++ b/Tests/base/NSSet/basic.m @@ -6,9 +6,9 @@ int main() { NSAutoreleasePool *arp = [NSAutoreleasePool new]; NSSet *testObj; - NSMutableArray *testObjs = [NSMutableArray new]; + NSMutableArray *testObjs = [NSMutableArray array]; - testObj = [NSSet new]; + testObj = [NSSet set]; [testObjs addObject:testObj]; PASS(testObj != nil && [testObj count] == 0, "can create an empty set"); diff --git a/Tests/base/NSSortDescriptor/basic.m b/Tests/base/NSSortDescriptor/basic.m index 4164560854..63b1154b82 100644 --- a/Tests/base/NSSortDescriptor/basic.m +++ b/Tests/base/NSSortDescriptor/basic.m @@ -18,7 +18,7 @@ int main() NSArray *a2; NSArray *a3; - s1 = [[NSSortDescriptor alloc] initWithKey: @"name" ascending: YES]; + s1 = [NSSortDescriptor sortDescriptorWithKey: @"name" ascending: YES]; PASS(s1 != nil, "can create a sort descriptor"); array = [NSArray arrayWithObject: s1]; @@ -27,9 +27,9 @@ int main() test_keyed_NSCoding(array); test_NSCopying(@"NSSortDescriptor", @"NSSortDescriptor", array, NO, NO); - s2 = [[NSSortDescriptor alloc] initWithKey: @"name" ascending: YES]; - s3 = [[NSSortDescriptor alloc] initWithKey: @"other" ascending: YES]; - s4 = [[NSSortDescriptor alloc] initWithKey: @"other" ascending: NO]; + s2 = [NSSortDescriptor sortDescriptorWithKey: @"name" ascending: YES]; + s3 = [NSSortDescriptor sortDescriptorWithKey: @"other" ascending: YES]; + s4 = [NSSortDescriptor sortDescriptorWithKey: @"other" ascending: NO]; PASS([s1 hash] == [s2 hash], "hash for similar descriptors is the same"); PASS([s1 isEqual: s2], "similar descriptors are equal"); PASS(![s1 isEqual: s3], "different keyed descriptors are not equal"); diff --git a/Tests/base/NSTask/basic.m b/Tests/base/NSTask/basic.m index a0c2c08652..d7980b64a9 100644 --- a/Tests/base/NSTask/basic.m +++ b/Tests/base/NSTask/basic.m @@ -4,11 +4,11 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSArray *testObj = [NSTask new]; + ENTER_POOL + NSArray *testObj = AUTORELEASE([NSTask new]); - test_NSObject(@"NSTask", [NSArray arrayWithObject:testObj]); + test_NSObject(@"NSTask", [NSArray arrayWithObject: testObj]); - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSURL/basic.m b/Tests/base/NSURL/basic.m index 23a1fc4dfe..5d776d6f28 100644 --- a/Tests/base/NSURL/basic.m +++ b/Tests/base/NSURL/basic.m @@ -20,7 +20,7 @@ int main() unichar u = 163; unichar buf[256]; - TEST_FOR_CLASS(@"NSURL", [NSURL alloc], + TEST_FOR_CLASS(@"NSURL", AUTORELEASE([NSURL alloc]), "NSURL +alloc returns an NSURL"); TEST_FOR_CLASS(@"NSURL", [NSURL fileURLWithPath: @"."], @@ -366,16 +366,18 @@ int main() NSURLQueryItem* item = [[NSURLQueryItem alloc] init]; PASS_EQUAL(item.name, @"", "NSURLQueryItem.name should not be nil"); PASS_EQUAL(item.value, nil, "NSURLQueryItem.value should be nil"); + RELEASE(item); //OSX behavior is to return query item with an empty string name item = [[NSURLQueryItem alloc] initWithName:nil value:nil]; PASS_EQUAL(item.name, @"", "NSURLQueryItem.name should not be nil"); PASS_EQUAL(item.value, nil, "NSURLQueryItem.value should be nil"); + RELEASE(item); item = [[NSURLQueryItem alloc] initWithName:@"myName" value:@"myValue"]; PASS_EQUAL(item.name, @"myName", "NSURLQueryItem.name should not be nil"); PASS_EQUAL(item.value, @"myValue", "NSURLQueryItem.value should not be nil"); - + RELEASE(item); [arp release]; arp = nil; return 0; From 0fb9739f211daa8f8b27524c874cfd70a1fa1fc1 Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 12:55:55 +0000 Subject: [PATCH 31/64] Fix leaks and a possible buffer overrun --- Source/GSFormat.m | 8 +++++++- Tests/base/NSTask/zombie.m | 1 + Tests/base/NSUUID/basic.m | 8 +++++--- Tests/base/NSUserDefaults/basic.m | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Source/GSFormat.m b/Source/GSFormat.m index 23a5874078..5457b90503 100644 --- a/Source/GSFormat.m +++ b/Source/GSFormat.m @@ -1770,7 +1770,13 @@ static int printf_unknown (GSStr, const struct printf_info *, if (-1 == prec) { - len = strlen(str); // Number of bytes to convert. + /* Find end of string, within the specified limit. + */ + len = 0; + while (str[len] != '\0' && len < width) + { + len++; + } blen = len; // Size of unichar output buffer. } else diff --git a/Tests/base/NSTask/zombie.m b/Tests/base/NSTask/zombie.m index fb88c2c5fe..28b69c7ea3 100644 --- a/Tests/base/NSTask/zombie.m +++ b/Tests/base/NSTask/zombie.m @@ -43,6 +43,7 @@ int main() encoding: NSISOLatin1StringEncoding]; PASS(str != nil && [str rangeOfString: @"sent to deallocated"].length > 0, "was able to read zombie message from subtask"); + RELEASE(str); [task terminate]; [arp release]; diff --git a/Tests/base/NSUUID/basic.m b/Tests/base/NSUUID/basic.m index 486a7d9a86..db856fd249 100644 --- a/Tests/base/NSUUID/basic.m +++ b/Tests/base/NSUUID/basic.m @@ -14,7 +14,7 @@ int main(int argc, char **argv) 0x80, 0x1f, 0x3a, 0x01, 0x95, 0x7c, 0x45, 0x0f, 0xaf, 0xf2, 0x1b, 0xe9, 0x59, 0xf5, 0x89, 0x54 }; - TEST_FOR_CLASS(@"NSUUID", [NSUUID alloc], + TEST_FOR_CLASS(@"NSUUID", AUTORELEASE([NSUUID alloc]), "+[NSUUID alloc] returns a NSUUID"); TEST_FOR_CLASS(@"NSUUID", [NSUUID UUID], "+[NSUUID UUID] returns a UUID"); @@ -22,9 +22,11 @@ int main(int argc, char **argv) uuid1 = [[NSUUID alloc] initWithUUIDString: nil]; PASS(uuid1 == nil, "Don't create a UUID from a nil string"); + DESTROY(uuid1); uuid1 = [[NSUUID alloc] initWithUUIDString: @"test"]; PASS(uuid1 == nil, "Don't create a UUID from an invalid string"); + DESTROY(uuid1); uuid1 = [[NSUUID alloc] initWithUUIDString: uuidString]; PASS(uuid1 != nil, "Create a UUID from a valid string"); PASS_EQUAL([uuid1 UUIDString], uuidString, @@ -43,12 +45,12 @@ int main(int argc, char **argv) int comparison = memcmp(uuidBytes, otherBytes, 16); PASS(comparison == 0, "Get a stable value for the UUID bytes"); - DESTROY(uuid2); + DESTROY(uuid2); uuid2 = [uuid1 copy]; PASS_EQUAL(uuid1, uuid2, "-[NSUUID copy] returns an identical object"); + DESTROY(uuid2); - NSData *coded = [NSKeyedArchiver archivedDataWithRootObject: uuid1]; uuid2 = [NSKeyedUnarchiver unarchiveObjectWithData: coded]; PASS_EQUAL(uuid1, uuid2, "UUID survives a round-trip through archiver"); diff --git a/Tests/base/NSUserDefaults/basic.m b/Tests/base/NSUserDefaults/basic.m index 5a46806a45..0f5a8fa888 100644 --- a/Tests/base/NSUserDefaults/basic.m +++ b/Tests/base/NSUserDefaults/basic.m @@ -5,7 +5,7 @@ int main() { NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSUserDefaults *defs = [NSUserDefaults new]; + NSUserDefaults *defs = AUTORELEASE([NSUserDefaults new]); test_NSObject(@"NSUserDefaults", [NSArray arrayWithObject: defs]); From 7cff5fc106a3b47d4012f1739395d16520c67ec3 Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 13:32:31 +0000 Subject: [PATCH 32/64] Fix more leaks --- Source/GSLocale.m | 19 +++++++++++++------ Tests/base/NSXMLDocument/basic.m | 4 ++++ Tests/base/NSXMLParser/basic.m | 2 ++ Tests/base/NSXMLParser/parse.m | 4 ++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Source/GSLocale.m b/Source/GSLocale.m index d52ab8c964..d76b62a56d 100644 --- a/Source/GSLocale.m +++ b/Source/GSLocale.m @@ -24,6 +24,7 @@ #import "common.h" #import "GSPrivate.h" #import "GNUstepBase/GSLocale.h" +#import "Foundation/NSAutoreleasePool.h" #import "Foundation/NSDictionary.h" #import "Foundation/NSArray.h" #import "Foundation/NSLock.h" @@ -262,6 +263,7 @@ || [locale length] < 2) return @"English"; + ENTER_POOL gbundle = [NSBundle bundleForLibrary: @"gnustep-base"]; aliases = [gbundle pathForResource: @"Locale" ofType: @"aliases" @@ -271,22 +273,27 @@ NSDictionary *dict; dict = [NSDictionary dictionaryWithContentsOfFile: aliases]; - language = [dict objectForKey: locale]; + language = [[dict objectForKey: locale] copy]; if (language == nil && [locale pathExtension] != nil) { locale = [locale stringByDeletingPathExtension]; if ([locale isEqual: @"C"] || [locale isEqual: @"POSIX"]) - return @"English"; - language = [dict objectForKey: locale]; + { + language = @"English"; + } + else + { + language = [[dict objectForKey: locale] copy]; + } } if (language == nil) { locale = [locale substringWithRange: NSMakeRange(0, 2)]; - language = [dict objectForKey: locale]; + language = [[dict objectForKey: locale] copy]; } } - - return language; + LEAVE_POOL + return AUTORELEASE(language); } NSArray * diff --git a/Tests/base/NSXMLDocument/basic.m b/Tests/base/NSXMLDocument/basic.m index c16887740f..33edcd8176 100644 --- a/Tests/base/NSXMLDocument/basic.m +++ b/Tests/base/NSXMLDocument/basic.m @@ -74,6 +74,8 @@ int main() PASS_RUNS([node setRootElement: nil], "setting a nil root is ignored"); PASS_EQUAL([node rootElement], elem, "root element remains"); + DESTROY(elem); + DESTROY(node); node = [[NSXMLDocument alloc] initWithXMLString:documentXML options:0 error:NULL]; @@ -96,6 +98,8 @@ int main() error:NULL]; PASS([node isEqual: node2], "Equal documents are equivalent"); + RELEASE(node2); + RELEASE(node); #endif END_SET("NSXMLDocument") diff --git a/Tests/base/NSXMLParser/basic.m b/Tests/base/NSXMLParser/basic.m index d61579263b..82b437afc3 100644 --- a/Tests/base/NSXMLParser/basic.m +++ b/Tests/base/NSXMLParser/basic.m @@ -10,10 +10,12 @@ int main() parser = [c new]; test_alloc(@"GSSloppyXMLParser"); test_NSObject(@"GSSloppyXMLParser", [NSArray arrayWithObject: parser]); + DESTROY(parser); parser = [NSXMLParser new]; test_alloc(@"NSXMLParser"); test_NSObject(@"NSXMLParser", [NSArray arrayWithObject: parser]); + DESTROY(parser); [arp release]; arp = nil; diff --git a/Tests/base/NSXMLParser/parse.m b/Tests/base/NSXMLParser/parse.m index e0dcea52e7..66f5ba7071 100644 --- a/Tests/base/NSXMLParser/parse.m +++ b/Tests/base/NSXMLParser/parse.m @@ -289,7 +289,7 @@ - (void) reset if (Nil == c) c = [NSXMLParser class]; parser = [[c alloc] initWithData: xml]; result = testParser(parser, expect); - + RELEASE(parser); [arp release]; return result; } @@ -315,7 +315,7 @@ - (void) reset if (Nil == c) c = [NSXMLParser class]; parser = [[c alloc] initWithStream: stream]; result = testParser(parser, expect); - + RELEASE(parser); [arp release]; return result; } From 90082eccac3808278f2d4639daa3a1f9a002f6da Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 15:03:22 +0000 Subject: [PATCH 33/64] Revert last change --- Source/GSFormat.m | 8 +------- Tests/base/NSStream/socket.m | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/Source/GSFormat.m b/Source/GSFormat.m index 5457b90503..1dbd01fbb1 100644 --- a/Source/GSFormat.m +++ b/Source/GSFormat.m @@ -1770,13 +1770,7 @@ static int printf_unknown (GSStr, const struct printf_info *, if (-1 == prec) { - /* Find end of string, within the specified limit. - */ - len = 0; - while (str[len] != '\0' && len < width) - { - len++; - } + len = strlen(str); // Number of bytes to convert. blen = len; // Size of unichar output buffer. } else diff --git a/Tests/base/NSStream/socket.m b/Tests/base/NSStream/socket.m index 03f51f22c1..635056cd56 100644 --- a/Tests/base/NSStream/socket.m +++ b/Tests/base/NSStream/socket.m @@ -73,7 +73,7 @@ - (void)stream: (NSStream *)theStream handleEvent: (NSStreamEvent)streamEvent NSLog(@"%@", [defaultInput streamError]); NSAssert([defaultInput streamError]==nil, @"read error"); } - if (readSize == 0) + else if (readSize == 0) { [defaultInput close]; [defaultInput removeFromRunLoop: [NSRunLoop currentRunLoop] From cd3e69245dfcdf050856a433d23306e8d39dc629 Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 16:16:46 +0000 Subject: [PATCH 34/64] More leak management fixes --- Headers/GNUstepBase/NSObject+GNUstepBase.h | 42 +++++------ Source/Additions/NSObject+GNUstepBase.m | 84 ++++++++++++++-------- Source/GSLocale.m | 3 +- Source/NSNull.m | 1 - Source/NSObject.m | 12 ++-- Source/NSURLProtocol.m | 33 +++++++-- Tests/base/NSURLHandle/basic.m | 7 +- Tests/base/NSURLProtocol/basic.m | 7 +- Tests/base/NSURLRequest/basic.m | 7 +- 9 files changed, 118 insertions(+), 78 deletions(-) diff --git a/Headers/GNUstepBase/NSObject+GNUstepBase.h b/Headers/GNUstepBase/NSObject+GNUstepBase.h index ec06173584..649b48b2ed 100644 --- a/Headers/GNUstepBase/NSObject+GNUstepBase.h +++ b/Headers/GNUstepBase/NSObject+GNUstepBase.h @@ -219,9 +219,9 @@ extern "C" { * set to YES).
* Your class then has two options for performing clean-up when the process * ends: - *

1. Use the +leaked: method to register addresses whose contents are to - * be either ignored or released depending on the clean-up setting in force - * when the program exits. + *

1. Use the +leak: at: method to register addresses whose contents are + * to be either ignored or released depending on the clean-up setting in + * force when the program exits. * This mechanism is simple and should be sufficient for many classes. *

*

2. Implement a +atExit method to be run when the process ends and, @@ -241,36 +241,30 @@ extern "C" { */ + (BOOL) isExiting; -/** This method informs the system that anObject should be retained to - * persist until the process exits. If clean-up is enabled the object - * should be released upon process exit. - * If this method is called while the process is already existing it - * returns nil, otherwise it returnes the retained argument. - * Raises an exception if anObject has already been leaked or if it is - * nil (unless the process is exiting). +/** This method stored anObject at anAddress (retaining it) and notes + * that the object should persist until the process exits. If clean-up + * is enabled the object should be released (and the address content + * zeroed out) upon process exit. + * If this method is called while the process is already exiting it + * simply zeros out the memory location then returns nil, otherwise + * it returns the object stored at the memory location. + * Raises an exception if anObject is nil or anAddress is NULL (unless + * the process is already exiting). */ -+ (id) NS_RETURNS_RETAINED leak: (id)anObject; ++ (id) leak: (id)anObject at: (id*)anAddress; -/** This method informs the system that the object at anAddress has been - * retained to persist until the process exits. If clean-up is enabled - * the object should be released (and the address content zeroed out) - * upon process exit. - * If this method is called while the process is already existing it releases - * the object and zeros out the memory location then returns nil, otherwise - * it returns the object found at the memory location. - * Raises an exception if anAddress (or the object at anAddress) has already - * been leaked or if it is nil (unless the process is exiting). +/** DEPRECATED ... use +leak: at: instead. */ -+ (void) leaked: (id*)anAddress; ++ (id) NS_RETURNS_RETAINED leak: (id)anObject; -/** DEPRECATED ... use +leaked: instead. +/** DEPRECATED ... use +leak: at: instead. */ + (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress; /** Sets the receiver to have its +atExit method called at the point when * the process terminates.
* Returns YES on success and NO on failure (if the class does not implement - * the method or if it is already registered to call it).
+ * +atExit or if it is already registered to call it).
* Implemented as a call to +registerAtExit: with the selector for the +atExit * method as its argument. */ @@ -279,7 +273,7 @@ extern "C" { /** Sets the receiver to have the specified method called at the point when * the process terminates.
* Returns YES on success and NO on failure (if the class does not implement - * the method ir if it is already registered to call it). + * the method or if it is already registered to call a method at exit). */ + (BOOL) registerAtExit: (SEL)aSelector; diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m index 0e3c7b21ac..b58aa36669 100644 --- a/Source/Additions/NSObject+GNUstepBase.m +++ b/Source/Additions/NSObject+GNUstepBase.m @@ -180,6 +180,10 @@ static inline void setup() BOOL unknownThread; isExiting = YES; + /* We turn off zombies during exiting so that we don't leak deallocated + * objects during cleanup. + */ +// NSZombieEnabled = NO; unknownThread = GSRegisterCurrentThread(); ENTER_POOL @@ -193,6 +197,7 @@ static inline void setup() Method method; IMP msg; +fprintf(stderr, "*** +[%s %s]\n", class_getName(tmp->obj), sel_getName(tmp->sel)); method = class_getClassMethod(tmp->obj, tmp->sel); msg = method_getImplementation(method); if (0 != msg) @@ -200,13 +205,18 @@ static inline void setup() (*msg)(tmp->obj, tmp->sel); } } - else if (YES == shouldCleanUp) + else if (shouldCleanUp) { if (tmp->at) { - tmp->obj = *(tmp->at); + if (tmp->obj != *(tmp->at)) + { +fprintf(stderr, "*** leaked value %p at %p changed to %p\n", tmp->obj, (const void*)tmp->at, *(tmp->at)); + tmp->obj = *(tmp->at); + } *(tmp->at) = nil; } +fprintf(stderr, "*** -[%s release] %p %p\n", class_getName(object_getClass(tmp->obj)), tmp->obj, (const void*)tmp->at); [tmp->obj release]; } free(tmp); @@ -227,35 +237,22 @@ + (BOOL) isExiting return isExiting; } -+ (id) leakAt: (id*)anAddress -{ - struct exitLink *l; - - l = (struct exitLink*)malloc(sizeof(struct exitLink)); - l->at = anAddress; - l->obj = [*anAddress retain]; - l->sel = 0; - setup(); - [exitLock lock]; - l->next = exited; - exited = l; - [exitLock unlock]; - return l->obj; -} - -+ (void) leaked: (id*)anAddress ++ (id) leak: (id)anObject at: (id*)anAddress { struct exitLink *l; - NSAssert(anAddress != NULL, NSInvalidArgumentException); if (isExiting) { - [*anAddress release]; - *anAddress = nil; + if (anAddress) + { + [*anAddress release]; + *anAddress = nil; + } return nil; } - NSAssert([*anAddress isKindOfClass: [NSObject class]], + NSAssert([anObject isKindOfClass: [NSObject class]], NSInvalidArgumentException); + NSAssert(anAddress != NULL, NSInvalidArgumentException); setup(); [exitLock lock]; for (l = exited; l != NULL; l = l->next) @@ -266,16 +263,17 @@ + (void) leaked: (id*)anAddress [NSException raise: NSInvalidArgumentException format: @"Repeated use of leak address %p", anAddress]; } - if (*anAddress != nil && *anAddress == l->obj) + if (anObject != nil && anObject == l->obj) { [exitLock unlock]; [NSException raise: NSInvalidArgumentException - format: @"Repeated use of leak object %p", *anAddress]; + format: @"Repeated use of leak object %p", anObject]; } } + ASSIGN(*anAddress, anObject); l = (struct exitLink*)malloc(sizeof(struct exitLink)); l->at = anAddress; - l->obj = *anAddress; + l->obj = anObject; l->sel = 0; l->next = exited; exited = l; @@ -283,6 +281,22 @@ + (void) leaked: (id*)anAddress return l->obj; } ++ (id) leakAt: (id*)anAddress +{ + struct exitLink *l; + + l = (struct exitLink*)malloc(sizeof(struct exitLink)); + l->at = anAddress; + l->obj = [*anAddress retain]; + l->sel = 0; + setup(); + [exitLock lock]; + l->next = exited; + exited = l; + [exitLock unlock]; + return l->obj; +} + + (id) leak: (id)anObject { struct exitLink *l; @@ -344,10 +358,16 @@ + (BOOL) registerAtExit: (SEL)sel [exitLock lock]; for (l = exited; l != 0; l = l->next) { - if (l->obj == self && sel_isEqual(l->sel, sel)) + if (l->obj == self) { - [exitLock unlock]; - return NO; // Already registered + if (sel_isEqual(l->sel, sel)) + { + fprintf(stderr, + "*** +[%s registerAtExit: %s] already registered for %s.\n", + class_getName(self), sel_getName(sel), sel_getName(l->sel)); + [exitLock unlock]; + return NO; // Already registered + } } } l = (struct exitLink*)malloc(sizeof(struct exitLink)); @@ -502,6 +522,12 @@ - (NSUInteger) sizeOfInstance */ @implementation NSObject(GSCleanup) ++ (id) leak: (id)anObject at: (id*)anAddress +{ + ASSIGN(*anAddress, anObject); + return *anAddress; +} + + (id) leakAt: (id*)anAddress { [*anAddress retain]; diff --git a/Source/GSLocale.m b/Source/GSLocale.m index d76b62a56d..0868e6f1c0 100644 --- a/Source/GSLocale.m +++ b/Source/GSLocale.m @@ -223,8 +223,7 @@ */ if (saved == nil) { - saved = [dict copy]; - [NSObject leaked: &saved]; + [NSObject leak: AUTORELEASE([dict copy]) at: &saved]; } /** diff --git a/Source/NSNull.m b/Source/NSNull.m index e31dc6326b..bb4b30131b 100644 --- a/Source/NSNull.m +++ b/Source/NSNull.m @@ -48,7 +48,6 @@ + (void) initialize if (null == 0) { null = (NSNull*)NSAllocateObject(self, 0, NSDefaultMallocZone()); - [[NSObject leakAt: &null] release]; } } diff --git a/Source/NSObject.m b/Source/NSObject.m index cd910b7126..cfbb579960 100644 --- a/Source/NSObject.m +++ b/Source/NSObject.m @@ -171,13 +171,13 @@ extern void GSLogZombie(id o, SEL sel) } if (c == 0) { - NSLog(@"*** -[??? %@]: message sent to deallocated instance %p", - NSStringFromSelector(sel), o); + fprintf(stderr, "*** -[??? %s]: message sent to deallocated instance %p", + sel_getName(sel), o); } else { - NSLog(@"*** -[%@ %@]: message sent to deallocated instance %p", - c, NSStringFromSelector(sel), o); + fprintf(stderr, "*** -[%s %s]: message sent to deallocated instance %p", + class_getName(c), sel_getName(sel), o); } if (GSPrivateEnvironmentFlag("CRASH_ON_ZOMBIE", NO) == YES) { @@ -814,7 +814,7 @@ static id retain_fast(id anObject) (*finalize_imp)(anObject, finalize_sel); AREM(aClass, (id)anObject); - if (NSZombieEnabled == YES) + if (NSZombieEnabled) { #ifdef OBJC_CAP_ARC if (0 != zombieMap) @@ -1086,12 +1086,14 @@ + (void) initialize + (void) _atExit { +/* NSMapTable *m = nil; GS_MUTEX_LOCK(allocationLock); m = zombieMap; zombieMap = nil; GS_MUTEX_UNLOCK(allocationLock); DESTROY(m); +*/ } /** diff --git a/Source/NSURLProtocol.m b/Source/NSURLProtocol.m index fd1f8f1d71..956a948734 100644 --- a/Source/NSURLProtocol.m +++ b/Source/NSURLProtocol.m @@ -180,6 +180,13 @@ @implementation GSSocketStreamPair static NSMutableArray *pairCache = nil; static NSLock *pairLock = nil; ++ (void) atExit +{ + [[NSNotificationCenter defaultCenter] removeObserver: self]; + DESTROY(pairLock); + DESTROY(pairCache); +} + + (void) initialize { if (pairCache == nil) @@ -196,6 +203,7 @@ + (void) initialize [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(purge:) name: @"GSHousekeeping" object: nil]; + [self registerAtExit]; } } @@ -468,19 +476,36 @@ + (id) allocWithZone: (NSZone*)z return o; } ++ (void) atExit +{ + if (placeholder) + { + id o = placeholder; + + placeholder = nil; + NSDeallocateObject(o); + } +fprintf(stderr, "Registered retain count %d\n", (int)[registered retainCount]); + DESTROY(registered); + DESTROY(regLock); +} + + (void) initialize { - if (registered == nil) + static BOOL beenHere = NO; + + if (NO == beenHere) { + beenHere = YES; abstractClass = [NSURLProtocol class]; placeholderClass = [NSURLProtocolPlaceholder class]; + + [self registerAtExit]; + placeholder = (NSURLProtocol*)NSAllocateObject(placeholderClass, 0, NSDefaultMallocZone()); - [[NSObject leakAt: &placeholder] release]; registered = [NSMutableArray new]; - [[NSObject leakAt: ®istered] release]; regLock = [NSLock new]; - [[NSObject leakAt: ®Lock] release]; [self registerClass: [_NSHTTPURLProtocol class]]; [self registerClass: [_NSHTTPSURLProtocol class]]; [self registerClass: [_NSFTPURLProtocol class]]; diff --git a/Tests/base/NSURLHandle/basic.m b/Tests/base/NSURLHandle/basic.m index 2fd8d15746..96e56249dd 100644 --- a/Tests/base/NSURLHandle/basic.m +++ b/Tests/base/NSURLHandle/basic.m @@ -18,7 +18,7 @@ int main() httpURL = [NSURL URLWithString: @"http://www.gnustep.org"]; foobarURL = [NSURL URLWithString: @"foobar://localhost/madeupscheme"]; - TEST_FOR_CLASS(@"NSURLHandle", [NSURLHandle alloc], + TEST_FOR_CLASS(@"NSURLHandle", AUTORELEASE([NSURLHandle alloc]), "NSURLHandle +alloc returns an NSURLHandle"); PASS_EXCEPTION([DummyHandle cachedHandleForURL: httpURL];, @@ -29,14 +29,11 @@ int main() PASS([cls canInitWithURL: httpURL] == YES, "Appropriate subclass found for +URLHandleClassForURL:"); - handle1 = [[cls alloc] initWithURL: httpURL cached: YES]; + handle1 = AUTORELEASE([[cls alloc] initWithURL: httpURL cached: YES]); handle2 = [NSURLHandle cachedHandleForURL: httpURL]; PASS(handle2 != nil, "Available handle returned from cache"); - [handle1 autorelease]; - [cls autorelease]; - #if !defined(GNUSTEP_BASE_LIBRARY) PASS(NO, "URLHandleClassForURL: seems to hang on MacOS-X when given an unknown URL scheme ... you may want to check to see if it has been fixed"); #else diff --git a/Tests/base/NSURLProtocol/basic.m b/Tests/base/NSURLProtocol/basic.m index 5ebd6f6c44..3afd6f05ea 100644 --- a/Tests/base/NSURLProtocol/basic.m +++ b/Tests/base/NSURLProtocol/basic.m @@ -11,10 +11,10 @@ int main() httpURL = [NSURL URLWithString: @"http://www.gnustep.org"]; - TEST_FOR_CLASS(@"NSURLProtocol", [NSURLProtocol alloc], + TEST_FOR_CLASS(@"NSURLProtocol", AUTORELEASE([NSURLProtocol alloc]), "NSURLProtocol +alloc returns an NSURLProtocol"); - mutable = [[NSMutableURLRequest requestWithURL: httpURL] retain]; + mutable = [NSMutableURLRequest requestWithURL: httpURL]; PASS_EXCEPTION([NSURLProtocol canInitWithRequest: mutable], nil, "NSURLProtocol +canInitWithRequest throws an exeception (subclasses should be used)"); @@ -22,13 +22,12 @@ int main() TEST_FOR_CLASS(@"NSURLRequest", canon, "NSURLProtocol +canonicalRequestForRequest: returns an NSURLProtocol"); - copy = [mutable copy]; + copy = AUTORELEASE([mutable copy]); PASS([NSURLProtocol requestIsCacheEquivalent: mutable toRequest: copy], "NSURLProtocol +requestIsCacheEquivalent:toRequest returns YES with a request and its copy"); [copy setHTTPMethod: @"POST"]; PASS([NSURLProtocol requestIsCacheEquivalent: mutable toRequest: copy] == NO, "NSURLProtocol +requestIsCacheEquivalent:toRequest returns NO after a method change"); - [copy release]; [arp release]; arp = nil; return 0; diff --git a/Tests/base/NSURLRequest/basic.m b/Tests/base/NSURLRequest/basic.m index 01c1e84f57..11efa966df 100644 --- a/Tests/base/NSURLRequest/basic.m +++ b/Tests/base/NSURLRequest/basic.m @@ -13,7 +13,7 @@ int main() httpURL = [NSURL URLWithString: @"http://www.gnustep.org"]; foobarURL = [NSURL URLWithString: @"foobar://localhost/madeupscheme"]; - TEST_FOR_CLASS(@"NSURLRequest", [NSURLRequest alloc], + TEST_FOR_CLASS(@"NSURLRequest", AUTORELEASE([NSURLRequest alloc]), "NSURLRequest +alloc returns an NSURLRequest"); request = [NSURLRequest requestWithURL: httpURL]; @@ -28,7 +28,7 @@ int main() PASS(request != nil, "NSURLRequest +requestWithURL returns a request from an invalid URL (unknown scheme)"); - mutable = [request mutableCopy]; + mutable = AUTORELEASE([request mutableCopy]); PASS(mutable != nil && [mutable isKindOfClass:[NSMutableURLRequest class]], "NSURLRequest -mutableCopy returns a mutable request"); [mutable setHTTPMethod: @"POST"]; @@ -53,9 +53,8 @@ int main() [mutable setValue: nil forHTTPHeaderField: @"gnustep"]; expected = [NSDictionary dictionaryWithObjectsAndKeys:@"object", @"key", nil]; PASS_EQUAL([mutable allHTTPHeaderFields], expected, "Remove header field"); - [mutable release]; - mutable = [NSMutableURLRequest new]; + mutable = AUTORELEASE([NSMutableURLRequest new]); PASS(mutable != nil && [mutable isKindOfClass:[NSMutableURLRequest class]], "NSURLRequest +new returns a mutable request"); From 65b9b55e01429dcc315fa7bd9e9ffffd9e6ab960 Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 16:31:37 +0000 Subject: [PATCH 35/64] Fix dealloc when init has not been called --- Source/NSURL.m | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/Source/NSURL.m b/Source/NSURL.m index c4c350f1e3..1a90aa1888 100644 --- a/Source/NSURL.m +++ b/Source/NSURL.m @@ -1279,7 +1279,7 @@ - (void) dealloc } DESTROY(_urlString); DESTROY(_baseURL); - [super dealloc]; + DEALLOC } - (id) copyWithZone: (NSZone*)zone @@ -2216,10 +2216,13 @@ - (instancetype) initWithName: (NSString *)name - (void) dealloc { - RELEASE(internal->_name); - RELEASE(internal->_value); - GS_DESTROY_INTERNAL(NSURLQueryItem); - [super dealloc]; + if (GS_EXISTS_INTERNAL) + { + RELEASE(internal->_name); + RELEASE(internal->_value); + GS_DESTROY_INTERNAL(NSURLQueryItem); + } + DEALLOC } // Reading a name and value from a query @@ -2375,17 +2378,20 @@ - (instancetype) initWithURL: (NSURL *)url - (void) dealloc { - RELEASE(internal->_string); - RELEASE(internal->_fragment); - RELEASE(internal->_host); - RELEASE(internal->_password); - RELEASE(internal->_path); - RELEASE(internal->_port); - RELEASE(internal->_queryItems); - RELEASE(internal->_scheme); - RELEASE(internal->_user); - GS_DESTROY_INTERNAL(NSURLComponents); - [super dealloc]; + if (GS_EXISTS_INTERNAL) + { + RELEASE(internal->_string); + RELEASE(internal->_fragment); + RELEASE(internal->_host); + RELEASE(internal->_password); + RELEASE(internal->_path); + RELEASE(internal->_port); + RELEASE(internal->_queryItems); + RELEASE(internal->_scheme); + RELEASE(internal->_user); + GS_DESTROY_INTERNAL(NSURLComponents); + } + DEALLOC } - (id) copyWithZone: (NSZone *)zone From 6a723e5a87ea754c02f5229973915230d76ac688 Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 16:41:59 +0000 Subject: [PATCH 36/64] Fixes for dealloc when init has not been called. --- Source/Additions/GSMime.m | 2 +- Source/NSConnection.m | 2 +- Source/NSDateFormatter.m | 2 +- Source/NSNumberFormatter.m | 2 +- Source/NSOperation.m | 19 +++++++++++-------- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Source/Additions/GSMime.m b/Source/Additions/GSMime.m index 9c69887c8b..1c7dfc140e 100644 --- a/Source/Additions/GSMime.m +++ b/Source/Additions/GSMime.m @@ -8440,7 +8440,7 @@ - (void) abort - (void) dealloc { [self abort]; - if (internal != nil) + if (GS_EXISTS_INTERNAL) { DESTROY(internal->reply); DESTROY(internal->wdata); diff --git a/Source/NSConnection.m b/Source/NSConnection.m index 590ff19869..de9fd966c2 100644 --- a/Source/NSConnection.m +++ b/Source/NSConnection.m @@ -857,7 +857,7 @@ - (void) dealloc if (debug_connection) NSLog(@"deallocating %@", self); [self finalize]; - if (internal != nil) + if (GS_EXISTS_INTERNAL) { GS_DESTROY_INTERNAL(NSConnection); } diff --git a/Source/NSDateFormatter.m b/Source/NSDateFormatter.m index 46ac499c5a..4651a1a711 100644 --- a/Source/NSDateFormatter.m +++ b/Source/NSDateFormatter.m @@ -155,7 +155,7 @@ - (NSString*) dateFormat - (void) dealloc { RELEASE(_dateFormat); - if (internal != 0) + if (GS_EXISTS_INTERNAL) { RELEASE(internal->_locale); RELEASE(internal->_tz); diff --git a/Source/NSNumberFormatter.m b/Source/NSNumberFormatter.m index 9f24889769..710924d2ce 100644 --- a/Source/NSNumberFormatter.m +++ b/Source/NSNumberFormatter.m @@ -559,7 +559,7 @@ - (void) dealloc RELEASE(_attributedStringForNil); RELEASE(_attributedStringForNotANumber); RELEASE(_attributedStringForZero); - if (internal != 0) + if (GS_EXISTS_INTERNAL) { int idx; diff --git a/Source/NSOperation.m b/Source/NSOperation.m index fb7584a4be..08590329af 100644 --- a/Source/NSOperation.m +++ b/Source/NSOperation.m @@ -193,7 +193,7 @@ - (void) dealloc { /* Only clean up if ivars have been initialised */ - if (internal && internal->lock) + if (GS_EXISTS_INTERNAL) { NSOperation *op; @@ -800,13 +800,16 @@ - (void) cancelAllOperations - (void) dealloc { [self cancelAllOperations]; - DESTROY(internal->operations); - DESTROY(internal->starting); - DESTROY(internal->waiting); - DESTROY(internal->name); - DESTROY(internal->cond); - DESTROY(internal->lock); - GS_DESTROY_INTERNAL(NSOperationQueue); + if (GS_EXISTS_INTERNAL) + { + DESTROY(internal->operations); + DESTROY(internal->starting); + DESTROY(internal->waiting); + DESTROY(internal->name); + DESTROY(internal->cond); + DESTROY(internal->lock); + GS_DESTROY_INTERNAL(NSOperationQueue); + } [super dealloc]; } From 75049ec22e244501bd4ad4e430db0f947c5f3893 Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 16:50:16 +0000 Subject: [PATCH 37/64] Replace lost check --- Source/NSOperation.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/NSOperation.m b/Source/NSOperation.m index 08590329af..c16d33c3d6 100644 --- a/Source/NSOperation.m +++ b/Source/NSOperation.m @@ -800,7 +800,7 @@ - (void) cancelAllOperations - (void) dealloc { [self cancelAllOperations]; - if (GS_EXISTS_INTERNAL) + if (GS_EXISTS_INTERNAL && internal->lock != nil) { DESTROY(internal->operations); DESTROY(internal->starting); From f12eabad50ebede855ee8a41ad11abb5d20c9abd Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 16:55:54 +0000 Subject: [PATCH 38/64] Fixup for dealloc of uninitialised instances --- Source/NSOperation.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/NSOperation.m b/Source/NSOperation.m index c16d33c3d6..b92e0e6a9c 100644 --- a/Source/NSOperation.m +++ b/Source/NSOperation.m @@ -193,7 +193,7 @@ - (void) dealloc { /* Only clean up if ivars have been initialised */ - if (GS_EXISTS_INTERNAL) + if (GS_EXISTS_INTERNAL && internal->lock != nil) { NSOperation *op; @@ -211,7 +211,7 @@ - (void) dealloc RELEASE(internal->completionBlock); GS_DESTROY_INTERNAL(NSOperation); } - [super dealloc]; + DEALLOC } - (NSArray *) dependencies @@ -568,7 +568,7 @@ - (void) addExecutionBlock: (GSBlockOperationBlock)block - (void) dealloc { RELEASE(_executionBlocks); - [super dealloc]; + DEALLOC } - (NSArray *) executionBlocks @@ -810,7 +810,7 @@ - (void) dealloc DESTROY(internal->lock); GS_DESTROY_INTERNAL(NSOperationQueue); } - [super dealloc]; + DEALLOC } - (id) init From 598236d3ef164e20574ffcd1b3aae9da8e628473 Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 17:01:19 +0000 Subject: [PATCH 39/64] prevent re-initialize --- Source/NSTimeZone.m | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/NSTimeZone.m b/Source/NSTimeZone.m index e7066e4e7c..7fda8d20bf 100644 --- a/Source/NSTimeZone.m +++ b/Source/NSTimeZone.m @@ -642,8 +642,11 @@ @implementation GSAbsTimeZone + (void) initialize { - if (self == [GSAbsTimeZone class]) + static BOOL beenHere = NO; + + if (NO == beenHere && self == [GSAbsTimeZone class]) { + beenHere = YES; absolutes = NSCreateMapTable(NSIntegerMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0); } @@ -1340,8 +1343,11 @@ + (NSTimeZone*) defaultTimeZone + (void) initialize { - if (self == [NSTimeZone class]) + static BOOL beenHere = NO; + + if (NO == beenHere && self == [NSTimeZone class]) { + beenHere = YES; NSTimeZoneClass = self; GS_MUTEX_INIT_RECURSIVE(zone_mutex); GSPlaceholderTimeZoneClass = [GSPlaceholderTimeZone class]; From 2c9e5217894e279b9716355da764c7906e367e6f Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 19:30:36 +0000 Subject: [PATCH 40/64] allow more time for slow tests --- Tests/base/NSURL/TestInfo | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/base/NSURL/TestInfo b/Tests/base/NSURL/TestInfo index e69de29bb2..79881f31de 100644 --- a/Tests/base/NSURL/TestInfo +++ b/Tests/base/NSURL/TestInfo @@ -0,0 +1 @@ +export GSTESTTIMEOUT=120 From 9e504da2df5bcefbdb8cf7983a784705636ee25c Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 20:50:17 +0000 Subject: [PATCH 41/64] Don't have the subtask crash when logging zombie message. --- Tests/base/NSTask/zombie.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Tests/base/NSTask/zombie.m b/Tests/base/NSTask/zombie.m index 28b69c7ea3..a55a78f3df 100644 --- a/Tests/base/NSTask/zombie.m +++ b/Tests/base/NSTask/zombie.m @@ -9,8 +9,8 @@ int main() { - NSTask *task; - NSPipe *outPipe; + NSTask *task; + NSPipe *outPipe; NSFileManager *mgr; NSString *helpers; NSFileHandle *outHandle; @@ -28,6 +28,7 @@ int main() env = [[[NSProcessInfo processInfo] environment] mutableCopy]; [env setObject: @"YES" forKey: @"NSZombieEnabled"]; + [env setObject: @"NO" forKey: @"CRASH_ON_ZOMBIE"]; task = [[NSTask alloc] init]; outPipe = [[NSPipe pipe] retain]; [task setLaunchPath: [helpers stringByAppendingPathComponent: @"NSZombie"]]; From 42fa1bf04a6970da1058e2dee4d0c4afa16c1151 Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 20:57:04 +0000 Subject: [PATCH 42/64] Protect against dealloc without init --- Source/NSConnection.m | 2 +- Source/NSOperation.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/NSConnection.m b/Source/NSConnection.m index de9fd966c2..fac103e8e1 100644 --- a/Source/NSConnection.m +++ b/Source/NSConnection.m @@ -856,9 +856,9 @@ - (void) dealloc { if (debug_connection) NSLog(@"deallocating %@", self); - [self finalize]; if (GS_EXISTS_INTERNAL) { + [self finalize]; GS_DESTROY_INTERNAL(NSConnection); } [super dealloc]; diff --git a/Source/NSOperation.m b/Source/NSOperation.m index b92e0e6a9c..a58a1621dd 100644 --- a/Source/NSOperation.m +++ b/Source/NSOperation.m @@ -799,9 +799,9 @@ - (void) cancelAllOperations - (void) dealloc { - [self cancelAllOperations]; if (GS_EXISTS_INTERNAL && internal->lock != nil) { + [self cancelAllOperations]; DESTROY(internal->operations); DESTROY(internal->starting); DESTROY(internal->waiting); From 96bbc05b18a482ca573c7326528af06d8f893ddb Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 21:41:43 +0000 Subject: [PATCH 43/64] More leak fixups --- Source/NSURLConnection.m | 2 ++ Source/NSURLProtocol.m | 12 ++++++------ Source/NSUserDefaults.m | 5 ++++- Tests/base/NSTimeZone/basic.m | 8 ++++---- Tests/base/NSTimeZone/create.m | 1 - Tests/base/NSURLConnection/basic.m | 2 +- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Source/NSURLConnection.m b/Source/NSURLConnection.m index b980f20d25..c7ae04cb9f 100644 --- a/Source/NSURLConnection.m +++ b/Source/NSURLConnection.m @@ -431,6 +431,7 @@ - (void) URLProtocol: (NSURLProtocol *)protocol this->_delegate = nil; [o connection: self didFailWithError: error]; DESTROY(o); + DESTROY(this->_protocol); } - (void) URLProtocol: (NSURLProtocol *)protocol @@ -510,6 +511,7 @@ - (void) URLProtocolDidFinishLoading: (NSURLProtocol *)protocol this->_delegate = nil; [o connectionDidFinishLoading: self]; DESTROY(o); + DESTROY(this->_protocol); } - (void) URLProtocol: (NSURLProtocol *)protocol diff --git a/Source/NSURLProtocol.m b/Source/NSURLProtocol.m index 956a948734..a4f076d4fd 100644 --- a/Source/NSURLProtocol.m +++ b/Source/NSURLProtocol.m @@ -572,9 +572,9 @@ - (void) dealloc [this->output close]; DESTROY(this->input); DESTROY(this->output); - DESTROY(this->in); - DESTROY(this->out); } + DESTROY(this->in); + DESTROY(this->out); DESTROY(this->cachedResponse); DESTROY(this->request); #if GS_HAVE_NSURLSESSION @@ -1769,18 +1769,18 @@ - (void) stream: (NSStream*)stream handleEvent: (NSStreamEvent)event { NSLog(@"%@ HTTP output stream opened", self); } - this->in = [[NSString alloc] - initWithFormat: @"(%@:%@ <-- %@:%@)", + s = [NSString stringWithFormat: @"(%@:%@ <-- %@:%@)", [stream propertyForKey: GSStreamLocalAddressKey], [stream propertyForKey: GSStreamLocalPortKey], [stream propertyForKey: GSStreamRemoteAddressKey], [stream propertyForKey: GSStreamRemotePortKey]]; - this->out = [[NSString alloc] - initWithFormat: @"(%@:%@ --> %@:%@)", + ASSIGN(this->in, s); + s = [NSString stringWithFormat: @"(%@:%@ --> %@:%@)", [stream propertyForKey: GSStreamLocalAddressKey], [stream propertyForKey: GSStreamLocalPortKey], [stream propertyForKey: GSStreamRemoteAddressKey], [stream propertyForKey: GSStreamRemotePortKey]]; + ASSIGN(this->out, s); DESTROY(_writeData); DESTROY(_masked); _writeOffset = 0; diff --git a/Source/NSUserDefaults.m b/Source/NSUserDefaults.m index 0913bc8e35..348e2d19ab 100644 --- a/Source/NSUserDefaults.m +++ b/Source/NSUserDefaults.m @@ -685,13 +685,16 @@ + (BOOL) automaticallyNotifiesObserversForKey: (NSString*)key + (void) initialize { - if (self == [NSUserDefaults class]) + static BOOL beenHere = NO; + + if (NO == beenHere && self == [NSUserDefaults class]) { ENTER_POOL NSEnumerator *enumerator; NSArray *args; NSString *key; + beenHere = YES; nextObjectSel = @selector(nextObject); objectForKeySel = @selector(objectForKey:); addSel = @selector(addEntriesFromDictionary:); diff --git a/Tests/base/NSTimeZone/basic.m b/Tests/base/NSTimeZone/basic.m index 700bf1ea3e..cbe52b2030 100644 --- a/Tests/base/NSTimeZone/basic.m +++ b/Tests/base/NSTimeZone/basic.m @@ -4,11 +4,11 @@ int main() { - NSAutoreleasePool *arp = [NSAutoreleasePool new]; - NSArray *testObj = [NSTimeZone defaultTimeZone]; + ENTER_POOL + NSTimeZone *testObj = [NSTimeZone defaultTimeZone]; - test_NSObject(@"NSTimeZone", [NSArray arrayWithObject:testObj]); + test_NSObject(@"NSTimeZone", [NSArray arrayWithObject: testObj]); - [arp release]; arp = nil; + LEAVE_POOL return 0; } diff --git a/Tests/base/NSTimeZone/create.m b/Tests/base/NSTimeZone/create.m index e88059fde7..4cad61ed0e 100644 --- a/Tests/base/NSTimeZone/create.m +++ b/Tests/base/NSTimeZone/create.m @@ -6,7 +6,6 @@ int main() { NSAutoreleasePool *arp = [NSAutoreleasePool new]; id current; - id localh; current = [NSTimeZone defaultTimeZone]; PASS(current != nil && [current isKindOfClass: [NSTimeZone class]], diff --git a/Tests/base/NSURLConnection/basic.m b/Tests/base/NSURLConnection/basic.m index c1fa78441e..0328497522 100644 --- a/Tests/base/NSURLConnection/basic.m +++ b/Tests/base/NSURLConnection/basic.m @@ -16,7 +16,7 @@ int main() httpURL = [NSURL URLWithString: @"http://www.gnustep.org"]; - TEST_FOR_CLASS(@"NSURLConnection", [NSURLConnection alloc], + TEST_FOR_CLASS(@"NSURLConnection", AUTORELEASE([NSURLConnection alloc]), "NSURLConnection +alloc returns an NSURLConnection"); mutable = [NSMutableURLRequest requestWithURL: httpURL]; From 240df48ec84bd15f91166cc9eed8b7ef0123c08f Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 18 Nov 2024 09:19:04 +0000 Subject: [PATCH 44/64] Avoid deadlock in cleanup functions/methods called by atexit() --- Tests/base/NSObject/initialize.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/base/NSObject/initialize.m b/Tests/base/NSObject/initialize.m index 3d766cbb4f..d7190f9469 100644 --- a/Tests/base/NSObject/initialize.m +++ b/Tests/base/NSObject/initialize.m @@ -160,7 +160,7 @@ + (void) mutual2: (id)ignored */ testHopeful = YES; PASS(0, "+initialize mutually dependent methods work"); - exit(0); + _exit(0); // Use _exit() to avoid deadlocking in atexit() } static void @@ -170,7 +170,7 @@ + (void) mutual2: (id)ignored */ testHopeful = YES; PASS(0, "+initialize runs concurrently"); - exit(0); + _exit(0); // Use _exit() to avoid deadlocking in atexit() } /** From 67eeb932d132357323ed20a6c5787f0a2cb94a0b Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 18 Nov 2024 14:33:52 +0000 Subject: [PATCH 45/64] Add tests for class and protocol lists --- Tests/base/Functions/runtime.m | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/Tests/base/Functions/runtime.m b/Tests/base/Functions/runtime.m index cc858f5989..58a29d22c0 100644 --- a/Tests/base/Functions/runtime.m +++ b/Tests/base/Functions/runtime.m @@ -94,6 +94,8 @@ - (const char *) sel2 const char *t0; const char *t1; const char *n; + unsigned u; + int i; t0 = "1@1:@"; t1 = NSGetSizeAndAlignment(t0, &s, &a); @@ -151,6 +153,55 @@ - (const char *) sel2 ivar = class_getInstanceVariable(cls, "ivar1obj"); PASS(ivar != 0, "class_getInstanceVariable() works for superclass obj ivar"); + + i = objc_getClassList(NULL, 0); + PASS(i > 2, "class list contains a reasonable number of classes"); + if (i > 2) + { + int classCount = i; + Class buf[classCount]; + BOOL foundClass = NO; + BOOL foundSubClass = NO; + + i = objc_getClassList(buf, classCount); + PASS(i == classCount, "retrieved all classes") + for (i = 0; i < classCount; i++) + { + n = class_getName(buf[i]); + if (n) + { + if (strcmp(n, "Class1") == 0) + { + foundClass = YES; + } + else if (strcmp(n, "SubClass1") == 0) + { + foundSubClass = YES; + } + } + } + PASS(foundClass && foundSubClass, "found classes in list") + } + + u = 0; + protocols = objc_copyProtocolList(&u); + PASS(protocols && u, "we copied some protocols") + if (protocols) + { + BOOL found = NO; + + for (i = 0; i < u; i++) + { + n = protocol_getName(protocols[i]); + if (strcmp(n, "SubProto") == 0) + { + found = YES; + } + } + free(protocols); + PASS(found, "we found our protocol in list") + } + methods = class_copyMethodList(cls, &count); PASS(count == 3, "SubClass1 has three methods"); PASS(methods[count] == 0, "method list is terminated"); From eeff6e08a71dfaacc47fafd562609fb85492c174 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 18 Nov 2024 15:34:53 +0000 Subject: [PATCH 46/64] Correct the creation of the hash table used for absolute time zones. --- Source/NSTimeZone.m | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/Source/NSTimeZone.m b/Source/NSTimeZone.m index 7fda8d20bf..df15cf07f8 100644 --- a/Source/NSTimeZone.m +++ b/Source/NSTimeZone.m @@ -225,6 +225,7 @@ Default place for the NSTimeZone directory is _time_zone_path(): static GSPlaceholderTimeZone *defaultPlaceholderTimeZone; static NSMapTable *placeholderMap; static GSAbsTimeZone *commonAbsolutes[145] = { 0 }; +static NSMapTable *absolutes = 0; /* * Temporary structure for holding time zone details. @@ -638,19 +639,6 @@ - (NSString*) timeZoneName @implementation GSAbsTimeZone static int uninitialisedOffset = 100000; -static NSMapTable *absolutes = 0; - -+ (void) initialize -{ - static BOOL beenHere = NO; - - if (NO == beenHere && self == [GSAbsTimeZone class]) - { - beenHere = YES; - absolutes = NSCreateMapTable(NSIntegerMapKeyCallBacks, - NSNonOwnedPointerMapValueCallBacks, 0); - } -} - (NSString*) abbreviationForDate: (NSDate*)aDate { @@ -1353,14 +1341,18 @@ + (void) initialize GSPlaceholderTimeZoneClass = [GSPlaceholderTimeZone class]; zoneDictionary = [[NSMutableDictionary alloc] init]; - /* - * Set up infrastructure for placeholder timezones. + /* Set up infrastructure for placeholder timezones. */ defaultPlaceholderTimeZone = (GSPlaceholderTimeZone*) NSAllocateObject(GSPlaceholderTimeZoneClass, 0, NSDefaultMallocZone()); placeholderMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 0); + /* Hash table lookup for absolute time zones. + */ + absolutes = NSCreateMapTable(NSIntegerMapKeyCallBacks, + NSNonOwnedPointerMapValueCallBacks, 0); + localTimeZone = [[NSLocalTimeZone alloc] init]; [[NSNotificationCenter defaultCenter] addObserver: self From 9207ab856fc9fa6b109978376910e55d13a05125 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 18 Nov 2024 17:15:11 +0000 Subject: [PATCH 47/64] Fix leak when absolute time zones are stored in the name dictionary --- Source/NSTimeZone.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/NSTimeZone.m b/Source/NSTimeZone.m index df15cf07f8..3cccab85e8 100644 --- a/Source/NSTimeZone.m +++ b/Source/NSTimeZone.m @@ -748,6 +748,7 @@ - (id) initWithOffset: (NSInteger)anOffset name: (NSString*)aName z = self; NSMapInsert(absolutes, (void*)(uintptr_t)anOffset, (void*)z); [zoneDictionary setObject: self forKey: (NSString*)name]; + RELEASE(self); } if (anOffset % 900 == 0) { @@ -755,7 +756,7 @@ - (id) initWithOffset: (NSInteger)anOffset name: (NSString*)aName if (nil == commonAbsolutes[index]) { - commonAbsolutes[index] = RETAIN(self); + commonAbsolutes[index] = RETAIN(z); } } GS_MUTEX_UNLOCK(zone_mutex); From bb4bcaff9de66ed09b9623c538bbe0e2736ce1f3 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 18 Nov 2024 19:17:16 +0000 Subject: [PATCH 48/64] Fix leak --- Tests/base/NSKVOSupport/general.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/base/NSKVOSupport/general.m b/Tests/base/NSKVOSupport/general.m index c9080f2223..e69ac332e9 100644 --- a/Tests/base/NSKVOSupport/general.m +++ b/Tests/base/NSKVOSupport/general.m @@ -244,6 +244,7 @@ - (NSInteger)numberOfObservedChanges - (void) dealloc { [_lock release]; [_changedKeypaths release]; + DEALLOC } @end From e782157ad7b816c533b11599712230288e8c3d80 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 18 Nov 2024 22:18:45 +0000 Subject: [PATCH 49/64] Fix buffer overflow --- Tools/AGSOutput.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/AGSOutput.m b/Tools/AGSOutput.m index 1c69f6ea6a..ead243f55a 100644 --- a/Tools/AGSOutput.m +++ b/Tools/AGSOutput.m @@ -1632,7 +1632,7 @@ - (NSArray*) split: (NSString*)str unsigned len = optr - buf; unichar c[len + 1]; - memcpy(c, buf, (len+1)*sizeof(unichar)); + memcpy(c, buf, len*sizeof(unichar)); c[len-2] = ' '; c[len-1] = '/'; c[len] = '>'; From 7287f767802bd17e30ca4f00a9014520aab62b62 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 16 Nov 2024 06:50:58 -0500 Subject: [PATCH 50/64] Add NSUnit documentation --- Headers/Foundation/NSUnit.h | 682 ++++++++++++++++++++++++++++++++---- 1 file changed, 616 insertions(+), 66 deletions(-) diff --git a/Headers/Foundation/NSUnit.h b/Headers/Foundation/NSUnit.h index ba890b3d73..273758ed84 100644 --- a/Headers/Foundation/NSUnit.h +++ b/Headers/Foundation/NSUnit.h @@ -32,14 +32,18 @@ extern "C" { #endif -// Unit converter +/** + * Unit converter + */ GS_EXPORT_CLASS @interface NSUnitConverter : NSObject - (double) baseUnitValueFromValue: (double)value; - (double) valueFromBaseUnitValue: (double)baseUnitValue; @end -// Linea converter... for things like C <-> F conversion... +/** + * Linear converter... for things like C to F conversion... + */ GS_EXPORT_CLASS @interface NSUnitConverterLinear : NSUnitConverter { @@ -53,7 +57,9 @@ GS_EXPORT_CLASS - (double) constant; @end -// Units... abstract... +/** + * Units... abstract... + */ GS_EXPORT_CLASS @interface NSUnit : NSObject { @@ -66,7 +72,9 @@ GS_EXPORT_CLASS @end -// Dimension using units.... +/** + * Dimension using units.... + */ GS_EXPORT_CLASS @interface NSDimension : NSUnit { @@ -81,22 +89,22 @@ GS_EXPORT_CLASS @end // Predefined.... +/** + * Base unit - metersPerSecondSquared + */ GS_EXPORT_CLASS @interface NSUnitAcceleration : NSDimension -/* - Base unit - metersPerSecondSquared - */ + (NSUnitAcceleration *) metersPerSecondSquared; + (NSUnitAcceleration *) gravity; @end +/** + * Base unit - degrees + */ GS_EXPORT_CLASS @interface NSUnitAngle : NSDimension -/* - Base unit - degrees - */ + (NSUnitAngle *) degrees; + (NSUnitAngle *) arcMinutes; @@ -107,11 +115,11 @@ GS_EXPORT_CLASS @end +/** + * Base unit - squareMeters + */ GS_EXPORT_CLASS @interface NSUnitArea : NSDimension -/* - Base unit - squareMeters - */ + (NSUnitArea *) squareMegameters; + (NSUnitArea *) squareKilometers; @@ -130,11 +138,11 @@ GS_EXPORT_CLASS @end +/** + * Base unit - gramsPerLiter + */ GS_EXPORT_CLASS @interface NSUnitConcentrationMass : NSDimension -/* - Base unit - gramsPerLiter - */ + (NSUnitConcentrationMass *) gramsPerLiter; + (NSUnitConcentrationMass *) milligramsPerDeciliter; @@ -143,293 +151,835 @@ GS_EXPORT_CLASS @end +/** + * Units of dispersion. Base unit - partsPerMillion + */ GS_EXPORT_CLASS @interface NSUnitDispersion : NSDimension -/* - Base unit - partsPerMillion + +/** + * Units of dispersion in parts per million. */ + (NSUnitDispersion *) partsPerMillion; @end +/** + * Units of duration. Base unit - seconds + */ GS_EXPORT_CLASS @interface NSUnitDuration : NSDimension -/* - Base unit - seconds - */ +/** + * Units of during in seconds. + */ + (NSUnitDuration *) seconds; + +/** + * Units of during in minutes. + */ + (NSUnitDuration *) minutes; + +/** + * Units of during in hours. + */ + (NSUnitDuration *) hours; @end +/** + * Units of electric charge. Base unit - coulombs + */ GS_EXPORT_CLASS @interface NSUnitElectricCharge : NSDimension -/* - Base unit - coulombs - */ +/** + * The units of eletric charge in coulombs. + */ + (NSUnitElectricCharge *) coulombs; + +/** + * The units of eletric charge in megaampere hours. + */ + (NSUnitElectricCharge *) megaampereHours; + +/** + * The units of eletric charge in kiloampere hours. + */ + (NSUnitElectricCharge *) kiloampereHours; + +/** + * The units of eletric charge in ampere hours. + */ + (NSUnitElectricCharge *) ampereHours; + +/** + * The units of eletric charge in milliampere hours. + */ + (NSUnitElectricCharge *) milliampereHours; + +/** + * The units of eletric charge in microampere hours. + */ + (NSUnitElectricCharge *) microampereHours; @end +/** + * Units of electric current. Base unit - amperes + */ GS_EXPORT_CLASS @interface NSUnitElectricCurrent : NSDimension -/* - Base unit - amperes - */ +/** + * The units of eletric current in megaamperes. + */ + (NSUnitElectricCurrent *) megaamperes; + +/** + * The units of eletric current in kiloamperes. + */ + (NSUnitElectricCurrent *) kiloamperes; + +/** + * The units of eletric current in amperes. + */ + (NSUnitElectricCurrent *) amperes; + +/** + * The units of eletric current in milliamperes. + */ + (NSUnitElectricCurrent *) milliamperes; + +/** + * The units of eletric current in microamperes. + */ + (NSUnitElectricCurrent *) microamperes; @end +/** + * Units of electric potential. Base unit - volts + */ GS_EXPORT_CLASS @interface NSUnitElectricPotentialDifference : NSDimension -/* - Base unit - volts - */ +/** + * The units of eletric potential in megavolts. + */ + (NSUnitElectricPotentialDifference *) megavolts; + +/** + * The units of eletric potential in kilovolts. + */ + (NSUnitElectricPotentialDifference *) kilovolts; + +/** + * The units of eletric potential in volts. + */ + (NSUnitElectricPotentialDifference *) volts; + +/** + * The units of eletric potential in millivolts. + */ + (NSUnitElectricPotentialDifference *) millivolts; + +/** + * The units of eletric potential in microvolts. + */ + (NSUnitElectricPotentialDifference *) microvolts; @end +/** + * Units of electric resistance. Base unit - ohms + */ GS_EXPORT_CLASS @interface NSUnitElectricResistance : NSDimension -/* - Base unit - ohms - */ +/** + * The units of eletric resistance in megaohms. + */ + (NSUnitElectricResistance *) megaohms; + +/** + * The units of eletric resistance in kiloohms. + */ + (NSUnitElectricResistance *) kiloohms; + +/** + * The units of eletric resistance in ohms. + */ + (NSUnitElectricResistance *) ohms; + +/** + * The units of eletric resistance in milliohms. + */ + (NSUnitElectricResistance *) milliohms; + +/** + * The units of eletric resistance in microohms. + */ + (NSUnitElectricResistance *) microohms; @end +/** + * Units of Energy. Base unit - joules + */ GS_EXPORT_CLASS @interface NSUnitEnergy : NSDimension -/* - Base unit - joules - */ +/** + * The units of energy in kilojoules. + */ + (NSUnitEnergy *) kilojoules; + +/** + * The units of energy in joules. + */ + (NSUnitEnergy *) joules; + +/** + * The units of energy in kilocalories. + */ + (NSUnitEnergy *) kilocalories; + +/** + * The units of energy in calories. + */ + (NSUnitEnergy *) calories; + +/** + * The units of energy in kilawatt hours. + */ + (NSUnitEnergy *) kilowattHours; @end +/** + * Units of frequency. Base unit - hertz + */ GS_EXPORT_CLASS @interface NSUnitFrequency : NSDimension -/* - Base unit - hertz - */ +/** + * The units of frequency in terahertz. + */ + (NSUnitFrequency *) terahertz; + +/** + * The units of frequency in gigahertz. + */ + (NSUnitFrequency *) gigahertz; + +/** + * The units of frequency in megahertz. + */ + (NSUnitFrequency *) megahertz; + +/** + * The units of frequency in kilohertz. + */ + (NSUnitFrequency *) kilohertz; + +/** + * The units of frequency in hertz. + */ + (NSUnitFrequency *) hertz; + +/** + * The units of frequency in millihertz. + */ + (NSUnitFrequency *) millihertz; + +/** + * The units of frequency in microhertz. + */ + (NSUnitFrequency *) microhertz; + +/** + * The units of frequency in nanohertz. + */ + (NSUnitFrequency *) nanohertz; @end +/** + * Units of fuel efficiency. Base unit - litersPer100Kilometers + */ GS_EXPORT_CLASS @interface NSUnitFuelEfficiency : NSDimension -/* - Base unit - litersPer100Kilometers - */ +/** + * The units of fuel efficiency in liters per 100 kilometers. + */ + (NSUnitFuelEfficiency *) litersPer100Kilometers; + +/** + * The units of fuel efficiency in miles per imperial gallon. + */ + (NSUnitFuelEfficiency *) milesPerImperialGallon; + +/** + * The units of fuel efficiency in miles per gallon. + */ + (NSUnitFuelEfficiency *) milesPerGallon; @end +/** + * Units of length. Base unit - meters + */ GS_EXPORT_CLASS @interface NSUnitLength : NSDimension -/* - Base unit - meters - */ +/** + * The units of length in megameters. + */ + (NSUnitLength *) megameters; + +/** + * The units of length in kilometers. + */ + (NSUnitLength *) kilometers; + +/** + * The units of length in hectometers. + */ + (NSUnitLength *) hectometers; + +/** + * The units of length in decameters. + */ + (NSUnitLength *) decameters; + +/** + * The units of length in meters. + */ + (NSUnitLength *) meters; + +/** + * The units of length in decimeters. + */ + (NSUnitLength *) decimeters; + +/** + * The units of length in centimeters. + */ + (NSUnitLength *) centimeters; + +/** + * The units of length in millimeters. + */ + (NSUnitLength *) millimeters; + +/** + * The units of length in micrometers. + */ + (NSUnitLength *) micrometers; + +/** + * The units of length in nanometers. + */ + (NSUnitLength *) nanometers; + +/** + * The units of length in picometers. + */ + (NSUnitLength *) picometers; + +/** + * The units of length in inches. + */ + (NSUnitLength *) inches; + +/** + * The units of length in feet. + */ + (NSUnitLength *) feet; + +/** + * The units of length in yards. + */ + (NSUnitLength *) yards; + +/** + * The units of length in miles. + */ + (NSUnitLength *) miles; + +/** + * The units of length in scandanavian miles. + */ + (NSUnitLength *) scandinavianMiles; + +/** + * The units of length in light years. + */ + (NSUnitLength *) lightyears; + +/** + * The units of length in nautical miles. + */ + (NSUnitLength *) nauticalMiles; + +/** + * The units of length in fathoms. + */ + (NSUnitLength *) fathoms; + +/** + * The units of length in furlongs. + */ + (NSUnitLength *) furlongs; + +/** + * The units of length in astronomical units. + */ + (NSUnitLength *) astronomicalUnits; + +/** + * The units of length in parsecs. + */ + (NSUnitLength *) parsecs; @end +/** + * Units of illumination. Base unit - lux + */ GS_EXPORT_CLASS @interface NSUnitIlluminance : NSDimension -/* - Base unit - lux - */ +/** + * The units of illuminance in lux. + */ + (NSUnitIlluminance *) lux; @end +/** + * Units of mass. Base unit - kilograms + */ GS_EXPORT_CLASS @interface NSUnitMass : NSDimension -/* - Base unit - kilograms - */ +/** + * The mass units in kilograms. + */ + (NSUnitMass *) kilograms; + +/** + * The mass units in grams. + */ + (NSUnitMass *) grams; + +/** + * The mass units in decigrams. + */ + (NSUnitMass *) decigrams; + +/** + * The mass units in centigrams. + */ + (NSUnitMass *) centigrams; + +/** + * The mass units in milligrams. + */ + (NSUnitMass *) milligrams; + +/** + * The mass units in micrograms. + */ + (NSUnitMass *) micrograms; + +/** + * The mass units in nanograms. + */ + (NSUnitMass *) nanograms; + +/** + * The mass units in picograms. + */ + (NSUnitMass *) picograms; + +/** + * The mass units in ounces. + */ + (NSUnitMass *) ounces; + +/** + * The mass units in pounds. + */ + (NSUnitMass *) pounds; + +/** + * The mass units in stones. + */ + (NSUnitMass *) stones; + +/** + * The mass units in metric tons. + */ + (NSUnitMass *) metricTons; + +/** + * The mass units in short tons. + */ + (NSUnitMass *) shortTons; + +/** + * The mass units in carats. + */ + (NSUnitMass *) carats; + +/** + * The mass units in ounces troy. + */ + (NSUnitMass *) ouncesTroy; + +/** + * The mass units in slugs. + */ + (NSUnitMass *) slugs; @end +/** + * Used to represent power. Base unit - watts + */ GS_EXPORT_CLASS @interface NSUnitPower : NSDimension -/* - Base unit - watts - */ +/** + * The power units in terawatts. + */ + (NSUnitPower *) terawatts; + +/** + * The power units in gigawatts. + */ + (NSUnitPower *) gigawatts; + +/** + * The power units in megawatts. + */ + (NSUnitPower *) megawatts; + +/** + * The power units in kilowatts. + */ + (NSUnitPower *) kilowatts; + +/** + * The power units in watts. + */ + (NSUnitPower *) watts; + +/** + * The power units in milliwatts. + */ + (NSUnitPower *) milliwatts; + +/** + * The power units in microwatts. + */ + (NSUnitPower *) microwatts; + +/** + * The power units in nanowatts. + */ + (NSUnitPower *) nanowatts; + +/** + * The power units in picowatts. + */ + (NSUnitPower *) picowatts; + +/** + * The power units in femtowatts. + */ + (NSUnitPower *) femtowatts; + +/** + * The power units in horsepower. + */ + (NSUnitPower *) horsepower; @end +/** + * Used to represent pressure. Base unit - newtonsPerMetersSquared (equivalent to 1 pascal) + */ GS_EXPORT_CLASS @interface NSUnitPressure : NSDimension -/* - Base unit - newtonsPerMetersSquared (equivalent to 1 pascal) - */ +/** + * The newtons per meters squared unit of pressure. + */ + (NSUnitPressure *) newtonsPerMetersSquared; + +/** + * The gigapascals unit of pressure. + */ + (NSUnitPressure *) gigapascals; + +/** + * The megapascals unit of pressure. + */ + (NSUnitPressure *) megapascals; + +/** + * The kilopascals unit of pressure. + */ + (NSUnitPressure *) kilopascals; + +/** + * The hetcopascals unit of pressure. + */ + (NSUnitPressure *) hectopascals; + +/** + * The inches of mercury unit of pressure. + */ + (NSUnitPressure *) inchesOfMercury; + +/** + * The bars unit of pressure. + */ + (NSUnitPressure *) bars; + +/** + * The millibars unit of pressure. + */ + (NSUnitPressure *) millibars; + +/** + * The millimeters of mercury of pressure. + */ + (NSUnitPressure *) millimetersOfMercury; + +/** + * The pounds of per square inch of pressure. + */ + (NSUnitPressure *) poundsForcePerSquareInch; @end +/** + * Used to represent speed. Base unit is meters per second. + */ GS_EXPORT_CLASS @interface NSUnitSpeed : NSDimension -/* - Base unit - metersPerSecond - */ +/** + * The meters per second measurement of speed. + */ + (NSUnitSpeed *) metersPerSecond; + +/** + * The kilometers per hour measurement of speed. + */ + (NSUnitSpeed *) kilometersPerHour; + +/** + * The miles per hour measurement of speed. + */ + (NSUnitSpeed *) milesPerHour; + +/** + * The knots measurement of speed. + */ + (NSUnitSpeed *) knots; @end +/** + * Used to represent temperature quantities. + * The base unit of this class is kelvin. + */ GS_EXPORT_CLASS @interface NSUnitTemperature : NSDimension -/* - Base unit - kelvin + +/** + * The kelvin unit of temperature. */ + (NSUnitTemperature *) kelvin; + +/** + * The kelvin unit of celsius. + */ + (NSUnitTemperature *) celsius; -+ (NSUnitTemperature *) fahrenheit; +/** + * The kelvin unit of fahenheit. + */ ++ (NSUnitTemperature *) fahrenheit; @end +/** + * Typically this is used to represent specific quantities. + * The base unit of this class is liters. + */ GS_EXPORT_CLASS @interface NSUnitVolume : NSDimension -/* - Base unit - liters - */ +/** + * The megaliters unit of volume. + */ + (NSUnitVolume *) megaliters; + +/** + * The kiloliters unit of volume. + */ + (NSUnitVolume *) kiloliters; + +/** + * The liters unit of volume. + */ + (NSUnitVolume *) liters; + +/** + * The deciliters unit of volume. + */ + (NSUnitVolume *) deciliters; + +/** + * The centiliters unit of volume. + */ + (NSUnitVolume *) centiliters; + +/** + * The milliliters unit of volume. + */ + (NSUnitVolume *) milliliters; + +/** + * The cubic kilometers unit of volume. + */ + (NSUnitVolume *) cubicKilometers; + +/** + * The cubic meters unit of volume. + */ + (NSUnitVolume *) cubicMeters; + +/** + * The cubic decimeters unit of volume. + */ + (NSUnitVolume *) cubicDecimeters; + +/** + * The cubic centimeteres unit of volume. + */ + (NSUnitVolume *) cubicCentimeters; + +/** + * The cubic millimeters unit of volume. + */ + (NSUnitVolume *) cubicMillimeters; + +/** + * The cubic inches unit of volume. + */ + (NSUnitVolume *) cubicInches; + +/** + * The cubic feet unit of volume. + */ + (NSUnitVolume *) cubicFeet; + +/** + * The cubic yards unit of volume. + */ + (NSUnitVolume *) cubicYards; + +/** + * The cubic miles unit of volume. + */ + (NSUnitVolume *) cubicMiles; + +/** + * The acre feet unit of volume. + */ + (NSUnitVolume *) acreFeet; + +/** + * The bushels unit of volume. + */ + (NSUnitVolume *) bushels; + +/** + * The teaspoons unit of volume. + */ + (NSUnitVolume *) teaspoons; + +/** + * The tablespoons unit of volume. + */ + (NSUnitVolume *) tablespoons; + +/** + * The fluid ounces unit of volume. + */ + (NSUnitVolume *) fluidOunces; + +/** + * The cups unit of volume. + */ + (NSUnitVolume *) cups; + +/** + * The pints unit of volume. + */ + (NSUnitVolume *) pints; + +/** + * The quarts unit of volume. + */ + (NSUnitVolume *) quarts; + +/** + * The gallons unit of volume. + */ + (NSUnitVolume *) gallons; + +/** + * The imperial teaspoons unit of volume. + */ + (NSUnitVolume *) imperialTeaspoons; + +/** + * The imperial tablespoons unit of volume. + */ + (NSUnitVolume *) imperialTablespoons; + +/** + * The imperial fluid ounces unit of volume. + */ + (NSUnitVolume *) imperialFluidOunces; + +/** + * The imperial pints unit of volume. + */ + (NSUnitVolume *) imperialPints; + +/** + * The imperial quarts unit of volume. + */ + (NSUnitVolume *) imperialQuarts; + +/** + * The imperial gallons unit of volume. + */ + (NSUnitVolume *) imperialGallons; + +/** + * The metric cups unit of volume. + */ + (NSUnitVolume *) metricCups; @end From bd8f4aadc162180826bc1f7cc76f85ad8fc75323 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sat, 16 Nov 2024 07:06:27 -0500 Subject: [PATCH 51/64] Cleanup whitespace --- Headers/Foundation/NSOrderedSet.h | 182 +++++++++++++++--------------- Headers/Foundation/NSUnit.h | 75 ++++++------ 2 files changed, 133 insertions(+), 124 deletions(-) diff --git a/Headers/Foundation/NSOrderedSet.h b/Headers/Foundation/NSOrderedSet.h index ad32006e61..c1c3532fd7 100644 --- a/Headers/Foundation/NSOrderedSet.h +++ b/Headers/Foundation/NSOrderedSet.h @@ -38,7 +38,7 @@ #if defined(__cplusplus) extern "C" { #endif - + @class GS_GENERIC_CLASS(NSArray, ElementT); @class GS_GENERIC_CLASS(NSEnumerator, ElementT); @class GS_GENERIC_CLASS(NSSet, ElementT); @@ -54,83 +54,83 @@ GS_EXPORT_CLASS // class methods + (instancetype) orderedSet; -+ (instancetype) orderedSetWithArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)objects; -+ (instancetype) orderedSetWithArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)objects - range: (NSRange)range - copyItems:(BOOL)flag; -+ (instancetype) orderedSetWithObject:(GS_GENERIC_TYPE(ElementT))anObject; -+ (instancetype) orderedSetWithObjects:(GS_GENERIC_TYPE(ElementT))firstObject, ...; -+ (instancetype) orderedSetWithObjects:(const GS_GENERIC_TYPE(ElementT)[])objects - count:(NSUInteger) count; -+ (instancetype) orderedSetWithOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; -+ (instancetype) orderedSetWithSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; -+ (instancetype) orderedSetWithSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet - copyItems:(BOOL)flag; ++ (instancetype) orderedSetWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)objects; ++ (instancetype) orderedSetWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)objects + range: (NSRange)range + copyItems: (BOOL)flag; ++ (instancetype) orderedSetWithObject: (GS_GENERIC_TYPE(ElementT))anObject; ++ (instancetype) orderedSetWithObjects: (GS_GENERIC_TYPE(ElementT))firstObject, ...; ++ (instancetype) orderedSetWithObjects: (const GS_GENERIC_TYPE(ElementT)[])objects + count: (NSUInteger) count; ++ (instancetype) orderedSetWithOrderedSet: (GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; ++ (instancetype) orderedSetWithSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; ++ (instancetype) orderedSetWithSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)aSet + copyItems: (BOOL)flag; // instance methods -- (instancetype) initWithArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)array; -- (instancetype) initWithArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)array copyItems:(BOOL)flag; -- (instancetype) initWithArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)array - range:(NSRange)range - copyItems:(BOOL)flag; -- (instancetype) initWithObject:(id)object; -- (instancetype) initWithObjects:(GS_GENERIC_TYPE(ElementT))firstObject, ...; -- (instancetype) initWithObjects:(const GS_GENERIC_TYPE(ElementT)[])objects - count:(NSUInteger)count; -- (instancetype) initWithOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; -- (instancetype) initWithOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet - copyItems:(BOOL)flag; -- (instancetype) initWithOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet - range: (NSRange)range - copyItems:(BOOL)flag; -- (instancetype) initWithSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; -- (instancetype) initWithSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet copyItems:(BOOL)flag; +- (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array; +- (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array copyItems: (BOOL)flag; +- (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array + range: (NSRange)range + copyItems: (BOOL)flag; +- (instancetype) initWithObject: (id)object; +- (instancetype) initWithObjects: (GS_GENERIC_TYPE(ElementT))firstObject, ...; +- (instancetype) initWithObjects: (const GS_GENERIC_TYPE(ElementT)[])objects + count: (NSUInteger)count; +- (instancetype) initWithOrderedSet: (GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; +- (instancetype) initWithOrderedSet: (GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet + copyItems: (BOOL)flag; +- (instancetype) initWithOrderedSet: (GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet + range: (NSRange)range + copyItems: (BOOL)flag; +- (instancetype) initWithSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; +- (instancetype) initWithSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)aSet copyItems:(BOOL)flag; - (instancetype) init; - (NSUInteger) count; -- (BOOL)containsObject:(GS_GENERIC_TYPE(ElementT))anObject; -- (void) enumerateObjectsAtIndexes:(NSIndexSet *)indexSet - options:(NSEnumerationOptions)opts - usingBlock:(GSEnumeratorBlock)aBlock; +- (BOOL)containsObject: (GS_GENERIC_TYPE(ElementT))anObject; +- (void) enumerateObjectsAtIndexes: (NSIndexSet *)indexSet + options: (NSEnumerationOptions)opts + usingBlock: (GSEnumeratorBlock)aBlock; - (void) enumerateObjectsUsingBlock: (GSEnumeratorBlock)aBlock; -- (void) enumerateObjectsWithOptions:(NSEnumerationOptions)opts - usingBlock:(GSEnumeratorBlock)aBlock; +- (void) enumerateObjectsWithOptions: (NSEnumerationOptions)opts + usingBlock: (GSEnumeratorBlock)aBlock; - (GS_GENERIC_TYPE(ElementT)) firstObject; - (GS_GENERIC_TYPE(ElementT)) lastObject; - (GS_GENERIC_TYPE(ElementT)) objectAtIndex: (NSUInteger)index; - - (GS_GENERIC_TYPE(ElementT)) objectAtIndexedSubscript:(NSUInteger)index; -- (GS_GENERIC_CLASS(NSArray, ElementT)*) objectsAtIndexes:(NSIndexSet *)indexes; -- (NSUInteger) indexOfObject:(GS_GENERIC_TYPE(ElementT))objects; +- (GS_GENERIC_TYPE(ElementT)) objectAtIndexedSubscript: (NSUInteger)index; +- (GS_GENERIC_CLASS(NSArray, ElementT)*) objectsAtIndexes: (NSIndexSet *)indexes; +- (NSUInteger) indexOfObject: (GS_GENERIC_TYPE(ElementT))objects; - (NSUInteger) indexOfObject: (id)key - inSortedRange: (NSRange)range - options: (NSBinarySearchingOptions)options - usingComparator: (NSComparator)comparator; - -- (NSUInteger) indexOfObjectAtIndexes:(NSIndexSet *)indexSet - options:(NSEnumerationOptions)opts - passingTest:(GSPredicateBlock)predicate; -- (NSUInteger) indexOfObjectPassingTest:(GSPredicateBlock)predicate; -- (NSUInteger) indexOfObjectWithOptions:(NSEnumerationOptions)opts - passingTest:(GSPredicateBlock)predicate; -- (NSIndexSet *) indexesOfObjectsAtIndexes:(NSIndexSet *)indexSet - options:(NSEnumerationOptions)opts - passingTest:(GSPredicateBlock)predicate; - -- (NSIndexSet *)indexesOfObjectsPassingTest:(GSPredicateBlock)predicate; -- (NSIndexSet *) indexesOfObjectsWithOptions:(NSEnumerationOptions)opts - passingTest:(GSPredicateBlock)predicate; + inSortedRange: (NSRange)range + options: (NSBinarySearchingOptions)options + usingComparator: (NSComparator)comparator; + +- (NSUInteger) indexOfObjectAtIndexes: (NSIndexSet *)indexSet + options: (NSEnumerationOptions)opts + passingTest: (GSPredicateBlock)predicate; +- (NSUInteger) indexOfObjectPassingTest: (GSPredicateBlock)predicate; +- (NSUInteger) indexOfObjectWithOptions: (NSEnumerationOptions)opts + passingTest: (GSPredicateBlock)predicate; +- (NSIndexSet *) indexesOfObjectsAtIndexes: (NSIndexSet *)indexSet + options: (NSEnumerationOptions)opts + passingTest: (GSPredicateBlock)predicate; + +- (NSIndexSet *)indexesOfObjectsPassingTest: (GSPredicateBlock)predicate; +- (NSIndexSet *) indexesOfObjectsWithOptions: (NSEnumerationOptions)opts + passingTest: (GSPredicateBlock)predicate; - (GS_GENERIC_CLASS(NSEnumerator, ElementT)*) objectEnumerator; - (GS_GENERIC_CLASS(NSEnumerator, ElementT)*) reverseObjectEnumerator; - (NSOrderedSet *)reversedOrderedSet; - (void) getObjects: (__unsafe_unretained GS_GENERIC_TYPE(ElementT)[])aBuffer - range: (NSRange)aRange; + range: (NSRange)aRange; // Key value coding support - (void) setValue: (id)value forKey: (NSString*)key; -- (id) valueForKey: (NSString*)key; +- (id) valueForKey: (NSString*)key; // Comparing Sets - (BOOL) isEqualToOrderedSet: (NSOrderedSet *)aSet; - + // Set operations - (BOOL) intersectsOrderedSet: (NSOrderedSet *)aSet; - (BOOL) intersectsSet: (NSSet *)aSet; @@ -138,12 +138,12 @@ GS_EXPORT_CLASS - (BOOL) isSubsetOfSet:(NSSet *)aSet; // Creating a Sorted Array -- (GS_GENERIC_CLASS(NSArray, ElementT) *) sortedArrayUsingDescriptors:(NSArray *)sortDescriptors; +- (GS_GENERIC_CLASS(NSArray, ElementT) *) sortedArrayUsingDescriptors: (NSArray *)sortDescriptors; - (GS_GENERIC_CLASS(NSArray, ElementT) *) sortedArrayUsingComparator: (NSComparator)comparator; - (GS_GENERIC_CLASS(NSArray, ElementT) *) sortedArrayWithOptions: (NSSortOptions)options - usingComparator: (NSComparator)comparator; + usingComparator: (NSComparator)comparator; // Filtering Ordered Sets - (NSOrderedSet *)filteredOrderedSetUsingPredicate: (NSPredicate *)predicate; @@ -165,42 +165,42 @@ GS_EXPORT_CLASS + (instancetype)orderedSetWithCapacity: (NSUInteger)capacity; - (instancetype)initWithCapacity: (NSUInteger)capacity; - (instancetype) init; -- (void)addObject:(GS_GENERIC_TYPE(ElementT))anObject; -- (void)addObjects:(const GS_GENERIC_TYPE(ElementT)[])objects count:(NSUInteger)count; -- (void)addObjectsFromArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)otherArray; -- (void)insertObject:(GS_GENERIC_TYPE(ElementT))object atIndex:(NSUInteger)index; -- (void)setObject:(GS_GENERIC_TYPE(ElementT))object atIndexedSubscript:(NSUInteger)index; -- (void)insertObjects:(GS_GENERIC_CLASS(NSArray, ElementT)*)array atIndexes:(NSIndexSet *)indexes; -- (void)removeObject:(GS_GENERIC_TYPE(ElementT))object; -- (void)removeObjectAtIndex:(NSUInteger)index; -- (void)removeObjectsAtIndexes:(NSIndexSet *)indexes; -- (void)removeObjectsInArray:(GS_GENERIC_CLASS(NSArray, ElementT)*)otherArray; -- (void)removeObjectsInRange:(NSRange)range; +- (void)addObject: (GS_GENERIC_TYPE(ElementT))anObject; +- (void)addObjects: (const GS_GENERIC_TYPE(ElementT)[])objects count: (NSUInteger)count; +- (void)addObjectsFromArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)otherArray; +- (void)insertObject: (GS_GENERIC_TYPE(ElementT))object atIndex: (NSUInteger)index; +- (void)setObject: (GS_GENERIC_TYPE(ElementT))object atIndexedSubscript: (NSUInteger)index; +- (void)insertObjects: (GS_GENERIC_CLASS(NSArray, ElementT)*)array atIndexes: (NSIndexSet *)indexes; +- (void)removeObject: (GS_GENERIC_TYPE(ElementT))object; +- (void)removeObjectAtIndex: (NSUInteger)index; +- (void)removeObjectsAtIndexes: (NSIndexSet *)indexes; +- (void)removeObjectsInArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)otherArray; +- (void)removeObjectsInRange: (NSRange)range; - (void)removeAllObjects; -- (void)replaceObjectAtIndex:(NSUInteger)index - withObject:(GS_GENERIC_TYPE(ElementT))object; +- (void)replaceObjectAtIndex: (NSUInteger)index + withObject: (GS_GENERIC_TYPE(ElementT))object; - (void) replaceObjectsAtIndexes: (NSIndexSet *)indexes - withObjects: (GS_GENERIC_CLASS(NSArray, ElementT)*)objects; -- (void) replaceObjectsInRange:(NSRange)range - withObjects:(const GS_GENERIC_TYPE(ElementT)[])objects - count: (NSUInteger)count; -- (void)setObject:(GS_GENERIC_TYPE(ElementT))object atIndex:(NSUInteger)index; -- (void)moveObjectsAtIndexes:(NSIndexSet *)indexes toIndex:(NSUInteger)index; -- (void) exchangeObjectAtIndex:(NSUInteger)index withObjectAtIndex:(NSUInteger)otherIndex; -- (void)filterUsingPredicate:(NSPredicate *)predicate; -- (void) sortUsingDescriptors:(NSArray *)descriptors; + withObjects: (GS_GENERIC_CLASS(NSArray, ElementT)*)objects; +- (void) replaceObjectsInRange: (NSRange)range + withObjects: (const GS_GENERIC_TYPE(ElementT)[])objects + count: (NSUInteger)count; +- (void)setObject: (GS_GENERIC_TYPE(ElementT))object atIndex: (NSUInteger)index; +- (void)moveObjectsAtIndexes: (NSIndexSet *)indexes toIndex: (NSUInteger)index; +- (void) exchangeObjectAtIndex: (NSUInteger)index withObjectAtIndex: (NSUInteger)otherIndex; +- (void)filterUsingPredicate: (NSPredicate *)predicate; +- (void) sortUsingDescriptors: (NSArray *)descriptors; - (void) sortUsingComparator: (NSComparator)comparator; - (void) sortWithOptions: (NSSortOptions)options - usingComparator: (NSComparator)comparator; + usingComparator: (NSComparator)comparator; - (void) sortRange: (NSRange)range - options:(NSSortOptions)options + options: (NSSortOptions)options usingComparator: (NSComparator)comparator; -- (void) intersectOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; -- (void) intersectSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; -- (void) minusOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; -- (void) minusSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; -- (void) unionOrderedSet:(GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; -- (void) unionSet:(GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; +- (void) intersectOrderedSet: (GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; +- (void) intersectSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; +- (void) minusOrderedSet: (GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; +- (void) minusSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; +- (void) unionOrderedSet: (GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; +- (void) unionSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; - (instancetype) initWithCoder: (NSCoder *)coder; @end diff --git a/Headers/Foundation/NSUnit.h b/Headers/Foundation/NSUnit.h index 273758ed84..04c3def7a5 100644 --- a/Headers/Foundation/NSUnit.h +++ b/Headers/Foundation/NSUnit.h @@ -1,21 +1,21 @@ /** Definition of class NSUnit Copyright (C) 2019 Free Software Foundation, Inc. - + By: Gregory John Casamento Date: Mon Sep 30 15:58:21 EDT 2019 This file is part of the GNUstep Library. - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA. @@ -52,7 +52,7 @@ GS_EXPORT_CLASS } - (instancetype) initWithCoefficient: (double)coefficient; - (instancetype) initWithCoefficient: (double)coefficient - constant: (double)constant; + constant: (double)constant; - (double) coefficient; - (double) constant; @end @@ -65,7 +65,7 @@ GS_EXPORT_CLASS { NSString *_symbol; } - + - (instancetype) init; - (instancetype) initWithSymbol: (NSString *)symbol; - (NSString *) symbol; @@ -93,7 +93,7 @@ GS_EXPORT_CLASS * Base unit - metersPerSecondSquared */ GS_EXPORT_CLASS -@interface NSUnitAcceleration : NSDimension +@interface NSUnitAcceleration : NSDimension + (NSUnitAcceleration *) metersPerSecondSquared; + (NSUnitAcceleration *) gravity; @@ -104,7 +104,7 @@ GS_EXPORT_CLASS * Base unit - degrees */ GS_EXPORT_CLASS -@interface NSUnitAngle : NSDimension +@interface NSUnitAngle : NSDimension + (NSUnitAngle *) degrees; + (NSUnitAngle *) arcMinutes; @@ -119,7 +119,7 @@ GS_EXPORT_CLASS * Base unit - squareMeters */ GS_EXPORT_CLASS -@interface NSUnitArea : NSDimension +@interface NSUnitArea : NSDimension + (NSUnitArea *) squareMegameters; + (NSUnitArea *) squareKilometers; @@ -139,14 +139,24 @@ GS_EXPORT_CLASS @end /** - * Base unit - gramsPerLiter + * Units of concentration. Base unit - gramsPerLiter. */ GS_EXPORT_CLASS -@interface NSUnitConcentrationMass : NSDimension +@interface NSUnitConcentrationMass : NSDimension +/** + * Concentration units in grams per liter. + */ + (NSUnitConcentrationMass *) gramsPerLiter; + +/** + * Concentration units in milligrams per deciliter. + */ + (NSUnitConcentrationMass *) milligramsPerDeciliter; +/** + * Concentration units in grams per mole. + */ + (NSUnitConcentrationMass *) millimolesPerLiterWithGramsPerMole: (double)gramsPerMole; @end @@ -155,7 +165,7 @@ GS_EXPORT_CLASS * Units of dispersion. Base unit - partsPerMillion */ GS_EXPORT_CLASS -@interface NSUnitDispersion : NSDimension +@interface NSUnitDispersion : NSDimension /** * Units of dispersion in parts per million. @@ -168,20 +178,20 @@ GS_EXPORT_CLASS * Units of duration. Base unit - seconds */ GS_EXPORT_CLASS -@interface NSUnitDuration : NSDimension +@interface NSUnitDuration : NSDimension /** - * Units of during in seconds. + * Units of duration in seconds. */ + (NSUnitDuration *) seconds; /** - * Units of during in minutes. + * Units of duration in minutes. */ + (NSUnitDuration *) minutes; /** - * Units of during in hours. + * Units of duration in hours. */ + (NSUnitDuration *) hours; @@ -191,7 +201,7 @@ GS_EXPORT_CLASS * Units of electric charge. Base unit - coulombs */ GS_EXPORT_CLASS -@interface NSUnitElectricCharge : NSDimension +@interface NSUnitElectricCharge : NSDimension /** * The units of eletric charge in coulombs. @@ -229,7 +239,7 @@ GS_EXPORT_CLASS * Units of electric current. Base unit - amperes */ GS_EXPORT_CLASS -@interface NSUnitElectricCurrent : NSDimension +@interface NSUnitElectricCurrent : NSDimension /** * The units of eletric current in megaamperes. @@ -262,7 +272,7 @@ GS_EXPORT_CLASS * Units of electric potential. Base unit - volts */ GS_EXPORT_CLASS -@interface NSUnitElectricPotentialDifference : NSDimension +@interface NSUnitElectricPotentialDifference : NSDimension /** * The units of eletric potential in megavolts. @@ -295,7 +305,7 @@ GS_EXPORT_CLASS * Units of electric resistance. Base unit - ohms */ GS_EXPORT_CLASS -@interface NSUnitElectricResistance : NSDimension +@interface NSUnitElectricResistance : NSDimension /** * The units of eletric resistance in megaohms. @@ -328,7 +338,7 @@ GS_EXPORT_CLASS * Units of Energy. Base unit - joules */ GS_EXPORT_CLASS -@interface NSUnitEnergy : NSDimension +@interface NSUnitEnergy : NSDimension /** * The units of energy in kilojoules. @@ -361,7 +371,7 @@ GS_EXPORT_CLASS * Units of frequency. Base unit - hertz */ GS_EXPORT_CLASS -@interface NSUnitFrequency : NSDimension +@interface NSUnitFrequency : NSDimension /** * The units of frequency in terahertz. @@ -409,7 +419,7 @@ GS_EXPORT_CLASS * Units of fuel efficiency. Base unit - litersPer100Kilometers */ GS_EXPORT_CLASS -@interface NSUnitFuelEfficiency : NSDimension +@interface NSUnitFuelEfficiency : NSDimension /** * The units of fuel efficiency in liters per 100 kilometers. @@ -432,7 +442,7 @@ GS_EXPORT_CLASS * Units of length. Base unit - meters */ GS_EXPORT_CLASS -@interface NSUnitLength : NSDimension +@interface NSUnitLength : NSDimension /** * The units of length in megameters. @@ -550,7 +560,7 @@ GS_EXPORT_CLASS * Units of illumination. Base unit - lux */ GS_EXPORT_CLASS -@interface NSUnitIlluminance : NSDimension +@interface NSUnitIlluminance : NSDimension /** * The units of illuminance in lux. @@ -563,7 +573,7 @@ GS_EXPORT_CLASS * Units of mass. Base unit - kilograms */ GS_EXPORT_CLASS -@interface NSUnitMass : NSDimension +@interface NSUnitMass : NSDimension /** * The mass units in kilograms. @@ -651,7 +661,7 @@ GS_EXPORT_CLASS * Used to represent power. Base unit - watts */ GS_EXPORT_CLASS -@interface NSUnitPower : NSDimension +@interface NSUnitPower : NSDimension /** * The power units in terawatts. @@ -714,7 +724,7 @@ GS_EXPORT_CLASS * Used to represent pressure. Base unit - newtonsPerMetersSquared (equivalent to 1 pascal) */ GS_EXPORT_CLASS -@interface NSUnitPressure : NSDimension +@interface NSUnitPressure : NSDimension /** * The newtons per meters squared unit of pressure. @@ -772,7 +782,7 @@ GS_EXPORT_CLASS * Used to represent speed. Base unit is meters per second. */ GS_EXPORT_CLASS -@interface NSUnitSpeed : NSDimension +@interface NSUnitSpeed : NSDimension /** * The meters per second measurement of speed. @@ -801,7 +811,7 @@ GS_EXPORT_CLASS * The base unit of this class is kelvin. */ GS_EXPORT_CLASS -@interface NSUnitTemperature : NSDimension +@interface NSUnitTemperature : NSDimension /** * The kelvin unit of temperature. @@ -811,7 +821,7 @@ GS_EXPORT_CLASS /** * The kelvin unit of celsius. */ -+ (NSUnitTemperature *) celsius; ++ (NSUnitTemperature *) celsius; /** * The kelvin unit of fahenheit. @@ -825,7 +835,7 @@ GS_EXPORT_CLASS * The base unit of this class is liters. */ GS_EXPORT_CLASS -@interface NSUnitVolume : NSDimension +@interface NSUnitVolume : NSDimension /** * The megaliters unit of volume. @@ -991,4 +1001,3 @@ GS_EXPORT_CLASS #endif /* GS_API_MACOSX */ #endif /* _NSUnit_h_GNUSTEP_BASE_INCLUDE */ - From 9800834360d4b52a6d9a913c3ce64c586a0597cd Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 17 Nov 2024 06:33:14 -0500 Subject: [PATCH 52/64] Add final documentation changes --- Headers/Foundation/NSUnit.h | 139 ++++++++++++++++++++++++++++++++++-- 1 file changed, 134 insertions(+), 5 deletions(-) diff --git a/Headers/Foundation/NSUnit.h b/Headers/Foundation/NSUnit.h index 04c3def7a5..0f5240b3f5 100644 --- a/Headers/Foundation/NSUnit.h +++ b/Headers/Foundation/NSUnit.h @@ -33,11 +33,18 @@ extern "C" { #endif /** - * Unit converter + * Unit converter. This is an abstract class. */ GS_EXPORT_CLASS @interface NSUnitConverter : NSObject +/** + * For a given unit, returns the specified value of that unit based on the units dimension. + */ - (double) baseUnitValueFromValue: (double)value; + +/** + * For a unit, returns the specified value of the base unit in terms of that unit. + */ - (double) valueFromBaseUnitValue: (double)baseUnitValue; @end @@ -50,10 +57,26 @@ GS_EXPORT_CLASS double _coefficient; double _constant; } + +/** + * Initialize with the coefficient. + */ - (instancetype) initWithCoefficient: (double)coefficient; + +/** + * Initialize with the coefficient and constant. + */ - (instancetype) initWithCoefficient: (double)coefficient constant: (double)constant; + +/** + * Return the coefficient. + */ - (double) coefficient; + +/** + * Return the constant. + */ - (double) constant; @end @@ -65,9 +88,19 @@ GS_EXPORT_CLASS { NSString *_symbol; } - +/** + * Initialize an NSUnit instance. + */ - (instancetype) init; + +/** + * Initialize NSUnit with a given symbol. + */ - (instancetype) initWithSymbol: (NSString *)symbol; + +/** + * The symbol used by a given unit. + */ - (NSString *) symbol; @end @@ -82,58 +115,154 @@ GS_EXPORT_CLASS NSUnitConverter *_converter; } +/** + * The NSUnitConverter instance used for this NSDimension object. + */ - (NSUnitConverter *) converter; + +/** + * Initialize with symbol and an NSUnitConverter. + */ - (instancetype) initWithSymbol: (NSString *)symbol converter: (NSUnitConverter *)converter; + +/** + * Return a base unit. + */ + (instancetype) baseUnit; @end // Predefined.... /** - * Base unit - metersPerSecondSquared + * Units of accelleration. Base unit - metersPerSecondSquared */ GS_EXPORT_CLASS @interface NSUnitAcceleration : NSDimension +/** + * Units of accelleration in meters per second squared. + */ + (NSUnitAcceleration *) metersPerSecondSquared; + +/** + * Units of accelleration equal to the gravitational constant. + */ + (NSUnitAcceleration *) gravity; @end /** - * Base unit - degrees + * Angle units. Base unit - degrees */ GS_EXPORT_CLASS @interface NSUnitAngle : NSDimension +/** + * Units of angle in degrees. + */ + (NSUnitAngle *) degrees; + +/** + * Units of angle in arc minutes. + */ + (NSUnitAngle *) arcMinutes; + +/** + * Units of angle arc seconds. + */ + (NSUnitAngle *) arcSeconds; + +/** + * Units of angle in radians. + */ + (NSUnitAngle *) radians; + +/** + * Units of area in square megameters. + */ + (NSUnitAngle *) gradians; + +/** + * Units of area in square megameters. + */ + (NSUnitAngle *) revolutions; @end /** - * Base unit - squareMeters + * Units of area. Base unit - squareMeters */ GS_EXPORT_CLASS @interface NSUnitArea : NSDimension +/** + * Units of area in square megameters. + */ + (NSUnitArea *) squareMegameters; + +/** + * Units of area in square kilometers. + */ + (NSUnitArea *) squareKilometers; + +/** + * Units of area in square meters. + */ + (NSUnitArea *) squareMeters; + +/** + * Units of area in square centimeters. + */ + (NSUnitArea *) squareCentimeters; + +/** + * Units of area in square millimeters. + */ + (NSUnitArea *) squareMillimeters; + +/** + * Units of area in square micrometers. + */ + (NSUnitArea *) squareMicrometers; + +/** + * Units of area in square nanometers. + */ + (NSUnitArea *) squareNanometers; + +/** + * Units of area in square inches. + */ + (NSUnitArea *) squareInches; + +/** + * Units of area in square feet. + */ + (NSUnitArea *) squareFeet; + +/** + * Units of area in square yards. + */ + (NSUnitArea *) squareYards; + +/** + * Units of area in square miles. + */ + (NSUnitArea *) squareMiles; + +/** + * Units of area in acres/ + */ + (NSUnitArea *) acres; + +/** + * Units of area in ares. + */ + (NSUnitArea *) ares; + +/** + * Units of area in hectares. + */ + (NSUnitArea *) hectares; @end From 37eba33f8c3a08c0956491fcf8d2d8e701680ddf Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 09:57:25 +0000 Subject: [PATCH 53/64] Fixup
to
--- Tools/AGSHtml.m | 62 ++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Tools/AGSHtml.m b/Tools/AGSHtml.m index 83bb6f9cff..99af2a1f46 100644 --- a/Tools/AGSHtml.m +++ b/Tools/AGSHtml.m @@ -337,9 +337,9 @@ - (NSString*) makeURL: (NSString*)r /** * Make a link for the element r, with the specified type t, * in a particular unit u. Only the start of - * the html element is returned (<a ...>).
+ * the html element is returned (<a ...>).
* If the boolean f is YES, then the link is a reference to somewhere, - * otherwise the link is an anchor for some element being output.
+ * otherwise the link is an anchor for some element being output.
* If there is an error, the method returns nil. */ - (NSString*) makeLink: (NSString*)r @@ -584,7 +584,7 @@ - (void) outputIndex: (NSString*)type } else { - [buf appendString: @"
"]; + [buf appendString: @"
"]; } [buf appendString: @"\n"]; } @@ -748,7 +748,7 @@ - (void) outputIndex: (NSString*)type } else { - [buf appendString: @"
"]; + [buf appendString: @"
"]; } [buf appendString: @"\n"]; @@ -797,7 +797,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [self outputNodeList: children to: buf]; [buf appendString: indent]; - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; if (prevFile != nil) { [buf appendString: indent]; @@ -836,7 +836,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf } else if ([name isEqual: @"br"] == YES) { - [buf appendString: @"
"]; + [buf appendString: @"
"]; } else if ([name isEqual: @"category"] == YES) { @@ -933,7 +933,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: @"\n"]; [buf appendString: indent]; [buf appendString: str]; - [buf appendString: @";
\n"]; + [buf appendString: @";
\n"]; node = firstElement(children); @@ -1246,7 +1246,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: @"\n"]; [buf appendString: indent]; [buf appendString: str]; - [buf appendString: @");
\n"]; + [buf appendString: @");
\n"]; node = firstElement(children); @@ -1359,25 +1359,25 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: indent]; [buf appendString: - @"Classes
\n"]; + @"Classes
\n"]; [buf appendString: indent]; [buf appendString: - @"Protocols
\n"]; + @"Protocols
\n"]; [buf appendString: indent]; [buf appendString: - @"Constants
\n"]; + @"Constants
\n"]; [buf appendString: indent]; [buf appendString: - @"Functions
\n"]; + @"Functions
\n"]; [buf appendString: indent]; [buf appendString: - @"Macros
\n"]; + @"Macros
\n"]; [buf appendString: indent]; [buf appendString: - @"Types
\n"]; + @"Types
\n"]; [buf appendString: indent]; [buf appendString: - @"Variables
\n"]; + @"Variables
\n"]; [self decIndent]; [buf appendString: indent]; @@ -1512,7 +1512,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf if (prevFile != nil || upFile != nil || nextFile != nil) { [buf appendString: indent]; - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; } [buf appendString: indent]; @@ -1733,7 +1733,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf { v = @"public"; } - [buf appendFormat: @"%@@%@ %@ %@;
\n", indent, v, t, n]; + [buf appendFormat: @"%@@%@ %@ %@;
\n", indent, v, t, n]; /* * List standards with which ivar complies @@ -1851,7 +1851,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf { [buf appendString: @")"]; } - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; node = firstElement(children); @@ -1998,7 +1998,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: @"\n"]; [buf appendString: indent]; [buf appendString: str]; - [buf appendString: @";
\n"]; + [buf appendString: @";
\n"]; node = firstElement(children); @@ -2016,23 +2016,23 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf && [str boolValue] == YES) { [buf appendString: @"This is a designated initialiser " - @"for the class.
\n"]; + @"for the class.
\n"]; } str = [prop objectForKey: @"override"]; if ([str isEqual: @"subclass"] == YES) { [buf appendString: @"Subclasses must " - @"override this method.
\n"]; + @"override this method.
\n"]; } else if ([str isEqual: @"dummy"] == YES) { [buf appendString: @"An empty method provided for subclasses " - @"to override.
\n"]; + @"to override.
\n"]; } else if ([str isEqual: @"never"] == YES) { [buf appendString: @"Subclasses must NOT " - @"override this method.
\n"]; + @"override this method.
\n"]; } if ([[node name] isEqual: @"desc"]) @@ -2214,7 +2214,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: @"\n"]; [buf appendString: indent]; [buf appendString: str]; - [buf appendString: @";
\n"]; + [buf appendString: @";
\n"]; node = firstElement(children); @@ -2292,7 +2292,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: @"\n"]; [buf appendString: indent]; [buf appendString: str]; - [buf appendString: @";
\n"]; + [buf appendString: @";
\n"]; node = firstElement(children); @@ -2866,11 +2866,11 @@ - (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendFormat: @"Instance Variables\n", classname]; [buf appendString: indent]; - [buf appendString: @"

\n"]; + [buf appendString: @"

\n"]; [ibuf appendFormat: @"", classname]; } [ibuf appendString: indent]; - [ibuf appendString: @"


\n"]; + [ibuf appendString: @"

\n"]; [ibuf appendString: indent]; [ibuf appendFormat: @"

Instance Variables for %@ Class

\n", classname]; @@ -2880,7 +2880,7 @@ - (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf node = [node nextElement]; } [ibuf appendString: indent]; - [ibuf appendString: @"


\n"]; + [ibuf appendString: @"


\n"]; } a = [localRefs methodsInUnit: unit]; @@ -3018,7 +3018,7 @@ - (void) outputVersion: (NSDictionary*)prop to: (NSMutableString*)buf } } [buf appendString:@"\n"]; - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; } else if ([gvadd length] > 0) { @@ -3036,14 +3036,14 @@ - (void) outputVersion: (NSDictionary*)prop to: (NSMutableString*)buf [buf appendString: @" deprecated at "]; [buf appendString: gvdep]; } - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; if ([gvrem length] > 0) { [buf appendString: @" Likely to be changed/moved/removed at "]; [buf appendString: gvrem]; } [buf appendString:@"\n"]; - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; } } From d31ed9a68ec2cce9708ae479af5be9913e1a72a0 Mon Sep 17 00:00:00 2001 From: rfm Date: Sun, 17 Nov 2024 10:14:08 +0000 Subject: [PATCH 54/64] Technically
is correct xml even though
is generally accepted. --- Tools/AGSHtml.m | 64 ++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/Tools/AGSHtml.m b/Tools/AGSHtml.m index 99af2a1f46..f6ed21f571 100644 --- a/Tools/AGSHtml.m +++ b/Tools/AGSHtml.m @@ -262,7 +262,7 @@ - (id) init * Calls -makeLink:ofType:isRef: or -makeLink:ofType:inUnit:isRef: to * create the first part of an anchor, and fills in the text content * of the anchor with n (the specified name). Returns an entire anchor - * string as a result.
+ * string as a result.
* This method is used to create all the anchors in the html output. */ - (NSString*) makeAnchor: (NSString*)r @@ -337,9 +337,9 @@ - (NSString*) makeURL: (NSString*)r /** * Make a link for the element r, with the specified type t, * in a particular unit u. Only the start of - * the html element is returned (<a ...>).
+ * the html element is returned (<a ...>).
* If the boolean f is YES, then the link is a reference to somewhere, - * otherwise the link is an anchor for some element being output.
+ * otherwise the link is an anchor for some element being output.
* If there is an error, the method returns nil. */ - (NSString*) makeLink: (NSString*)r @@ -584,7 +584,7 @@ - (void) outputIndex: (NSString*)type } else { - [buf appendString: @"
"]; + [buf appendString: @"
"]; } [buf appendString: @"\n"]; } @@ -748,7 +748,7 @@ - (void) outputIndex: (NSString*)type } else { - [buf appendString: @"
"]; + [buf appendString: @"
"]; } [buf appendString: @"\n"]; @@ -797,7 +797,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [self outputNodeList: children to: buf]; [buf appendString: indent]; - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; if (prevFile != nil) { [buf appendString: indent]; @@ -836,7 +836,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf } else if ([name isEqual: @"br"] == YES) { - [buf appendString: @"
"]; + [buf appendString: @"
"]; } else if ([name isEqual: @"category"] == YES) { @@ -933,7 +933,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: @"\n"]; [buf appendString: indent]; [buf appendString: str]; - [buf appendString: @";
\n"]; + [buf appendString: @";
\n"]; node = firstElement(children); @@ -1246,7 +1246,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: @"\n"]; [buf appendString: indent]; [buf appendString: str]; - [buf appendString: @");
\n"]; + [buf appendString: @");
\n"]; node = firstElement(children); @@ -1359,25 +1359,25 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: indent]; [buf appendString: - @"
Classes
\n"]; + @"Classes
\n"]; [buf appendString: indent]; [buf appendString: - @"Protocols
\n"]; + @"Protocols
\n"]; [buf appendString: indent]; [buf appendString: - @"Constants
\n"]; + @"Constants
\n"]; [buf appendString: indent]; [buf appendString: - @"Functions
\n"]; + @"Functions
\n"]; [buf appendString: indent]; [buf appendString: - @"Macros
\n"]; + @"Macros
\n"]; [buf appendString: indent]; [buf appendString: - @"Types
\n"]; + @"Types
\n"]; [buf appendString: indent]; [buf appendString: - @"Variables
\n"]; + @"Variables
\n"]; [self decIndent]; [buf appendString: indent]; @@ -1512,7 +1512,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf if (prevFile != nil || upFile != nil || nextFile != nil) { [buf appendString: indent]; - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; } [buf appendString: indent]; @@ -1733,7 +1733,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf { v = @"public"; } - [buf appendFormat: @"%@@%@ %@ %@;
\n", indent, v, t, n]; + [buf appendFormat: @"%@@%@ %@ %@;
\n", indent, v, t, n]; /* * List standards with which ivar complies @@ -1851,7 +1851,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf { [buf appendString: @")"]; } - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; node = firstElement(children); @@ -1998,7 +1998,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: @"\n"]; [buf appendString: indent]; [buf appendString: str]; - [buf appendString: @";
\n"]; + [buf appendString: @";
\n"]; node = firstElement(children); @@ -2016,23 +2016,23 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf && [str boolValue] == YES) { [buf appendString: @"This is a designated initialiser " - @"for the class.
\n"]; + @"for the class.
\n"]; } str = [prop objectForKey: @"override"]; if ([str isEqual: @"subclass"] == YES) { [buf appendString: @"Subclasses must " - @"override this method.
\n"]; + @"override this method.
\n"]; } else if ([str isEqual: @"dummy"] == YES) { [buf appendString: @"An empty method provided for subclasses " - @"to override.
\n"]; + @"to override.
\n"]; } else if ([str isEqual: @"never"] == YES) { [buf appendString: @"Subclasses must NOT " - @"override this method.
\n"]; + @"override this method.
\n"]; } if ([[node name] isEqual: @"desc"]) @@ -2214,7 +2214,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: @"\n"]; [buf appendString: indent]; [buf appendString: str]; - [buf appendString: @";
\n"]; + [buf appendString: @";
\n"]; node = firstElement(children); @@ -2292,7 +2292,7 @@ - (void) outputNode: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendString: @"\n"]; [buf appendString: indent]; [buf appendString: str]; - [buf appendString: @";
\n"]; + [buf appendString: @";
\n"]; node = firstElement(children); @@ -2866,11 +2866,11 @@ - (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf [buf appendFormat: @"Instance Variables\n", classname]; [buf appendString: indent]; - [buf appendString: @"

\n"]; + [buf appendString: @"

\n"]; [ibuf appendFormat: @"", classname]; } [ibuf appendString: indent]; - [ibuf appendString: @"

\n"]; + [ibuf appendString: @"

\n"]; [ibuf appendString: indent]; [ibuf appendFormat: @"

Instance Variables for %@ Class

\n", classname]; @@ -2880,7 +2880,7 @@ - (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf node = [node nextElement]; } [ibuf appendString: indent]; - [ibuf appendString: @"


\n"]; + [ibuf appendString: @"


\n"]; } a = [localRefs methodsInUnit: unit]; @@ -3018,7 +3018,7 @@ - (void) outputVersion: (NSDictionary*)prop to: (NSMutableString*)buf } } [buf appendString:@"\n"]; - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; } else if ([gvadd length] > 0) { @@ -3036,14 +3036,14 @@ - (void) outputVersion: (NSDictionary*)prop to: (NSMutableString*)buf [buf appendString: @" deprecated at "]; [buf appendString: gvdep]; } - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; if ([gvrem length] > 0) { [buf appendString: @" Likely to be changed/moved/removed at "]; [buf appendString: gvrem]; } [buf appendString:@"\n"]; - [buf appendString: @"
\n"]; + [buf appendString: @"
\n"]; } } From 32b84ca49dc8b22267f194cacfbfb1883ee426e5 Mon Sep 17 00:00:00 2001 From: Riccardo Mottola Date: Mon, 18 Nov 2024 15:38:57 +0100 Subject: [PATCH 55/64] fix minor typos --- configure | 3 ++- configure.ac | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 49c94db90b..ae62e54627 100755 --- a/configure +++ b/configure @@ -6314,7 +6314,7 @@ printf "%s\n" "no" >&6; } PKG_CONFIG="" fi fi -# If the modern mechanism failswe may havew an older pkg-config +# If the modern mechanism fails we may have an older pkg-config # so try looking it up the old fashioned way. if test -z "$PKG_CONFIG"; then # Extract the first word of "pkg-config", so it can be a program name with args. @@ -14139,6 +14139,7 @@ fi fi + #-------------------------------------------------------------------- # Check for International Components for Unicode # See DEPENDENCIES POLICY at the start of this file. diff --git a/configure.ac b/configure.ac index 617e4dc989..18f06693c5 100644 --- a/configure.ac +++ b/configure.ac @@ -1220,7 +1220,7 @@ AC_LANG_POP(C) AC_PATH_PROG(WHOAMI, whoami, echo, $PATH:/usr/ucb) PKG_PROG_PKG_CONFIG -# If the modern mechanism failswe may havew an older pkg-config +# If the modern mechanism fails we may have an older pkg-config # so try looking it up the old fashioned way. if test -z "$PKG_CONFIG"; then AC_PATH_PROG(PKG_CONFIG,pkg-config,,) @@ -3562,6 +3562,7 @@ if test $enable_zeroconf = yes; then fi AC_SUBST(HAVE_MDNS) AC_SUBST(HAVE_AVAHI) + #-------------------------------------------------------------------- # Check for International Components for Unicode # See DEPENDENCIES POLICY at the start of this file. From 90eda7101872f43e77bedcc28a39f257cafc9b47 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 17 Nov 2024 10:17:46 -0500 Subject: [PATCH 56/64] Add documentation for NSOrderedSet --- Headers/Foundation/NSOrderedSet.h | 66 +++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/Headers/Foundation/NSOrderedSet.h b/Headers/Foundation/NSOrderedSet.h index c1c3532fd7..14936841bc 100644 --- a/Headers/Foundation/NSOrderedSet.h +++ b/Headers/Foundation/NSOrderedSet.h @@ -53,30 +53,96 @@ GS_EXPORT_CLASS NSFastEnumeration> // class methods +/** + * Create and return an empty ordered set. + */ + (instancetype) orderedSet; + +/** + * Create and return an empty ordered set with the provided NSArray instance. + */ + (instancetype) orderedSetWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)objects; + +/** + * Create and return an empty ordered set with the provided NSArray instance. + * Use the range to determine which elements to use. If flag is YES copy the + * elements. + */ + (instancetype) orderedSetWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)objects range: (NSRange)range copyItems: (BOOL)flag; + +/** + * Create and return an ordered set with anObject as the sole member. + */ + (instancetype) orderedSetWithObject: (GS_GENERIC_TYPE(ElementT))anObject; + +/** + * Create and return an ordered set with list of arguments starting with + * firstObject and terminated with nil. + */ + (instancetype) orderedSetWithObjects: (GS_GENERIC_TYPE(ElementT))firstObject, ...; + +/** + * Create and return an ordered set using the C array of objects with count. + */ + (instancetype) orderedSetWithObjects: (const GS_GENERIC_TYPE(ElementT)[])objects count: (NSUInteger) count; + +/** + * Create and return an ordered set with the provided ordered set aSet. + */ + (instancetype) orderedSetWithOrderedSet: (GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; + +/** + * Create and return an ordered set with set aSet. + */ + (instancetype) orderedSetWithSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)aSet; + +/** + * Create and return an ordered set with the elements in aSet. If flag is YES, + * copy the elements. + */ + (instancetype) orderedSetWithSet: (GS_GENERIC_CLASS(NSSet, ElementT)*)aSet copyItems: (BOOL)flag; // instance methods +/** + * Initialize and return an empty ordered set with the provided NSArray instance. + */ - (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array; + +/** + * Initialize and return an empty ordered set with the provided NSArray instance. + * If flag is YES copy the elements. + */ - (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array copyItems: (BOOL)flag; + +/** + * Initialize and return an empty ordered set with the provided NSArray instance. + * Use the range to determine which elements to use. If flag is YES copy the + * elements. + */ - (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array range: (NSRange)range copyItems: (BOOL)flag; + +/** + * Initialize and return an ordered set with anObject as the sole member. + */ - (instancetype) initWithObject: (id)object; + +/** + * Initialize and return an ordered set with list of arguments starting with + * firstObject and terminated with nil. + */ - (instancetype) initWithObjects: (GS_GENERIC_TYPE(ElementT))firstObject, ...; - (instancetype) initWithObjects: (const GS_GENERIC_TYPE(ElementT)[])objects count: (NSUInteger)count; + +/** + * Initialize and return an ordered set using the C array of objects with count. + */ - (instancetype) initWithOrderedSet: (GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet; - (instancetype) initWithOrderedSet: (GS_GENERIC_CLASS(NSOrderedSet, ElementT)*)aSet copyItems: (BOOL)flag; From c8c10d0aac07e4bd88fa9509197b2ced63071758 Mon Sep 17 00:00:00 2001 From: Gregory John Casamento Date: Sun, 17 Nov 2024 12:04:24 -0500 Subject: [PATCH 57/64] Add the rest of the ordered set documentation --- Headers/Foundation/NSOrderedSet.h | 361 ++++++++++++++++++++++++++++-- 1 file changed, 338 insertions(+), 23 deletions(-) diff --git a/Headers/Foundation/NSOrderedSet.h b/Headers/Foundation/NSOrderedSet.h index 14936841bc..6244caa66d 100644 --- a/Headers/Foundation/NSOrderedSet.h +++ b/Headers/Foundation/NSOrderedSet.h @@ -46,6 +46,11 @@ extern "C" { @class NSString; @class NSPredicate; +/** + * This class provides an ordered set, a set where the order of the elements matters and + * is preserved. Once created the set cannot be modified. NSMutableOrderedSet can be + * modified. + */ GS_EXPORT_CLASS @interface GS_GENERIC_CLASS(NSOrderedSet, __covariant ElementT) : NSObject Date: Sun, 17 Nov 2024 12:07:20 -0500 Subject: [PATCH 58/64] Add the rest of the ordered set documentation --- Headers/Foundation/NSOrderedSet.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Headers/Foundation/NSOrderedSet.h b/Headers/Foundation/NSOrderedSet.h index 6244caa66d..0230e3a993 100644 --- a/Headers/Foundation/NSOrderedSet.h +++ b/Headers/Foundation/NSOrderedSet.h @@ -491,7 +491,7 @@ GS_EXPORT_CLASS * Replace the object at index with object. */ - (void) replaceObjectAtIndex: (NSUInteger)index - withObject: (GS_GENERIC_TYPE(ElementT))object; + withObject: (GS_GENERIC_TYPE(ElementT))object; /** * Replace objects at indexes with objects. The number of objects must correspond to the number of indexes. From 39e46d214c0a1697054dd70554ea11a4b8496470 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 18 Nov 2024 20:33:37 +0000 Subject: [PATCH 59/64] Remove unecessary graphviz settings --- Tools/AGSHtml.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tools/AGSHtml.m b/Tools/AGSHtml.m index f6ed21f571..3bac1229d3 100644 --- a/Tools/AGSHtml.m +++ b/Tools/AGSHtml.m @@ -2740,7 +2740,7 @@ - (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf [dot appendFormat: @"digraph class_%@ {\n", cNam]; [dot appendString: @" rankdir = \"TB\";\n"]; [dot appendString: @" {\n"]; - [dot appendString: @" node [margin=0 fontcolor=blue" + [dot appendString: @" node [margin=0 " @" fontsize=24 width=0.5 shape=rectangle style=filled]\n"]; if (sNam) { @@ -2750,13 +2750,13 @@ - (void) outputUnit: (GSXMLNode*)node to: (NSMutableString*)buf [dot appendFormat: @" URL=\"%@\"", url]; } [dot appendString: @"]\n"]; - [dot appendFormat: @" %@ [class=figure_class fontcolor=\"green\"]\n", + [dot appendFormat: @" %@ [class=figure_class]\n", cNam]; } else { sNam = cNam; // This is a root class ... - [dot appendFormat: @" %@ [class=figure_root fontcolor=\"green\"]\n", + [dot appendFormat: @" %@ [class=figure_root]\n", cNam]; } if (protocols) From ef0569cd4af61f08de81be7c6e294fda68268ebb Mon Sep 17 00:00:00 2001 From: rfm Date: Tue, 19 Nov 2024 09:20:06 +0000 Subject: [PATCH 60/64] Rename method to better reflect what it actually does. --- Headers/GNUstepBase/NSObject+GNUstepBase.h | 35 +++++++++++----------- Source/Additions/NSObject+GNUstepBase.m | 21 +++++++++---- Source/GSLocale.m | 2 +- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Headers/GNUstepBase/NSObject+GNUstepBase.h b/Headers/GNUstepBase/NSObject+GNUstepBase.h index 649b48b2ed..166c13a105 100644 --- a/Headers/GNUstepBase/NSObject+GNUstepBase.h +++ b/Headers/GNUstepBase/NSObject+GNUstepBase.h @@ -219,16 +219,17 @@ extern "C" { * set to YES).
* Your class then has two options for performing clean-up when the process * ends: - *

1. Use the +leak: at: method to register addresses whose contents are - * to be either ignored or released depending on the clean-up setting in - * force when the program exits. + *

1. Use the +keep:at: method to register static/global variables whose + * contents are to be retained for the lifetime of the program (up to exit) + * and either ignored or released depending on the clean-up setting in force + * when the program exits.
* This mechanism is simple and should be sufficient for many classes. *

- *

2. Implement a +atExit method to be run when the process ends and, - * within your +initialize implementation, call +shouldCleanUp to determine - * whether clean-up should be done, and if it returns YES then call - * +registerAtExit to have your +atExit method called when the process - * terminates. + *

2. Implement an +atExit method to be run when the process ends and, + * within your +initialize implementation, +registerAtExit to have your + * +atExit method called when the process exits. Within the +atExit method + * you may call +shouldCleanUp to determine whether celan up has been + * requested. *

*

The order in which 'leaked' objects are released and +atExit methods * are called on process exist is the reverse of the order in which they @@ -241,23 +242,23 @@ extern "C" { */ + (BOOL) isExiting; -/** This method stored anObject at anAddress (retaining it) and notes - * that the object should persist until the process exits. If clean-up - * is enabled the object should be released (and the address content - * zeroed out) upon process exit. +/** This method stores anObject at anAddress (which should be a static or + * global variable) and retains it. The code notes that the object should + * persist until the process exits. If clean-up is enabled the object will + * be released (and the address content zeroed out) upon process exit. * If this method is called while the process is already exiting it * simply zeros out the memory location then returns nil, otherwise * it returns the object stored at the memory location. - * Raises an exception if anObject is nil or anAddress is NULL (unless - * the process is already exiting). + * Raises an exception if anObject is nil or anAddress is NULL or the old + * value at anAddresss is not nil (unless the process is already exiting). */ -+ (id) leak: (id)anObject at: (id*)anAddress; ++ (id) NS_RETURNS_RETAINED keep: (id)anObject at: (id*)anAddress; -/** DEPRECATED ... use +leak: at: instead. +/** DEPRECATED ... use +keep:at: instead. */ + (id) NS_RETURNS_RETAINED leak: (id)anObject; -/** DEPRECATED ... use +leak: at: instead. +/** DEPRECATED ... use +keep:at: instead. */ + (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress; diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m index b58aa36669..316b6edbcb 100644 --- a/Source/Additions/NSObject+GNUstepBase.m +++ b/Source/Additions/NSObject+GNUstepBase.m @@ -197,7 +197,11 @@ static inline void setup() Method method; IMP msg; -fprintf(stderr, "*** +[%s %s]\n", class_getName(tmp->obj), sel_getName(tmp->sel)); + if (shouldCleanUp) + { + fprintf(stderr, "*** clean-up +[%s %s]\n", + class_getName(tmp->obj), sel_getName(tmp->sel)); + } method = class_getClassMethod(tmp->obj, tmp->sel); msg = method_getImplementation(method); if (0 != msg) @@ -211,12 +215,16 @@ static inline void setup() { if (tmp->obj != *(tmp->at)) { -fprintf(stderr, "*** leaked value %p at %p changed to %p\n", tmp->obj, (const void*)tmp->at, *(tmp->at)); + fprintf(stderr, + "*** clean-up kept value %p at %p changed to %p\n", + tmp->obj, (const void*)tmp->at, *(tmp->at)); tmp->obj = *(tmp->at); } *(tmp->at) = nil; } -fprintf(stderr, "*** -[%s release] %p %p\n", class_getName(object_getClass(tmp->obj)), tmp->obj, (const void*)tmp->at); + fprintf(stderr, "*** clean-up -[%s release] %p %p\n", + class_getName(object_getClass(tmp->obj)), + tmp->obj, (const void*)tmp->at); [tmp->obj release]; } free(tmp); @@ -237,7 +245,7 @@ + (BOOL) isExiting return isExiting; } -+ (id) leak: (id)anObject at: (id*)anAddress ++ (id) keep: (id)anObject at: (id*)anAddress { struct exitLink *l; @@ -253,6 +261,7 @@ + (id) leak: (id)anObject at: (id*)anAddress NSAssert([anObject isKindOfClass: [NSObject class]], NSInvalidArgumentException); NSAssert(anAddress != NULL, NSInvalidArgumentException); + NSAssert(*anAddress == nil, NSInvalidArgumentException); setup(); [exitLock lock]; for (l = exited; l != NULL; l = l->next) @@ -520,9 +529,9 @@ - (NSUInteger) sizeOfInstance /* Dummy implementation */ -@implementation NSObject(GSCleanup) +@implementation NSObject(GSCleanUp) -+ (id) leak: (id)anObject at: (id*)anAddress ++ (id) keep: (id)anObject at: (id*)anAddress { ASSIGN(*anAddress, anObject); return *anAddress; diff --git a/Source/GSLocale.m b/Source/GSLocale.m index 0868e6f1c0..00be5e93fd 100644 --- a/Source/GSLocale.m +++ b/Source/GSLocale.m @@ -223,7 +223,7 @@ */ if (saved == nil) { - [NSObject leak: AUTORELEASE([dict copy]) at: &saved]; + [NSObject keep: AUTORELEASE([dict copy]) at: &saved]; } /** From 6f02b87ae1f90b2bbf09d057c5c4e342821c94b0 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 18 Nov 2024 09:26:25 +0000 Subject: [PATCH 61/64] Fix compiler warnings about variable size --- Tests/base/NSURLSession/Helpers/HTTPServer.m | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Tests/base/NSURLSession/Helpers/HTTPServer.m b/Tests/base/NSURLSession/Helpers/HTTPServer.m index cbc963bee9..b69604efa1 100644 --- a/Tests/base/NSURLSession/Helpers/HTTPServer.m +++ b/Tests/base/NSURLSession/Helpers/HTTPServer.m @@ -164,8 +164,9 @@ @implementation HTTPServer _routes = [routes copy]; - struct sockaddr_in serverAddr; - NSUInteger addrLen = sizeof(struct sockaddr_in); + struct sockaddr_in serverAddr; + socklen_t addrLen = sizeof(struct sockaddr_in); + serverAddr.sin_family = AF_INET; serverAddr.sin_port = NSSwapHostShortToBig(port); serverAddr.sin_addr.s_addr = INADDR_ANY; @@ -208,12 +209,12 @@ @implementation HTTPServer return self; } -- (void)acceptConnection +- (void) acceptConnection { - struct sockaddr_in clientAddr; - dispatch_source_t clientSource; - NSUInteger sin_size; - int clientSocket; + struct sockaddr_in clientAddr; + dispatch_source_t clientSource; + socklen_t sin_size; + int clientSocket; sin_size = sizeof(struct sockaddr_in); clientSocket = accept(_socket, (struct sockaddr *) &clientAddr, &sin_size); From 077e4646ab657d25d463bca29060672d2e727ac6 Mon Sep 17 00:00:00 2001 From: rfm Date: Tue, 19 Nov 2024 10:58:37 +0000 Subject: [PATCH 62/64] Fix reference cycle in absolute time zone and its detail --- Source/NSTimeZone.m | 77 ++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/Source/NSTimeZone.m b/Source/NSTimeZone.m index 3cccab85e8..65d46a21cd 100644 --- a/Source/NSTimeZone.m +++ b/Source/NSTimeZone.m @@ -317,7 +317,6 @@ @interface GSAbsTimeZone : NSTimeZone { @public NSString *name; - id detail; int offset; // Offset from UTC in seconds. } @@ -654,7 +653,6 @@ - (void) dealloc GS_MUTEX_UNLOCK(zone_mutex); } RELEASE(name); - RELEASE(detail); DEALLOC; } @@ -696,60 +694,53 @@ - (id) initWithOffset: (NSInteger)anOffset name: (NSString*)aName } anOffset *= sign; + GS_MUTEX_LOCK(zone_mutex); if (anOffset % 900 == 0) { z = commonAbsolutes[anOffset/900 + 72]; - if (z != nil) - { - IF_NO_ARC(RETAIN(z);) - DESTROY(self); - return z; - } } - - GS_MUTEX_LOCK(zone_mutex); - z = (GSAbsTimeZone*)NSMapGet(absolutes, (void*)(uintptr_t)anOffset); - if (z != nil) + else + { + z = (GSAbsTimeZone*)NSMapGet(absolutes, (void*)(uintptr_t)anOffset); + } + if (z) { IF_NO_ARC(RETAIN(z);) DESTROY(self); + return z; } - else + if (aName == nil) { - if (aName == nil) + if (anOffset % 60 == 0) { - if (anOffset % 60 == 0) - { - char s = (anOffset >= 0) ? '+' : '-'; - unsigned i = (anOffset >= 0) ? anOffset / 60 : -anOffset / 60; - unsigned h = (i / 60) % 24; - unsigned m = i % 60; - char buf[9]; - - snprintf(buf, sizeof(buf), "GMT%c%02u%02u", s, h, m); - name = [[NSString alloc] initWithUTF8String: buf]; - } - else - { - /* - * Should never happen now we round to the minute - * for MacOS-X compatibnility. - */ - name = [[NSString alloc] - initWithFormat: @"NSAbsoluteTimeZone:%"PRIdPTR, anOffset]; - } + char s = (anOffset >= 0) ? '+' : '-'; + unsigned i = (anOffset >= 0) ? anOffset / 60 : -anOffset / 60; + unsigned h = (i / 60) % 24; + unsigned m = i % 60; + char buf[9]; + + snprintf(buf, sizeof(buf), "GMT%c%02u%02u", s, h, m); + name = [[NSString alloc] initWithUTF8String: buf]; } else { - name = [aName copy]; + /* + * Should never happen now we round to the minute + * for MacOS-X compatibnility. + */ + name = [[NSString alloc] + initWithFormat: @"NSAbsoluteTimeZone:%"PRIdPTR, anOffset]; } - detail = [[GSAbsTimeZoneDetail alloc] initWithTimeZone: self]; - offset = anOffset; - z = self; - NSMapInsert(absolutes, (void*)(uintptr_t)anOffset, (void*)z); - [zoneDictionary setObject: self forKey: (NSString*)name]; - RELEASE(self); } + else + { + name = [aName copy]; + } + z = self; + offset = anOffset; + NSMapInsert(absolutes, (void*)(uintptr_t)anOffset, (void*)z); + [zoneDictionary setObject: z forKey: name]; + if (anOffset % 900 == 0) { int index = anOffset/900 + 72; @@ -780,12 +771,12 @@ - (NSInteger) secondsFromGMTForDate: (NSDate*)aDate - (NSArray*) timeZoneDetailArray { - return [NSArray arrayWithObject: detail]; + return [NSArray arrayWithObject: [self timeZoneDetailForDate: nil]]; } - (NSTimeZoneDetail*) timeZoneDetailForDate: (NSDate*)date { - return detail; + return AUTORELEASE([[GSAbsTimeZoneDetail alloc] initWithTimeZone: self]); } - (NSString*) timeZoneName From 0243b4efecbe14e9f2916fbefe77e8d40582be2f Mon Sep 17 00:00:00 2001 From: rfm Date: Tue, 19 Nov 2024 11:06:26 +0000 Subject: [PATCH 63/64] Revert unnecessary change --- Headers/GNUstepBase/GSIArray.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Headers/GNUstepBase/GSIArray.h b/Headers/GNUstepBase/GSIArray.h index bdf883d51b..b11edc90a9 100644 --- a/Headers/GNUstepBase/GSIArray.h +++ b/Headers/GNUstepBase/GSIArray.h @@ -574,16 +574,13 @@ GSIArrayRemoveItemsFromIndex(GSIArray array, unsigned index) GS_STATIC_INLINE void GSIArrayRemoveAllItems(GSIArray array) { - if (array->count) - { #ifndef GSI_ARRAY_NO_RELEASE - while (array->count--) - { - GSI_ARRAY_RELEASE(array, array->ptr[array->count]); - } -#endif - array->count = 0; + while (array->count--) + { + GSI_ARRAY_RELEASE(array, array->ptr[array->count]); } +#endif + array->count = 0; } GS_STATIC_INLINE void From e7e7051acdfb2123a0c704048ceca71f32f406a5 Mon Sep 17 00:00:00 2001 From: rfm Date: Tue, 19 Nov 2024 12:27:56 +0000 Subject: [PATCH 64/64] Document changes --- ChangeLog | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6557b728da..6a3916e1aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2024-11-19 Richard Frith-Macdonald + + * GSMime: fixed buffer overrun in rare circumstances when decoding + an encoded word in a header. + fix to cope with dealloc of uninitialised instances of GSMimeSMTPClient + * GSTLS: clean up used resources on exit + * NSCharacterSet: Fix retain count of cached character sets + * NSDateFormatter: fix to cope with dealloc of uninitialised instances + * NSFileManager: fix leak of enumerator when enumerating files at + a directory specified by URL + * NSHTTPCookie: fix buffer overrun parsing cookie header fields + * NSInvocation: fix leak of type information memory when passing + general struct argument/return values + * NSNumberFormatter: fix to cope with dealloc of uninitialised instances + * NSOperation: fix to cope with dealloc of uninitialised instances + * NSPredicate: fix leaks of keypath and set expressions + also fix leak of objects if exception occurs while scanning predicate + string + * NSPropertyList: fix leaks if exception occurs while parsing + * NSRegularExpression: fix leaks if exception occurs while parsing + * NSString: fix lead in dataUsingEncoding:allowLossyConversion: + * NSTimeZone: fix retain cycle in absolute time zones + fix leak of ICU calendar in -localizedName:locale: + * NSURL: fix leaks when initialising with unparseable string etc + * Testcases: fix many leaks so that most tests run to completion + without any leaked memory. + 2024-11-14 Richard Frith-Macdonald * Source/NSBundle.m: Restructure a bit to expose resource lookup